CBreeze
CBreeze

Reputation: 2965

How to Store a Temporary Unmodified Model in WPF MVVM

I want to store a temporary version of my Company model within WPF MVVM however I am having issues where even though the temp I create isn't bound to my UI elements, it is still being updated.

Here is what happens when the ModifyCompanyViewModel is instantiated:

public ModifyCompanyViewModel(Company passedCompany)
{
    SelectedCompany = passedCompany;
    _tempCompany = passedCompany;
    CloseWindowCommand = new CloseableCommand<Window>(CloseWindow);
}

So I have a readonly Company named _tempCompany. The UI elements are bound like so:

<TextBox Grid.Row="1" Grid.Column="1" x:Name="NameTextBox" Text="{Binding SelectedCompany.Name, Mode=TwoWay}"/>

Clearly they're bound to the SelectedCompany. If I then type something different in the TextBox that contains the Company's Name, but return the _tempCompany the _tempCompany's name reflects that which I have typed.

How can I store the _tempCompany in a way that no matter what is typed it's name stays the same? I have started using this approach which works:

_tempCompany = new Company
{
    Id = passedCompany.Id,
    Name = passedCompany.Name
    //Other properties..
};

But this seems very cumbersome and that I am overlooking an easier way.

Upvotes: 0

Views: 283

Answers (2)

Sinatr
Sinatr

Reputation: 21989

You have to create a viewmodel. Currently Company is a model. Attempting to use it as viewmodel (to bind to its properties) sooner or later will cause you problem, since you mention it's generated.

Consider a simple viewmodel wrapping Company:

public class CompanyViewModel: INotifyPropertyChanged
{
    readonly Company _company;
    public CompanyViewModel(Company company)
    {
        _company = company;
    }

    // now expose something
    public string Address
    {
        get { return _company.Address }
        set
        {
            // tracking changes
            // note: you aren't tracking changes made to model instance!
            _company.Address = value;
            OnPropertyChanged();
        }
    }

    // and here is what you actually want, read-only name
    public string Name => _company.Name;

    // you can optinally expose model and bind to it properties
    // but that wouldn't let you track the changes
    // unless model implements INotifyPropertyChanged
    public Company Company => _company;

    ...
}

If you want to edit company name, then just make another property (call it NewName), set its initial value in constructor and decide for yourself when its value will replace _company.Name (e.g. in some method AcceptChanges() which will be called when user finish editing). You will be able to access both: NewName and not yet changed _company.Name to compare them and display confirmation button.

Upvotes: 0

mm8
mm8

Reputation: 169170

The SelectedCompany property and the _tempCompany field reference the same Company object. If you want to store "a temporary version" of the Company object you need to create a temporary version, i.e. you need to create another instance of the Company class like you are currently doing:

_tempCompany = new Company
{
    Id = passedCompany.Id,
    Name = passedCompany.Name
    //Other properties..
};

This is not cumbersome.

As suggested in the comments you could implement the ICloneable interface but this just moves the creation of the other instance to a method within the class that implements the interface. You still need to create another instance somewhere.

How can I implement ICloneable when the model is generated by EF?

Create a partial class and implement the Clone method in this one.

Upvotes: 1

Related Questions