2010-07-26 22 views
18

Sto pensando di scrivere un controllo utente WPF per la mia applicazione. Sto usando MVVM nella mia applicazione.Wpf UserControl e MVVM

I controlli utente possono richiedere le proprietà di dipendenza che possono essere impostate nella vista padre. quando si utilizza MVVM, l'idea è che la Capogruppo Vista finirà per creare un legame tra la UserControls DP con Capogruppo vista VM)

Dependency Properties devono essere creati nella classe Vedi come VM non ereditano da DependencyObject. Ciò significa aggiungere codice all'interno del codice XAML.

Mi chiedevo se si può dare consigli su come avrei dovuto progettare un controllo utente durante lo sviluppo di un'applicazione WPF utilizzando MVVM ...

risposta

24

Caso 1: Se si crea questo controllo solo per essere consumato in la tua applicazione quindi puoi andare avanti e creare uno ViewModel per questo, ma poi non hai bisogno di creare DP, il tuo ViewModel può semplicemente implementare INotifyPropertyChanged e il tuo genitore Vm può ancora legarsi a loro.

Nel nostro caso, per i controlli utente abbiamo creato VM separate e una sua istanza era presente in ParentVM. Quindi la visualizzazione padre avrà questo controllo e vincolerà il UserControlVM a questo controllo (ParentVM.UserControlVM) e usercontrol si prenderà cura di altri binding.

Caso 2: Se il controllo verrà utilizzato da altre applicazioni/sviluppatori e non si desidera mantenerlo semplice, procedere alla creazione di controlli personalizzati seguendo l'implementazione del modello di controllo. In questo modo puoi creare controlli senza look e usare anche dependency properties. Inoltre chi usa quel controllo non ha bisogno di conoscere il relativo modello di vista e di usarlo.

Alcuni dei simili domande/post:

WPF questione di progettazione (controllo o MVVM): WPF design question (custom control or mvvm)

controllo personalizzato in WPF utilizzando MVVM concetto: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/6293b176-e1e9-4610-af49-d53e6d294969/

Controllo utente WPF inferno con MVVM e Proprietà dipendenza: WPF User Control hell with MVVM and Dependency Properties

+0

hi akjoshi, quello startegy si usa per legare dai genitori VM alla proprietà VM dei controlli? Potresti fare un piccolo esempio? – byte

+1

In genere ho impostato il DataContext del controllo figlio sull'oggetto di UserCOntrolVM che è presente in ParentVM. Quindi, diciamo che hai una finestra principale all'interno della quale è presente il tuo controllo utente. Ora, il contesto dati della finestra principale è impostato su ParentVM, questo ParentVM esporrà una proprietà di tipo UserControlVM. Ora abbiamo solo bisogno di impostare il contesto dei dati del controllo utente come questo - akjoshi

+0

Grazie akjoshi, io uso questa strategia nella mia applicazione e tutte le VM implementano INotifyPropertyChanged. La mia domanda riguardava più il legame di proprietà nel tuo commento "il tuo ViewModel può semplicemente implementare INotifyPropertyChanged e il tuo genitore Vm può ancora legarsi a loro." Crei i controlli VM in ParentVM e permetti a ParentVM di collegarsi direttamente ai controlli VM ?? – byte

7

Un UserControl fa parte della "vista" in "MVVM" proprio come i TextBox o ListView controlli sono parte della vista.

Se si decide di utilizzare MVVM per sviluppare la vostra UserControl stesso o scrivere in QBASIC (non raccomandato) non si rompe il modello MVVM per i consumatori del vostro UserControl fino a quando si può fare ogni cosa di cui hanno bisogno con la vostra UserControl legandosi allo DependencyProperty esposto sul tuo UserControl. Ad esempio, il tuo UserControl dovrebbe esporre le proprietà che è dipendente su (da cui il nome). Una volta capito, questo DependencyProperty ha improvvisamente un sacco di buonsenso e vuoi il loro aiuto sui gestori di eventi modificati e sui valori predefiniti che hai specificato nel loro costruttore.

Se il vostro UserControl si trova in un altro gruppo o no, non vedo come questo faccia la differenza.

Detto questo molti sostengono che costruisci il tuo UserControl utilizzando lo stesso pattern MVVM per tutte le buone ragioni che MVVM offre, ad es. aiutare un altro sviluppatore a guardare il tuo codice. Tuttavia alcune cose semplicemente non sono possibili e/o molto più complesse e meno performanti hackerare lo XAML per fare questo - Non sto parlando della tua varietà di giardino Aggiungi modulo utente ma ad esempio un UserControl che gestisce il layout di migliaia di elementi visivi. Inoltre, dal momento che stai lavorando nella tua vista, fai NON vuoi che ViewModels di UserControl si mischi con le tue applicazioni!

Fondamentalmente sto dicendo che è bene all'interno MVVM non utilizzare MVVM sul tuo View!

+1

Ti ho upvoted perché è stata una buona risposta, ma anche perché volevo essere colui che ha reso il tuo punteggio di 4444 andare a 4454 bwahah –

+1

Buon consiglio di mantenere le VM dell'applicazione e 'UserControl' separate (+1). –

0

Fondamentalmente, invece di collegare il datacontext di UserControl a userControlViewModel, è meglio farlo sul primo elemento figlio del controllo utente. In questo modo, tutti i riferimenti effettuati all'interno del controllo verranno associati a userControlViewModel, ma le proprietà delle dipendenze possono essere impostate dal set di contesto dati in cui si desidera utilizzare l'UserControl.

Questo modello ha funzionato abbastanza bene per me, sul UserControl XAML:

<UserControl x:Class="Six_Barca_Main_Interface.MyUserControl" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:local="clr-namespace:Six_Barca_Main_Interface" 
      xmlns:System="clr-namespace:System;assembly=mscorlib" 
      mc:Ignorable="d" 
      d:DesignHeight="900" d:DesignWidth="900"> 

    <DockPanel x:Name="rootDock" > 
     <TextBlock>{Binding SomethingInMyUserControlViewModel}</TabControl> 
    </DockPanel> 
</UserControl> 

Poi sul codice dietro:

public partial class MyUserControl : UserControl 
{ 
    UserControlViewModel _vm; 

    public MyUserControl() 
    { 
     InitializeComponent(); 

     //internal viewModel set to the first child of MyUserControl 
     rootDock.DataContext = new UserControlViewModel(); 

     _vm = (UserControlViewModel)rootDock.DataContext; 


     //sets control to be able to use the viewmodel elements 

    } 

    #region Dependency properties 
    public string textSetFromApplication 
    { 
     get{return (string)GetValue(textSetFromApplicationProperty);} 
     set{SetValue(textSetFromApplicationProperty, value);} 
    } 

    public static readonly DependencyProperty textSetFromApplicationProperty = DependencyProperty.Register("textSetFromApplication", typeof(string), typeof(MyUserControl), new PropertyMetadata(null, OnDependencyPropertyChanged)); 

    private static void OnDependencyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     ((MyUserControl)d)._vm.SomethingInMyUserControlViewModel = 
      e.NewValue as string; 
    } 
#endregion