DependencyProperty della proprietà Twoway-bind view per viewmodel?

Diverse fonti sulla rete ci dicono che, in MVVM , la comunicazione / sincronizzazione tra viste e viewmodels dovrebbe avvenire attraverso le proprietà di dipendenza. Se ho capito bene, una proprietà di dipendenza della vista dovrebbe essere associata a una proprietà di viewmodel usando l’associazione bidirezionale. Ora, domande simili sono state poste prima, ma senza una risposta sufficiente.

Prima di iniziare ad analizzare questo problema piuttosto complesso, ecco la mia domanda:

Come posso sincronizzare DependencyProperty di una vista personalizzata con una proprietà di viewmodel?

In un mondo ideale, lo si legherebbe semplicemente in questo modo:

  

Ciò non funziona poiché MyProperty non è un membro di UserControl . Doh! Ho provato approcci diversi, ma nessuno ha avuto successo.

Una soluzione consiste nel definire una class base, UserControlEx , con le proprietà di dipendenza necessarie per far funzionare quanto sopra. Tuttavia, questo diventa presto estremamente disordinato. Non buono abbastanza!

Uso Caliburn.Micro per separare ViewModel dalla vista. Tuttavia, potrebbe funzionare allo stesso modo in MVVM. Immagino che MVVM imposta la proprietà DataContext della vista anche DataContext di ViewModel.

VISTA

 // in the class of the view: MyView public string ViewModelString // the property which stays in sync with VM's property { get { return (string)GetValue(ViewModelStringProperty); } set { var oldValue = (string) GetValue(ViewModelStringProperty); if (oldValue != value) SetValue(ViewModelStringProperty, value); } } public static readonly DependencyProperty ViewModelStringProperty = DependencyProperty.Register( "ViewModelString", typeof(string), typeof(MyView), new PropertyMetadata(OnStringValueChanged) ); private static void OnStringValueChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) { // do some custom stuff, if needed // if not, just pass null instead of a delegate } public MyView() { InitializeComponent(); // This is the binding, which binds the property of the VM // to your dep. property. // My convention is give my property wrapper in the view the same // name as the property in the VM has. var nameOfPropertyInVm = "ViewModelString" var binding = new Binding(nameOfPropertyInVm) { Mode = BindingMode.TwoWay }; this.SetBinding(SearchStringProperty, binding); } 

VM

 // in the class of the ViewModel: MyViewModel public string ViewModelStringProperty { get; set; } 

Nota che questo tipo di implementazione non ha completamente implementazione dell’interfaccia INotifyPropertyChanged . Dovresti aggiornare questo codice correttamente.

Se vuoi farlo in XAML, puoi provare a usare gli stili per farlo.

Ecco un esempio:

       

Nel tuo caso sia MyViewProperty che MyViewModelProperty si MyViewModelProperty ma ho usato nomi diversi solo per essere chiari su cosa sia cosa.

Diciamo che hai definito DepProp DependencyProperty nella vista e vuoi usare esattamente lo stesso valore nel tuo ViewModel (che implementa INotifyPropertyChanged ma non DependencyObject). Dovresti essere in grado di eseguire quanto segue nel tuo XAML:

      ...