2013-02-14 5 views
7

Ich habe einige Design-Fragen in meinem wpf MVVM (Prism-basierte) Anwendung, würde mich freuen, Ihren Rat zu bekommen. Mein Modell ist sehr einfach:Hinzufügen von INotifyPropertyChanged zu Model?

public class Customer 
{ 
    public string FirstName {get;set;} 
    public string LastName {get;set;} 
} 

Wie Sie sehen können, habe ich jede INotifyPropertyChnaged Unterstützung nicht für meine Modellklasse haben. Ich habe auch ViewModel für den CustomerDetails Bildschirm, der INotifyPropertyChanged unterstützt.

In meiner Sicht verwende ich die Bindung an den Item.FirstName und mein ViewModel wird aktualisiert. Mein Problem ist - da nur die FirstName-Eigenschaft über die Ansicht aktualisiert wird und das Model selbst INotifyPropertyChanged nicht unterstützt, daher wird der Itemsetter nicht aufgerufen, und der IsDirty bleibt gleich falsch (und aktualisiert daher die IsDirty-Benachrichtigung nicht) auf der Benutzeroberfläche).

Ich weiß, ich INotifyPropertyChanged im Modell unterstützen kann, und dann registrieren, auf das Item.PropertyChanged Ereignis in dem View-Modell und stelle tatsächlich die IsDirty zu wahren, aber - Da ich auch CodeFirst verwenden, und mein Modell Klasse, die zwischen meiner ServerSide- und meiner Client-Seite geteilt wird (ohne Add Service Reference), möchte ich die INotifyPreoprtyChanged-Sachen nicht auf meiner Serverseite hinzufügen.

Ich bin daran interessiert, ein neues Projekt zu erstellen, das T4-Vorlagen verwenden wird, um alle meine Entitäten nacheinander zu kopieren (als Kunde) und INotifyPropertyChanged Unterstützung für jedes Modell hinzuzufügen. Ist das etwas, das vernünftig erscheint oder nicht? Irgendwelche anderen Vorschläge?

Danke!

Antwort

4

Option1.
Separate Entitäten, die zwischen Client und Server (DTO) von Entitäten übertragen werden, bei denen es sich um Modelle auf der Clientseite handelt. Implementieren Sie INPC in Modellen. Verwenden Sie eine Zuordnung zwischen diesen Entitäten.

Option2.
Bindungsansicht, um nur Modelleigenschaften anzuzeigen. Erstellen Sie Ansichtsmodelleigenschaften, die entsprechende Modelleigenschaften umbrechen.

Option 3.
Ist eine Mischung aus ersten beiden Optionen. Aggregieren Sie das Modell nicht im Ansichtsmodell. Verwenden Sie die Zuordnung zwischen Modell und Ansichtsmodell. Erstellen Sie Ansichtsmodelleigenschaften, die den Modelleigenschaften entsprechen.

0

Ich denke, Sie sind auf dem richtigen Weg. Auf der Serverseite benötigen Sie INotifyPropertyChanged nicht, fügen Sie sie daher nicht den Domänenklassen auf der Serverseite hinzu.

Sie können nur einige Build-Symbole wie "WPF" zu Ihren Client-Projekten hinzufügen; und im Code implementieren erste Definitionen INotifyPropertyChanged nur, wenn es "WPF" Build-Symbol gibt. Fügen Sie dann einfach Ihre serverseitigen Domänenklassen als Links zu Ihrer Präsentationsanwendung hinzu. Etwas wie;

#if WPF 
public class MyEntity : INotifyPropertyChanged 
#else 
public class MyEntity 

.... 
1

Nun, Ihr Ansatz ist einfach nicht der beste. Viel besser wäre es, eine VM wie diese zu verwenden


public class CustomerDetailsViewModel : INotifyPropertyChanged 
{ 
    public CustomerDetailsViewModel(Customer customer) 
    { 
    _item = customer; 
    } 
    private Customer _item; 

    public string FirstName 
    { 
    get { return _item != null ? _item.FirstName : null; } 
    set 
    { 
     if (_item == null) 
     _item = new Customer(); // just an example, probably it's not the desired behavior 
     _item.FirstName = value; 
     RaisePropertyChanged(...); 
    } 
    } 
    ... 
} 

Dies würde an den Geist von MVVM bleiben.

+2

Ich verstehe, was Sie sagen, aber das wird eine Menge Codierung für (fast) ohne Grund erfordern. Sollte ich jede Eigenschaft meines Modells in meinem Ansichtsmodell duplizieren? – Asaf

+0

@Asaf Sie haben Recht. Ich kenne dein Projekt nicht. Wenn es nur ein kleiner ist, könnte es ein großer Overhead sein. Aber in größeren Projekten, wenn Sie zusätzliche Anforderungen wie Testbarkeit haben, entkoppeln a.s.o. Es wäre ein Weg, sie zu erreichen. – DHN

1

Wenn Sie Ihre UI möchten, wenn Sie Ihr Modell Eigentum bemerken geändert, Ihre Modellklasse MUST implementieren INotifyPropertyChanged und ähnliche MVVM Schnittstellen (IDataErrorInfo, etc ...), um Notify an der Benutzeroberfläche, dass die property changed.

Das liegt daran, dass Sie Ihr Modell nicht immer aus dem Viewmodel aktualisieren, in dem Sie INotifyProperyChanged implementieren und für Änderungen benachrichtigen müssen.

Die entsprechenden Modelleigenschaften werden in das Viewmodel eingeschlossen, wenn Sie INotifyPropertyChanged in der Modellklasse nicht implementieren können, wodurch das Viewmodel sehr schnell wächst und unnötige Codeverdopplung erzeugt.

Szenario zum Beispiel:

public class Customer 
{ 
    public string FirstName {get;set;} 
    public string LastName {get;set;} 

    // Changes the first name. 
    public void ChangeFirstName(string newName) 
    { 
     FirstName = newName; 
     //The UI will never know that the property changed, and it won't update. 
    } 
} 

Lösung:

Implementieren INotifyPropertyChanged in Ihnen Modellklasse, erstellen backing fields auf Ihre properties und für jede Eigenschaft setter nach dem set Betrieb erhöhen OnPropertyChanged aufgerufene Methode mit der Name property.

0

Wenn Sie nicht Ihr Modell wie mit INotifyPropertyChanged Code Krempel Sie könnten versuchen, eine NuGet Paket namens PropertyChanged.Fody

Sie können es wie folgt verwenden;

using PropertyChanged; 

[ImplementPropertyChanged] 
public class Customer 
{ 
    public string FirstName {get;set;} 
    public string LastName {get;set;} 
} 

unterstützt öffentliche Eigenschaft in dieser Klasse jetzt INotifyPropertyChanged