2016-06-28 13 views
0

Ich möchte das Verhalten einer RangeSlider modellieren, mit einer Klasse RangeSliderModel mit Eigenschaften beschreiben die Größen (Breiten) für eine bestimmte Reihe von Werten.DependencyProperty und DataBinding - Warum wird Property Setter nicht aufgerufen, wenn UserControl geladen wird?

Dann Ich habe ein Usercontrol in dem die Position und Größe von einigen Rechtecke sollten diese Eigenschaften, und einige Fälle von Thumb, aus denen die DragDelta Ereignisse verwendet werden, repräsentieren diese Rechtecke, um die Größe und die Berechnung eines neuen Wertes für eine RangeSliderModel ermöglichen .

Endlich hat dieses Usercontrol ein DependencyProperty vom Typ RangeSliderModel:

public RangeSliderModel Model 
    { 
     get 
     { 
      return (RangeSliderModel)GetValue(RangeSliderModelProperty); 
      // or instead calculate a RangeSliderModel from children sizes. 
     } 
     set 
     { 
      // this IS NOT called when UserControl loads 
      SetValue(RangeSliderModelProperty, value); 
      // here I could take the value and calculate new sizes for the children. 
     } 
    } 

    public static readonly DependencyProperty RangeSliderModelProperty = 
     DependencyProperty.Register("RangeSliderModel", 
            typeof(RangeSliderModel), 
            typeof(MyUserControl), 
            new PropertyMetadata(ModelPropertyChanged)); 

    private static void ModelPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     // this IS called when UserControl loads. 
     RangeSliderModel model = e.NewValue as RangeSliderModel; 
    } 

Ich erwartete die SetValue und GetValue Eigenschaften außer Kraft zu setzen, aber selbst wenn ich binden diese DependencyProperty an eine entsprechende Quelle in Ansichtsmodell, der Setter wird nie genannt! Und ich kann nicht verstehen, warum PropertyChangedHandler stattdessen aufgerufen wird, und viel weniger, was ich mit diesen Informationen tun sollte - ich erwartete, nur GetValue und SetValue auf eine Art zu verwenden, die einem ValueConverter ähnlich ist.

+0

In Ihrem ModelPropertyChanged-Handler sollte der Code meinObject.Model = e.NewValue als RangeSliderModel sein. – user2880486

Antwort

1

Abhängigkeitseigenschaften funktionieren nicht auf diese Weise, wenn Sie sie über Bindungen festlegen. DependencyObject.SetCurrentValuewird genannt. Die Bindung ruft (im Wesentlichen):

yourObject.SetCurrentValue(YourClassName.RangeSliderModelProperty, someValue); 

Also, ja, SetCurrentValue vs SetValue. SetValue überschreibt alle Bindungen der Abhängigkeitseigenschaft; SetCurrentValue wird nicht. IIRC Dies hat mit der Art und Weise zu tun, wie Style-Trigger in XAML die durch Attribute gesetzten Werte nicht überschreiben können. Es ist nicht direkt relevant für das, was Sie hier tun, zum Glück.

Die Quintessenz ist, dass Ihre ModelPropertyChanged Handler ist, wo Sie Code, der aufgerufen werden muss, wenn der Wert ändert. Abhängigkeitseigenschaften und reguläre .NET CLR-Eigenschaften sind zwei unabhängige Mechanismen.

Ich hatte Abhängigkeitseigenschaften korrekt in XAML binden, wenn ich die öffentliche Eigenschaft vollständig ausließ; Ich habe es gerade noch einmal getestet und festgestellt, dass dies bei meinem Testbeispiel der Fall ist. In Kommentaren erwähnst du, dass du das bei deinem Code nicht gefunden hast, also muss ich noch etwas mehr lesen.

Wenn Sie Subklassen müssen Änderungen haben reagieren, können Sie entweder eine virtuelle Methode schreiben sie außer Kraft setzen können, und nennen Sie es in ModelPropertyChanged oder auch ein ModelChanged Ereignis schreiben, und das in ModelPropertyChanged erhöhen.

Sie konnte einen ValueChanged Handler über ein DependencyPropertyDescriptor hinzufügen, aber es würde nachbarschaftliche von Ihnen Recht, ihnen die Mühe, googeln, wie man das ersparen, indem eine virtuelle Methode oder Ereignis zu schreiben.

+0

Gut, ich habe begonnen, SetValue direkt anstelle des normalen Setter zu verwenden, und das hat gut funktioniert. Auf der anderen Seite hat das Löschen des regulären Setter/Getter die XAML-Bindung zerstört (ich vermute, dass es den gegebenen Eigenschaftsnamen erwartet hat), also lasse ich es. Jetzt funktioniert alles wie erwartet, danke! – heltonbiker

+0

@heltonbiker Hmm! Lass mich das testen und sicherstellen, dass ich keinen Unsinn spucke. Vielen Dank! –

+0

Eigentlich ruft es 'SetValue' nicht auf, es ruft' SetBinding' auf. –

Verwandte Themen