Reputation: 2965
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
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
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