2009-08-18 5 views
1

WPF XAML, ich habe ein benutzerdefiniertes Steuerelement, das ich geschrieben habe, das Suchvorgänge umschließt. In der typischen Regierungsweise haben sie eine Nachschlagetabelle für alle möglichen Nachschlagewerke. Mein benutzerdefiniertes Steuerelement wirft ein Popup-Overlay, in dem Sie aufgefordert werden, eines der Elemente in der Liste auszuwählen. Meine Probleme beziehen sich speziell auf die Datenbindung von meinem aufrufenden Formular an meine Steuerelementeigenschaft an meine zugrunde liegende Steuerungs-VM.WPF-Steuerelementeigenschaft, die keine Datenbindung empfängt

Ich rufe die Steuerung wie folgt aus:

<Controls:LookupSelector SelectedLookupValueId="{Binding Path=DataContext.SelectedHarvestMethod, ElementName=SurveyFormWindow, Mode=TwoWay}" /> 

(andere Spam entfernt wurde) In diesem Fall wird die explizite Datacontext ist erforderlich, weil die tatsächliche Datacontext der Kontrolle seiner eigenen Ansicht Modell ist. SelectedHarvestMethod ist eine Eigenschaft auf dem Formular ViewModel.

Es funktioniert im "New Form" -Modus, in dem das Steuerelement für das Festlegen seines eigenen Werts zuständig ist (das Steuerelement enthält eine Schaltfläche, die beim Klicken ein Popup anzeigt und Sie den gewünschten Wert der Suchdaten auswählen) . Das funktioniert gut, wie ich schon sagte, es bindet sogar zurück an die "SelectedHarvestMethod" im obigen Code. Ich kann diese Geldstrafe verwenden und bin sicher, dass mein ViewModel immer die ausgewählte ID dieser Eigenschaft zugewiesen hat.

Aber jetzt mache ich den "Edit Existing Form" -Modus, wo ich Daten aus der Datenbank zurückladen und die Eigenschaften im Ansichtsmodell festlegen. Also setze ich 'SelectedHarvestMethod' und dieser Code funktioniert gut (Haltepunkttreffer in Setter), aber der resultierende Setter auf 'SelectedLookupValueId' wird nicht aufgerufen - der Wert geht nie durch.

‚SelectedLookupValueId‘ ist ein DP auf der View-Modell Kontrolle:

public static readonly DependencyProperty SelectedLookupValueIdProperty = 

    DependencyProperty.Register("SelectedLookupValueId", typeof(int), typeof(LookupSelector), new UIPropertyMetadata(0)); 

    public int SelectedLookupValueId 
    { 

     get { return (int) GetValue(SelectedLookupValueIdProperty); } 

     set { SetValue(SelectedLookupValueIdProperty, value); ViewModel.SetPreSelectedLookupValueId(value); } 

    } 

gibt es keine Fehler im Ausgabefenster oder Ereignisprotokoll oder auf der Unterseite meines Schuhs geschrieben. Debug-Konverter eingefügt zeigt, dass der Integer-Wert eindeutig zugewiesen ist. Wie im Kommentar erwähnt, implementiert die VM natürlich INotifyPropertyChanged und löst das Ereignis korrekt aus.

Auch der tatsächliche Typ ist "Benutzerkontrolle", nicht benutzerdefinierte Steuerung: Es hat XAML beteiligt.

Warum wird nicht die Eigenschaft Setter für meine Kontrolle aufgerufen?

+0

Ich sollte hinzufügen, dass ich INotifyPropertyChanged auf dem ViewModel implementieren und das Ereignis zurückgeben, wenn die VM-Eigenschaft festgelegt ist. Wie auch immer, hoffentlich war das für Sie bereits offensichtlich, da ich anzeigte, dass der DebugConverter getroffen wurde. – DarkwingDuck

Antwort

15

Warum wird nicht die Eigenschaft Setter für meine Kontrolle aufgerufen?

Ich gestehe, ich habe Ihre ganze Frage nicht gelesen - es ist zu lang;) Sind Sie jedoch sicher, dass die Bindung fehlschlägt? Wissen Sie, dass WPF den Zugriff auf Abhängigkeitseigenschaften optimiert, sodass die Getter und Setter Ihres CLR-Wrappers nicht aufgerufen werden. Stattdessen ruft es DependencyObject.GetValue und DependencyObject.SetValue direkt auf und übergibt die entsprechende DependencyProperty Instanz.

Daher können Sie für Ihre CLR-Eigenschaft keinen Haltepunkt festlegen, um zu bestimmen, ob der D-Prop geändert wird. Geben Sie stattdessen einen Änderungshandler in den Metadaten für den d-prop an. Legen Sie dann in diesem Handler einen Haltepunkt fest. Sie können auch Tools wie Snoop verwenden, um dies zu sehen.

Übrigens, das ist der Grund, warum Ihre CLR-Wrapper-Eigenschaft nie mehr tun sollte als GetValue und SetValue aufrufen. Es besteht nur aus praktischen Gründen und jede zusätzliche Logik, die Sie mit der Eigenschaft packen, kann nicht garantiert ausgeführt werden.

+1

+1 Auch wenn dies in diesem speziellen Fall nicht das Problem ist, besteht eine gute Chance, dass sich jemand diese Frage in Zukunft ansehen wird. –

+3

+1 Dies war das Problem. Ich hakte mich stattdessen in den Rückruf ein. Ich konnte dies mit einem ähnlichen Code wie in diesem Artikel tun: http://blogs.msdn.com/llobo/archive/2007/03/05/listening-to-dependencyproperty-changes.aspx – DarkwingDuck

+0

Randnotiz: Wenn die Namenszeichenfolge, die Sie an DependencyProperty.Register übergeben, sich von den CLR-Eigenschaftsnamen unterscheidet, ruft das DP-System _will_ den GetValue- und SetValue-Wert auf (und verhält sich andernfalls immer noch als DP). Der benutzerdefinierte Rückruf ist ein viel besseres Design, aber dieser Hack ist nützlich, wenn Sie angehängte Auflistungseigenschaften erstellen möchten. –