Ho avuto anche questo problema. L'ho risolto usando "The Memento Pattern Design". Con questo modello è possibile salvare facilmente una copia dell'oggetto originale e, in selectedIndexChange
(di un controllo) o nel pulsante Annulla, è possibile ripristinare facilmente la versione precedente del proprio oggetto.
Un esempio di utilizzo di questo modello è disponibile presso How is the Memento Pattern implemented in C#4?
Un esempio di codice:
Se abbiamo un utente classe con proprietà Nome utente Password e NombrePersona abbiamo bisogno di aggiungere metodi CreateMemento e 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;
}
Poi, abbiamo bisogno di una Memento classe che conterrà la "copia" del nostro oggetto come questo:
/// <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; }
}
}
e abbiamo bisogno di una classe che genera e contiene il nostro oggetto ricordo:
/// <summary>
/// The 'Caretaker' class
/// </summary>
class Caretaker
{
private Memento _memento;
// Gets or sets memento
public Memento Memento
{
set { _memento = value; }
get { return _memento; }
}
}
Poi, per attuare questo modello dobbiamo creare un'istanza di Caretaker
classe
Caretaker creadorMemento = new Caretaker();
e creare il nostro oggetto ricordo quando è stato selezionato un nuovo utente per la modifica, ad esempio in selectedIndexChange
dopo l'inizializzazione di SelectedUser, utilizzo il metodo per l'evento RaisPropertyChanged
in questo modo:
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);
}
}
Una spiegazione per questo, quando selectedIndexChanged
valore di variazione controlliamo se UserSelected
e our memento object
non sono nulli significa che il nostro articolo reale in modalità di modifica è cambiato allora dobbiamo ripristinare il nostro oggetto con il metodo SetMemento
. E se la nostra proprietà UserSelected
cambia e non è nulla, "Crea il nostro oggetto Memento" che useremo quando la modifica è stata annullata.
Per finire, abbiamo utilizzare il metodo SetMemento
in ogni metodo che abbiamo bisogno di cancellare l'edizione, e quando la modifica è impegnata come nel SaveCommand possiamo impostare nullo il nostro oggetto ricordo come questo this.creadorMemento = null
.
IEditableObject crea un sacco di spese generali per gli oggetti, soprattutto se gli oggetti del modello sono una classe e non una stringa, è necessario riscrivere gli oggetti del modello per supportarlo. – Agies
@Agies: perché il downvote? Se IEditableObject è un "sovraccarico" o non dipende interamente dalla tua infrastruttura o da come desideri implementarla. È solo un'interfaccia che WPF comprende. Come lo realizzi dipende da te. –
+1, sì, voglio implementarlo con IEditableObject, ma ho un ViewModelBase che espone una proprietà Modello di tipo TModel e leghiamo la vista direttamente alle proprietà del modello esposto. Ora, come posso ancora usare "Annulla modifica", inoltre, ora che conosci il mio scenario, dì che il mio TModel è un'entità indirizzo. in modalità di visualizzazione si collega solo alla riga di FullAddress e utilizza AddressDataTemplate (creando un collegamento a GMaps), ma voglio che quando l'utente fa clic sul pulsante Modifica su AddressView, dovrebbe aprire ChildWindow (SL, o qualsiasi altra finestra in WPF) continua ... –
Shimmy