2016-08-26 4 views
2

In meinem WPF-Anwendung habe ich ein Label, das sich auf die Länge eines Text-Eigenschaft gebunden ist:Abbrechen Bindung je nach Objekttyp

entweder
<Label Content="{Binding Editor.Text.Length}"/> 

Der Editor-Objekt ein Textfeld oder eine Checkbox sein kann. Das Textfeld hat eine Text-Eigenschaft, das Kontrollkästchen dagegen nicht.
Wenn das Etikett auf einen „Checkbox-Editor“ gebunden ist, erzeugt es eine Warnung in Visual Studio:

BindingExpression path error: 'Text' property not found on 'object'...

Dies ist zu erwarten, und ich würde gerne wissen, ob es eine Möglichkeit ist, die Bindungsmodul zu sagen, nicht zu Versuchen Sie, diesen Wert zu binden, es sei denn, das Editor-Objekt ist ein Textfeld?

Antwort

2

Ist die Editor Eigenschaft Ihres Viewmodels ein Steuerelement? Ich hoffe nicht, aber trotzdem.

Sie könnten einen Wertkonverter schreiben, der den Typ des Werts zurückgibt, und dann den Inhalt des Labels über eine Reihe von Triggern in einem Style festlegen. Wenn der Typ des Editors {x:Type TextBox} ist, legen Sie ihn auf die Bindung fest, die Sie oben haben. Wenn es {x:Type CheckBox} ist, mach es `{Binding Editor.IsChecked} '.

XAML

<Label> 
    <Label.Style> 
     <Style TargetType="Label" BasedOn="{StaticResource {x:Type Label}}"> 
      <Style.Triggers> 
       <DataTrigger 
        Binding="{Binding ElementName=Editor, Converter={local:GetTypeConverter}}" 
        Value="{x:Type TextBox}" 
        > 
        <Setter 
         Property="Content" 
         Value="{Binding Text.Length, ElementName=Editor}" 
         /> 
       </DataTrigger> 
       <DataTrigger 
        Binding="{Binding ElementName=Editor, Converter={local:GetTypeConverter}}" 
        Value="{x:Type CheckBox}" 
        > 
        <Setter 
         Property="Content" 
         Value="{Binding IsChecked, ElementName=Editor}" 
         /> 
       </DataTrigger> 
      </Style.Triggers> 
     </Style> 
    </Label.Style> 
</Label> 

C#

public class GetTypeConverter : MarkupExtension, IValueConverter 
{ 
    public override object ProvideValue(IServiceProvider serviceProvider) 
    { 
     return this; 
    } 

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     return value?.GetType(); 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 

Alternativ Ihre Ansichtsmodell könnte ein Nur-Lese-Eigenschaft haben, die zurückgibt, was in diesem Label sein sollte, da die Viewmodel Editor hat und weiß, was es ist. Nennen Sie es vorerst EditorLabelValue. Vermutlich ist Editor an eine string Eigenschaft oder eine bool Eigenschaft gebunden, je nachdem welcher Editor es ist. Also würden beide diese Setzer PropertyChanged für "EditorLabelValue" erhöhen, was den entsprechenden Wert zurückgeben würde.

Ich habe versucht, dies in reiner XAML zu tun, indem Editor die Content ein ContentControl machte und dann mit Datatemplates zu spielen, aber ich konnte nicht einen Weg finden, für Neuzuordnung Editor, dass die Arbeit zu machen, ohne eine Ausnahme zu bekommen.

+0

Schöner Trick mit 'ContentControl'! – Sam

+0

@Sam Wenn es nur funktioniert! Siehe mein Update. –

+0

Ja, es war zu cool, um wahr zu sein ... – Sam