In a C# Wpf application I have an XML Binded datasource.
I want to update some xml like this:
loop.Innerxml = "false"
This value is binded (as a boolean) to a control. However when doing this, a formatexception comes up saying that a string is not a valid boolean (logical). However if the false is not entered as a string, I can't update the innerxml...
Any advice?
You can use a Converter to convert your Strings to Booleans when the binding happens.
For more about converters, see http://www.scip.be/index.php?Page=ArticlesNET22&Lang=EN.
Code sample:
[ValueConversion(typeof(string), typeof(bool))]
public class StringToBoolConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return TypeDescriptor.GetConverter(typeof(bool)).ConvertFrom(value);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotSupportedException();
}
}
Related
I have a funny problem with Binding,I have a DataTemplate that contain a Button,and the DataTemplate had been placed in a Window(specView),i need to bind the Button.Command to a Commnad inside window's viewmodel,so i do this:
Command="{Binding DataContext.NewOfferNoCommand,ElementName=specView}"/>
but it doesn't get bound until i make a Converter that return the value:
public class ReturnValueConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return value;
}
}
I really can't understand what the problem is?any idia?
You need to set the relative source in order for the binding to work.
{Binding DataContext.NewOfferNoCommand, RelativeSource={RelativeSource TemplatedParent}}
I added a custom control library to my project and in that control there is an array DependencyProperty. Now when I try to bind that property in the client I get:
Tags of type 'PropertyArrayStart' are not supported in template sections.
The message is self explanatory but how do you set array properties in a DataTemplate?
You can use a IMultiValueConverter to build an array from multiple bindings. A converter is only required as you cannot use a MultiBinding without one.
public class MultipleValuesToArrayConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
return values.ToArray();
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
I use to bind a bool variable of a class to a IsChecked property of Checkbox. What i want to do is to bind 'NOT' of the original value, like IsChecked = Binding Not(IsSelected), please let me know how this can be done.
Thanks
You need to use a Convertor. A convertor class implements IValueConverter and can convert the binding value into something else, in your case, negate it. You can do it like this:
public class BoolInverseConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is bool)
return !(bool)value;
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
I use a Ivalueconverter to convert a string to a boolean using an xml datasource. This works fine until I manually change the xml like so:
myelement.InnerXml = "true"
I then receive a formatexception saying the string is not a valid boolean, I check the value that goes in to my converter and it is equal to ""
Here is my converter:
[ValueConversion(typeof(string), typeof(bool))]
public class StringToBoolConverter : IValueConverter {
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
return TypeDescriptor.GetConverter(typeof(bool)).ConvertFrom(value); }
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
return value.ToString();
}
}
I bind the converter like so:
<local:StringToBoolConverter x:Key="stringbool"></local:StringToBoolConverter>
And apply it in the binding:
IsChecked="{Binding Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, XPath=myelement, Converter={StaticResource stringbool}}"
I'm not sure, but if you use "XPath=myelement", the string should be
myCheckBox.DataContext="<myelement>true</myelement>";
What is the difference between using a Converter (IValueConverter) and passing in other values as parameters (ConverterParameter) vs using a MultiConverter (IMultiValueConverter) and just passing in multiple converter values?
There are two main differences. One is that ConverterParameter is not a Binding and does not listen for property changes, so the Binding won't refresh automatically if the value changes.
The other difference is that the ConverterParameter is an input to both Convert and ConvertBack, while all of the Bindings in a MultiBinding are inputs to Convert and outputs of ConvertBack. For example, if you are converting from DateTime to string, you might have the ConverterParameter be a format string, since that affects the conversion in both directions:
public class DateTimeConverter
: IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return ((DateTime)value).ToString((string)parameter, null);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return DateTime.ParseExact((string)value, (string)parameter, null);
}
}
On the other hand, if you want to convert from two doubles to a Size, then you would want to return two doubles when converting back:
public class SizeConverter
: IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
return new Size((double)values[0], (double)values[1]);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
var size = (Size)value;
return new object[] { size.Width, size.Height };
}
}