2012-04-02 8 views
8

Necesito determinar el StringFormat de algún límite TextBlocks en tiempo de ejecución basado en el sistema de unidad identificado en el objeto a vincular.IValueConverter con Bound Dependency Properties

Tengo un convertidor con una Propiedad de dependencia al cual me gustaría vincularme. El valor Bound se usa para determinar el proceso de conversión.

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(); 
    } 
} 

declaro el convertidor

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

y obligar a la TextBlock

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

Nunca menos, me sale el siguiente error:

System.Windows.Data de error: 2: No se puede encontrar FrameworkElemento o FrameworkContentElement para el elemento de destino. BindingExpression: Path = IsMetric; DataItem = null; el elemento objetivo es 'UnitConverter' (HashCode = 62641008); target property is 'IsMetric' (tipo 'Boolean')

Supongo que esto se inicializa antes de configurar el contexto de datos y, por lo tanto, no hay nada para enlazar la propiedad IsMetric. ¿Cómo puedo lograr el resultado deseado?

Respuesta

6

Siempre que Breadth y IsMetric son propiedades del mismo objeto de datos, es posible utilizar un MultiBinding en conjunción con un multi value converter:

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

con un convertidor de la siguiente manera:

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(); 
    } 
} 

El problema con su enfoque es que cuando UnitConverter se declara como recurso no tiene un DataContext, y nunca lo obtendrá.

Y una cosa más importante: la devolución de llamada ValueChanged para UnitConverter.IsMetric es una tontería. Establece la misma propiedad de nuevo, que acaba de cambiar.

+0

Quería evitar esto ya que tengo cientos de TextBlocks y no quería tener que pasar por ellos y modificarlos todos. –

+0

Gracias, hombre. Sí, me di cuenta de que solo estaba estableciendo la misma propiedad, ¡bueno si alguna vez se llamara así! El MultiBinding funciona bien sin embargo –