IValueConverter with bound dependency properties

I need to determine the StringFormat some associated TextBlocks at runtime based on the unit system identified in the object that should be connected.

I have a converter with the Dependency property that I would like to bind to. The Bound value is used to determine the conversion process.

 public class UnitConverter : DependencyObject, IValueConverter { public static readonly DependencyProperty IsMetricProperty = DependencyProperty.Register("IsMetric", typeof(bool), typeof(UnitConverter), new PropertyMetadata(true, ValueChanged)); private static void ValueChanged(DependencyObject source, DependencyPropertyChangedEventArgs e) { ((UnitConverter)source).IsMetric = (bool)e.NewValue; } public bool IsMetric { get { return (bool)this.GetValue(IsMetricProperty); } set { this.SetValue(IsMetricProperty, value); } } object IValueConverter.Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { if (IsMetric) return string.Format("{0:0.0}", value); else return string.Format("{0:0.000}", value); } object IValueConverter.ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } } 

Declare Converter

 <my:UnitConverter x:Key="Units" IsMetric="{Binding Path=IsMetric}"/> 

and bind TextBlock

 <TextBlock Text="{Binding Path=Breadth, Converter={StaticResource Units}}" Style="{StaticResource Values}"/> 

However, I get the following error:

System.Windows.Data error: 2: Cannot find the FrameworkElement or FrameworkContentElement control for the target element. BindingExpression: Path = IsMetric; DataItem = NULL; target element - "UnitConverter" (HashCode = 62641008); target - isMetric (type "Boolean")

I assume this is initialization before I set the datacontext, and therefore I don't need to bind the IsMetric property. How can I achieve the desired result?

+8
c # data-binding wpf ivalueconverter
source share
1 answer

Provided that Breadth and IsMetric are properties of the same data object, you can use MultiBinding in combination with a multi-valued converter :

 <TextBlock> <TextBlock.Text> <MultiBinding Converter="{StaticResource UnitMultiValueConverter}"> <Binding Path="Breadth" /> <Binding Path="IsMetric" /> </MultiBinding> </TextBlock.Text> </TextBlock> 

with such a converter:

 public class UnitMultiValueConverter : IMultiValueConverter { public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) { double value = (double)values[0]; bool isMetric = (bool)values[1]; string format = isMetric ? "{0:0.0}" : "{0:0.000}"; return string.Format(format, value); } public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) { throw new NotImplementedException(); } } 

The problem with your approach is that when UnitConverter is declared as a resource, it does not have a DataContext, and it will never receive it later.

And one more important thing: ValueChanged for UnitConverter.IsMetric is nonsense. It again sets the same property, which was just changed.

+6
source share

All Articles