I need to determine the StringFormat
of some bound TextBlocks
at runtime based on the unit system identified in the object to be bound.
I Have a converter with a Dependency Property that I would like to Bind to. The Bound value is used in determining 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();
}
}
I declare the converter
<my:UnitConverter x:Key="Units" IsMetric="{Binding Path=IsMetric}"/>
and bind the TextBlock
<TextBlock Text="{Binding Path=Breadth, Converter={StaticResource Units}}" Style="{StaticResource Values}"/>
Never the less, I get the following error:
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=IsMetric; DataItem=null; target element is 'UnitConverter' (HashCode=62641008); target property is 'IsMetric' (type 'Boolean')
I guess this is initialising before I set the datacontext and therefore there is nothing to bind the IsMetric
property to. How can I achieve the desired result?
Provided that Breadth
and IsMetric
are properties of the same data object, you might use a MultiBinding in conjunction with a multi value converter:
<TextBlock>
<TextBlock.Text>
<MultiBinding Converter="{StaticResource UnitMultiValueConverter}">
<Binding Path="Breadth" />
<Binding Path="IsMetric" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
with a converter like this:
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 the UnitConverter is declared as resource it does not have a DataContext, and it will never get one later on.
And one more important thing: the ValueChanged
callback for UnitConverter.IsMetric
is nonsense. It sets the same property again which was just changed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With