2012-04-02 2 views
8

Ich muss zur Laufzeit StringFormat eines gebundenen TextBlocks basierend auf dem Einheitensystem ermitteln, das im zu bindenden Objekt identifiziert wird.IValueConverter mit gebundenen Abhängigkeitseigenschaften

Ich habe einen Konverter mit einer Dependency-Eigenschaft, an die ich gerne binden würde. Der gebundene Wert wird beim Festlegen des Konvertierungsprozesses verwendet.

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

Ich erkläre die Konverter

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

und binden das TextBlock-

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

Nie weniger, bekomme ich folgende Fehlermeldung:

System.Windows.Data Fehler: 2: Das FrameworkElement oder FrameworkContentElement für das Zielelement kann nicht gefunden werden. BindingExpression: Pfad = IsMetric; Datenelement = null; Zielelement ist 'UnitConverter' (HashCode = 62641008); Zieleigenschaft ist 'IsMetric' (Typ 'Boolean')

Ich denke, das wird initialisiert, bevor ich den Datenkontext festlegen und daher gibt es nichts, das die Eigenschaft IsMetric zu binden. Wie kann ich das gewünschte Ergebnis erzielen?

Antwort

6

Sofern Breadth und IsMetric sind Eigenschaften des gleichen Datenobjekt, können Sie eine MultiBinding in Verbindung mit einem multi value converter verwenden:

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

mit einem Konverter wie folgt aus:

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

Das Problem Ihr Ansatz sieht vor, dass der UnitConverter, wenn er als Ressource deklariert ist, keinen DataContext hat und später nie einen bekommt.

Und noch eine wichtige Sache: dieRückruf für UnitConverter.IsMetric ist Unsinn. Es setzt dieselbe Eigenschaft wieder, die gerade geändert wurde.

+0

Ich wollte dies vermeiden, da ich Hunderte von TextBlocks habe und ich nicht alle durchlaufen und verändern wollte. –

+0

Danke Mann, ja, ich erkannte, dass ich nur die gleiche Eigenschaft gesetzt hatte, nun, wenn es jemals so heißt! Das MultiBinding funktioniert jedoch großartig –