20 votes

Comment annuler la modification d'un objet en utilisant MVVM ?

Comment puis-je mettre en œuvre l'annulation de l'édition d'un objet en utilisant MVVM.

Par exemple : J'ai une liste de clients. Je choisis un client et clique sur le bouton "Editer", une fenêtre de dialogue (DataContext est lié à CustomerViewModel) s'ouvre et je commence à modifier les champs du client. Et puis je décide d'annuler l'édition, mais les champs du client ont déjà été modifiés, alors comment puis-je ramener un client à son état précédent en MVVM ?

1voto

amigable vecino Points 11

J'ai eu ce problème aussi. Je l'ai résolu en utilisant "The Memento Pattern Design". Avec ce modèle, vous pouvez facilement sauvegarder une copie de votre objet original et, en selectedIndexChange (d'un contrôle) ou dans le bouton Annuler, vous pourriez rétablir facilement la version antérieure de votre objet.

Un exemple d'utilisation de ce modèle est disponible à l'adresse suivante Comment le modèle Memento est-il mis en œuvre en C#4 ?

Un exemple de code :

Si nous avons une classe User avec les propriétés UserName Password et NombrePersona, nous devons ajouter les méthodes CreateMemento et 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;
    }

Ensuite, nous avons besoin d'une classe Memento qui contiendra la "copie" de notre objet comme ceci :

 /// <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; }
    }
}

Et nous avons besoin d'une classe qui va générer et contenir notre objet memento :

/// <summary>
/// The 'Caretaker' class
/// </summary>
class Caretaker
{
    private Memento _memento;

    // Gets or sets memento
    public Memento Memento
    {
        set { _memento = value; }
        get { return _memento; }
    }

}

Ensuite, pour mettre en œuvre cette motif nous devons créer une instance de Caretaker classe

Caretaker creadorMemento = new Caretaker();

Et créer notre objet mémento lorsqu'un nouvel utilisateur a été sélectionné pour être édité, par exemple dans selectedIndexChange après que le SelectedUser ait été initialisé, j'utilise la méthode pour l'événement RaisPropertyChanged comme ça :

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);
        }
    }

Une explication à ce sujet, lorsque selectedIndexChanged changer la valeur, nous vérifions si UserSelected y our memento object ne sont pas nuls signifie que l'élément actuel en mode édition a changé, alors nous devons restaurer notre objet avec la méthode SetMemento . Et si notre UserSelected et n'est pas nulle, nous "créons notre objet Memento" que nous utiliserons lorsque la modification a été annulée.

Pour la finition, nous avons utilisé le SetMemento dans chaque méthode dont nous avons besoin pour annuler l'édition, et lorsque l'édition a été validée comme dans la SaveCommand, nous pouvons mettre à zéro notre objet memento comme ceci this.creadorMemento = null .

0voto

Goblin Points 4612

Vous pourriez également, dans votre ViewModel, copier l'état du modèle dans des champs internes, puis les exposer et ne les définir que sur le modèle, lorsque l'utilisateur effectue effectivement le changement.

Le problème pourrait être que la validation à la volée sera plus problématique si la validation repose sur la mise à jour de l'entité - si c'est une exigence, vous pourriez créer un clone du modèle sur lequel travailler, puis fusionner le clone avec l'entité réelle lorsqu'elle est enregistrée.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X