Ich hatte dieses Problem auch. Ich löste es mit "The Memento Pattern Design". Mit diesem Muster könnten Sie einfach eine Kopie Ihres Originalobjekts speichern und in selectedIndexChange
(eines Steuerelements) oder in der Abbrechen-Schaltfläche können Sie einfach die vorherige Version Ihres Objekts wiederherstellen.
Ein Beispiel für die Verwendung dieses Musters ist bei How is the Memento Pattern implemented in C#4?
Ein Beispiel-Code zur Verfügung:
Wenn wir eine Klasse Benutzer mit Eigenschaften haben Benutzername Passwort und NombrePersona wir hinzufügen müssen Methoden CreateMemento und SetMemento:
public class Usuario : INotifyPropertyChanged
{
#region "Implementación InotifyPropertyChanged"
internal void RaisePropertyChanged(string prop)
{
if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(prop)); }
}
public event PropertyChangedEventHandler PropertyChanged;
#endregion
private String _UserName = "Capture su UserName";
public String UserName
{
get { return _UserName; }
set { _UserName = value; RaisePropertyChanged("UserName"); }
}
private String _Password = "Capture su contraseña";
public String Password
{
get { return _Password; }
set { _Password = value; RaisePropertyChanged("Password"); }
}
private String _NombrePersona = "Capture su nombre";
public String NombrePersona
{
get { return _NombrePersona; }
set { _NombrePersona = value; RaisePropertyChanged("NombrePersona"); }
}
// Creates memento
public Memento CreateMemento()
{
return (new Memento(this));
}
// Restores original state
public void SetMemento(Memento memento)
{
this.UserName memento.State.UserName ;
this.Password = memento.State.Password ;
this.NombrePersona = memento.State.NombrePersona;
}
Dann brauchen wir eine Klasse Memento, die die „Kopie“ unseres Objekt wie folgt enthalten:
/// <summary>
/// The 'Memento' class
/// </summary>
public class Memento
{
//private Usuario _UsuarioMemento;
private Usuario UsuarioMemento { get; set; }
// Constructor
public Memento(Usuario state)
{
this.UsuarioMemento = new Usuario();
this.State.UserName = state.UserName ;
this.State.Password = state.Password ;
this.State.NombrePersona = state.NombrePersona ;
}
// Gets or sets state
public Usuario State
{
get { return UsuarioMemento; }
}
}
Und wir brauchen eine Klasse, die generiert und enthält unser Erinnerungsobjekt:
/// <summary>
/// The 'Caretaker' class
/// </summary>
class Caretaker
{
private Memento _memento;
// Gets or sets memento
public Memento Memento
{
set { _memento = value; }
get { return _memento; }
}
}
Dann für Umsetzung dieser Muster wir haben eine Instanz Caretaker
Klasse
Caretaker creadorMemento = new Caretaker();
erstellen und erstellen unser Memento-Objekt, wenn ein neuer Benutzer zum Bearbeiten ausgewählt wurde, zum Beispiel in selectedIndexChange
nachdem der SelectedUser initialisiert wurde, verwende ich die Methode für das Ereignis RaisPropertyChanged
wie folgt:
internal void RaisePropertyChanged(string prop)
{
if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(prop)); }
if (prop == "RowIndexSelected") // This is my property assigned to SelectedIndex property of my DataGrid
{
if ((this.UserSelected != null) && (creadorMemento .Memento != null))
{
this.UserSelected.SetMemento(creadorMemento .Memento);
}
}
if (prop == "UserSelected") // Property UserSelected changed and if not is null we create the Memento Object
{
if (this.UserSelected != null)
creadorMemento .Memento = new Memento(this.UserSelected);
}
}
Eine Erklärung für dieses, wenn selectedIndexChanged
Wert, den wir ändern überprüfen, ob UserSelected
und our memento object
nicht null sind, bedeutet, dass unsere tatsächlichen Artikel im Bearbeitungsmodus dann geändert wir unser Objekt mit der Methode SetMemento
wiederherstellen müssen. Und wenn sich unsere UserSelected
Eigenschaft ändert und nicht null ist, erstellen wir unser Memento-Objekt, das wir verwenden werden, wenn die Bearbeitung abgebrochen wurde.
Für das Ende haben wir die SetMemento
Methode in jeder Methode, die wir brauchen, um die Ausgabe abzubrechen, und wenn die Bearbeitung wie im SaveCommand commited hat, können wir null unser Memento-Objekt wie dieses this.creadorMemento = null
setzen.
IEditableObject erzeugt eine Menge Overhead für Ihre Objekte. Insbesondere wenn Ihre Model-Objekte eine Klasse und kein Struct sind, müssten Sie Ihre Modellobjekte neu schreiben, um sie zu unterstützen. – Agies
@Agies: Warum der Downvote? Ob IEditableObject "viel Overhead" ist oder nicht, hängt ganz von Ihrer Infrastruktur ab oder davon, wie Sie es implementieren möchten. Es ist nur eine Schnittstelle, die WPF versteht. Wie Sie es umsetzen, liegt an Ihnen. –
+1, ja, ich möchte es mit IEditableObject implementieren, aber ich habe eine ViewModelBase, die eine Eigenschaft Modell des Typs TModel verfügbar macht, und ich binde die Ansicht direkt auf die Eigenschaften des exponierten Modells. Nun, wie könnte ich noch "Abbrechen bearbeiten" verwenden, auch jetzt, da Sie mein Szenario kennen, sagen Sie, dass mein TModel eine Address-Entität ist. Im Ansichtsmodus bindet es nur an die FullAddress-Zeile und verwendet die AddressDataTemplate (eine Verknüpfung zu GMaps), aber wenn der Benutzer auf die Edit-Schaltfläche in der AddressView klickt, sollte ein ChildWindow (SL oder ein beliebiges Fenster in WPF geöffnet werden)) wird fortgesetzt ... –
Shimmy