21 Stimmen

Wie kann man eine Bearbeitung eines Objekts mit MVVM abbrechen?

Wie kann ich den Abbruch der Bearbeitung eines Objekts mit MVVM implementieren.

Zum Beispiel: Ich habe eine Liste von Kunden. Ich wähle einen Kunden aus und klicke auf die Schaltfläche "Bearbeiten", ein Dialogfenster (DataContext ist an CustomerViewModel gebunden) öffnet sich und ich beginne, die Felder des Kunden zu bearbeiten. Und dann entscheide ich mich, die Bearbeitung abzubrechen, aber die Felder des Kunden wurden bereits geändert, wie kann ich also einen Kunden in MVVM in seinen vorherigen Zustand zurückversetzen?

13voto

Kent Boogaart Punkte 170094

Überprüfen Sie die IEditableObject Schnittstelle. Ihr Customer Klasse sollte das implementieren, und Ihre Befehle können ausgeführt werden BeginEdit / CancelEdit / EndEdit nach Bedarf.

1 Stimmen

IEditableObject schafft eine Menge Overhead für Ihre Objekte, vor allem, wenn Ihr Modell Objekte sind eine Klasse und nicht eine Struktur, müssten Sie Ihre Modell-Objekte, um es zu unterstützen neu zu schreiben.

7 Stimmen

@Agies: Warum das Downvote? Ob IEditableObject eine "Menge Overhead" ist oder nicht, hängt ganz von deiner Infrastruktur ab oder davon, wie du es implementieren willst. Es ist nur eine Schnittstelle, die WPF versteht. Wie du es implementierst, ist dir überlassen.

0 Stimmen

+1, ja, ich möchte es mit IEditableObject implementieren, aber ich habe eine ViewModelBase<TModel>, die eine Eigenschaft Model vom Typ TModel offenlegt und ich binde die Ansicht direkt an die Eigenschaften des offengelegten Modells. Nun, wie könnte ich noch 'Cancel Edit' verwenden, auch, jetzt, dass Sie mein Szenario kennen, sagen, dass mein TModel eine Adresse Entität ist. im Ansichtsmodus ist es nur bindet an die FullAddress Zeile und verwendet die AddressDataTemplate (eine Verknüpfung zu GMaps machen), aber ich möchte, dass, wenn der Benutzer die Schaltfläche Bearbeiten auf der AddressView klickt, sollte es ein ChildWindow (SL, oder was auch immer Fenster in WPF) öffnen, um fortgesetzt werden...

5voto

Sie können die Bindung mit UpdateSourceTrigger=Explicit . Hier finden Sie weitere Informationen, wie dies umgesetzt werden kann.

2 Stimmen

Eine gute Antwort sollte spezifischer sein, am besten mit einem Codebeispiel.

1 Stimmen

Obwohl es dieser Antwort an Details mangelt, halte ich sie für die sauberste Lösung. UpdateSourceTrigger=Explicit ist genau für das gemacht, was terkri zu tun versucht. Die anderen Lösungen, obwohl sie funktionieren können, sind wirklich nur Hacks.

0 Stimmen

Wenn Ihre Validierung auf der Verfolgung von Quelländerungen beruht (über IDataErrorInfo zum Beispiel), dann erhalten Sie keine Validierung, bis Sie die Quelle aktualisieren (wenn überhaupt, ich bin mir nicht sicher), zu diesem Zeitpunkt möchten Sie vielleicht immer noch in der Lage sein, alle Änderungen rückgängig zu machen, aber Ihr Modell wird bereits aktualisiert haben.

4voto

Agies Punkte 1105

Wenn Ihr Objekt bereits serialisierbar ist, wie z. B. bei der Verwendung von WCF, gibt es eine sehr einfache Möglichkeit. Sie können Ihr Originalobjekt in ein internes Feld serialisieren. Wenn Ihr Objekt nicht serialisierbar ist, dann verwenden Sie einfach AutoMapper um eine Kopie Ihres Objekts mit einer Zeile Code zu erstellen.

Order backup = Mapper.Map<Order, Order>(order);

Wenn Sie Ihren CancelCommand bearbeiten, rufen Sie AutoMapper einfach in umgekehrter Reihenfolge auf. Da Ihre Eigenschaften bereits eine Änderungsbenachrichtigung haben, funktioniert alles einfach. Es ist möglich, dass Sie diese Techniken mit IEditableObject kombinieren können, wenn Sie den zusätzlichen Code schreiben müssen und wollen.

0 Stimmen

Der Nachteil von AutoMapper ist, dass es nur den Zustand erfasst, der durch die Eigenschaften reflektiert wird. Wie bei anderen Lösungen, bei denen davon ausgegangen wird, dass jeder Status für jede bearbeitbare Klasse durch Lese-/Schreibeigenschaften offengelegt wird, sollte dies für Szenarien, die DTOs oder andere ähnliche anämische Objekte verwenden, gut funktionieren. Binäre Serialisierung und NetDataContractSerialization haben dieses Problem nicht, da sie mit Feldern arbeiten. BTW, es ist schwierig, wenn Ereignisse und Delegaten ins Spiel kommen.

3voto

Eduardo Molteni Punkte 37808

En dieser Artikel Raul lädt das Objekt einfach neu aus der DB. Ich denke, das ist weniger problematisch als die Lösung, die Kent vorschlägt.

    internal void Cancel(CustomerWorkspaceViewModel cvm)
    {
        Mainardi.Model.ObjectMapping.Individual dc = cvm.DataContext 
                                 as Mainardi.Model.ObjectMapping.Individual;

        int index = 0;

        if (dc.ContactID > 0 && dc.CustomerID > 0)
        {
            index = _customerCollectionViewModel.List.IndexOf(dc);
            _customerCollectionViewModel.List[index] = 
                                  _customerBAL.GetCustomerById(dc.CustomerID);
        }

        Collection.Remove(cvm);
    }

0 Stimmen

Ich denke, dass das Nachladen aus der DB eine Möglichkeit ist, die Verpflichtungen des IEditableObject von Herrn Boogaarts Vorschlag zu erfüllen, nicht unbedingt eine Alternative zu diesem.

1voto

Silas Punkte 1130

Basierend auf Antwort :

Sie können Ihre Bindungen als manuell zu aktualisieren markieren, indem Sie

<TextBox Name="yourTextBox" Text="{BindingPath=YourBinding, UpdateSourceTrigger=Explicit}" />

in Ihrer Ansicht (XAML). Dann müssen Sie die Änderungen aus Ihrer Benutzeroberfläche in das ViewModel schreiben, indem Sie

yourTextBox.GetBindingExpression(TextBox.TextProperty).UpdateSource();
wenn Sie auf Speichern klicken.

Bitte beachten Sie, dass Aktualisierungen der Datenbindungsquelle, die von anderen Quellen ausgelöst werden, weiterhin direkt auf der Benutzeroberfläche angezeigt werden.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X