c# – Binding and undoing changes

Question:

There is a class. For example such

public class MyClass
{
    public string Prop1 { get; set; }
    public string Prop2 { get; set; }
}

Well, this is a VM and implements the property change interface

There is xaml markup, for example this

<TextBox Text="{Binding Prop1}"/>
<TextBox Text="{Binding Prop2}"/>
<Button Content="Сохранить"/>
<Button Content="Отменить"/>

That is, there is a form for editing an instance of the MyClass class, into which we pass an instance as a parameter to the constructor (or in some other way). Now the question is how to make the Save and Cancel buttons work? Editing the text boxes in the example changes the properties of the class in real time. Once I used UpdateSourceTrigger=Explicit for this, but for a number of reasons I don't like it. There is also an idea to duplicate an instance (that is, send a copy of it to the form), but this option does not suit me at all in a particular case. What other options are there?

UPD:

I will try to explain why the solutions I proposed above do not suit me. I need a solution that will be obvious to a person who can later take part in expanding the functionality. And the first thing that catches your eye will be the transfer of an instance of the class to the form, the properties of the class and their correspondence to the fields in the xaml markup. And if you make changes to the obvious, without making them to the unobvious (in the function of copying a class, for example), then at best this will lead to an error that will be easy to track down, although it will take time. In the worst case, this will lead to erroneous data that will surface indefinitely.

Answer:

You can try to solve it in the following way.

1) Create your own attribute, which will mark the properties, can change in the dialog.

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class RememberAttribute {}

2) Mark with this attribute the properties that need to be remembered:

public class MyClass
{
    [Remember]
    public string Prop1 { get; set; }
    public string Prop2 { get; set; }
}

3) Create a class that will remember the values ​​of all properties of the view model marked with this attribute. This is where you probably have to tinker with collections, nested properties, and so on (if necessary).

public class StateSaver<T> where T : ViewModel 
{
    // здесь восстанавливаем исходное состояние модели представления
    public void Restore() { ... } 
}

4) Before showing the dialog, save the state of the class, and then, if necessary, roll back the changes

class SomeVm
{
    MyClass myClass = new MyClass();

    void ShowMyClass()
    {
        var stateSaver = new StateSaver(myClass);

        // здесь все зависит от того, каким образом у вас организован метод для показа модели представления в новом окне
        // можно, например, сделать так, чтобы он принимал stateSaver и самостоятельно вызывал метод Restore
        ShowInDialog(myClass, stateSaver); 
        // либо он может возвращает какой-нибудь dialogResult, на основе которого будут отменены изменения
    }
}

And you can screw AutoMapper to your version. Then you will not need to monitor the change of the list of properties in the view model.

Scroll to Top