2010-07-26 16 views
18

Ich denke darüber nach, ein WPF User Control für meine Anwendung zu schreiben. Ich verwende MVVM in meiner Anwendung.Wpf UserControl und MVVM

Benutzersteuerelemente erfordern möglicherweise Abhängigkeitseigenschaften, die in der übergeordneten Ansicht festgelegt werden können. wenn MVVM verwendet, ist die Idee, dass die Ebene wird schließlich eine Bindung zwischen dem UserControls DP mit übergeordneter Ansicht VM)

Dependency Properties Notwendigkeit zu schaffen, in der View-Klasse als VM erstellt werden erbt nicht von DependencyObject. Dies bedeutet, dass Code innerhalb des XAML-Codes hinzugefügt wird.

Ich habe mich gefragt, ob Sie Tipps geben, wie ich ein Benutzersteuer entwerfen sollte, wenn WPF-Anwendung zu entwickeln MVVM mit ...

Antwort

24

Fall 1: Wenn Sie diese Kontrolle schaffen nur in verzehrt werden Ihre Anwendung dann können Sie voran gehen und eine ViewModel dafür erstellen, aber dann müssen Sie keine DPs erstellen, Ihre ViewModel können nur implementieren INotifyPropertyChanged und Ihre Eltern Vm kann immer noch an sie binden.

In unserem Fall haben wir für Benutzersteuerelemente separate VMs erstellt und eine Instanz davon war in ParentVM vorhanden. In der übergeordneten Ansicht wird dieses Steuerelement enthalten sein und das UserControlVM an dieses Steuerelement (ParentVM.UserControlVM) binden, und Benutzersteuerung wird sich um andere Bindungen kümmern.

Fall 2: Wenn Ihr Steuerelement von anderen Anwendungen/Entwicklern verwendet wird und Sie es nicht einfach halten möchten, dann fahren Sie mit der Erstellung benutzerdefinierter Steuerelemente nach der Implementierung der Steuervorlage fort. Auf diese Weise können Sie lupenreine Steuerelemente erstellen und auch dependency properties verwenden. Darüber hinaus muss derjenige, der dieses Steuerelement verwendet, das zugehörige Ansichtsmodell nicht kennen und verwenden.

Einige der ähnlichen Fragen/posts:

WPF-Design Frage (Custom Controls oder mvvm): WPF design question (custom control or mvvm)

Custom Control in WPF mit MVVM Konzept: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/6293b176-e1e9-4610-af49-d53e6d294969/

WPF User Control Hölle mit MVVM und Abhängigkeit Eigenschaften: WPF User Control hell with MVVM and Dependency Properties

+0

hallo akjoshi, was startegy verwenden Sie von den Eltern zu binden VM in die Steuerelemente VM-Eigenschaft? Können Sie ein kleines Beispiel geben? – byte

+1

Normalerweise setze ich den DataContext des Kindsteuerelements auf das Objekt von UserControlVM, das im ParentVM vorhanden ist. Also sagen Sie, Sie haben ein Hauptfenster, in dem Ihr Benutzersteuerelement vorhanden ist. Jetzt ist der Datenkontext des Hauptfensters auf ParentVM gesetzt, diese ParentVM zeigt eine Eigenschaft des Typs UserControlVM. Jetzt müssen wir nur den Datenkontext der Benutzersteuerung wie folgt setzen - akjoshi

+0

Danke akjoshi, ich benutze diese Strategie in meiner Anwendung und alle VM implementieren INotifyPropertyChanged. Meine Frage war mehr über die Eigenschaft Bindung in Ihrem Kommentar "Ihr ViewModel kann nur INotifyPropertyChanged implementieren und Ihre Eltern Vm kann immer noch an sie binden." Erstellen Sie die Steuerelemente VM in ParentVM und lassen Sie das ParentVM direkt an Steuerelemente VM? – byte

7

A UserControl ist Teil des "View" in "MVVM" wie die TextBox oder ListView Kontrollen Teil der Ansicht sind.

Ob Sie sich entscheiden MVVM zu benutzen, um Ihre UserControl selbst zu entwickeln oder sie in QBASIC schreiben (nicht empfohlen) ist es nicht das MVVM Muster für die Verbraucher Ihrer UserControl so lange dauert brechen, wie sie alles tun können, sie mit Ihrem UserControl brauchen durch Bindung an DependencyProperty ist auf Ihrer UserControl ausgesetzt. d. h. Ihr UserControl sollte die Eigenschaften freisetzen, die es abhängig ist (daher der Name). Sobald Sie diese DependencyProperty fangen plötzlich machen eine Menge Sinn und Sie wollen ihre hilfreiche auf geänderte Ereignishandler und Standardwerte, die Sie in ihrem Konstruktor angeben.

Wenn Ihre UserControl in einer anderen Baugruppe ist oder nicht, kann ich nicht sehen, wie das einen Unterschied macht.

Das sagte viele würden befürworten Sie bauen Ihre UserControl mit dem MVVM-Muster selbst für all die guten Gründe MVVM bringt z. einem anderen Entwickler helfen, Ihren Code zu betrachten. Allerdings sind einige Dinge einfach nicht möglich und/oder viel schwieriger, komplexer und weniger performant, um den XAML dafür zu hacken - ich spreche nicht von Ihrer Gartensorte Benutzerformular hinzufügen, sondern zum Beispiel von UserControl, die das Layout von Tausenden von Visuals behandelt. Außerdem, da Sie in Ihrem View arbeiten, tun Sie NICHT wollen Ihre UserControl 's ViewModels mit Ihren Anwendungen gemischt!

Grundsätzlich sage ich, es ist gut in MVVM MVVM auf Ihrem View nicht zu verwenden!

+1

Ich habe Sie aufgestuft, weil es eine gute Antwort war, aber auch, weil ich derjenige sein wollte, der Ihre Bewertung von 4444 zu 4454 bwahah machte –

+1

Gute Empfehlung, die VMs der Anwendung und 'UserControl' separat zu halten (+1). –

0

Anstatt den Datenkontext Ihres UserControls an das userControlViewModel zu binden, ist es besser, dies auf dem ersten untergeordneten Element des Benutzersteuerelements zu tun. Auf diese Weise werden alle Referenzen, die Sie innerhalb des Steuerelements erstellen, an das userControlViewModel gebunden, aber die Abhängigkeiteneigenschaften können aus dem Datenkontextsatz festgelegt werden, in dem Sie Ihr Benutzersteuerelement verwenden möchten.

Dieses Muster hat sich ziemlich gut für mich gearbeitet, auf dem 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> 

Dann auf den Code hinter:

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