I've started working on an application that allows the user to enter some data in different textboxes and then these data are serialized in an XML format, but it seems that I've understood the MVVM concept completely wrong because I've tried to serialize the ViewModel and one of my work colleagues said that is an incorrect way to do things and I should serialize the MODEL.
The "incorrect" implementation:
public class ExampleViewModel : ViewModelBase
{
private double lowerRange;
public double LowerRange
{
get { return lowerRange; }
set
{
lowerRange = value;
RaisePropertyChanged();
}
}
private double upperRange;
public double UpperRange
{
get { return upperRange; }
set
{
upperRange = value;
RaisePropertyChanged();
}
}
}
According to my colleague, serializing this is wrong, but then how should look my MODEL (actually this is the question) This is correct?
public class ExampleModel
{
public double LowerRange { get; set; }
public double UpperRange { get; set; }
}
public class ExampleViewModel : ViewModelBase
{
private ExampleModel model;
public ExampleViewModel()
{
model = new ExampleModel();
}
private double lowerRange;
public double LowerRange
{
get { return model.LowerRange; }
set
{
model.LowerRange = value;
RaisePropertyChanged();
}
}
private double upperRange;
public double UpperRange
{
get { return model.UpperRange; }
set
{
model.UpperRange = value;
RaisePropertyChanged();
}
}
}
Or this is complety overhead? If you can provide me a meaningful example, I'll be grateful. Also, I've seen some people that use "RaisePropertyChanged()" inside a MODEL, is this correct? that this model because a ViewModel, right?
CodePudding user response:
Following my comment above, here is how I tend to do this:
public class ExampleModel : ViewModelBase
{
private double _lowerRange;
private double _upperRange;
public double LowerRange
{
get { return _lowerRange; }
set
{
_lowerRange = value;
RaisePropertyChanged();
}
}
public double UpperRange
{
get { return _upperRange; }
set
{
_upperRange= value;
RaisePropertyChanged();
}
}
}
public class ExampleViewModel : ViewModelBase
{
private ExampleModel model;
public ExampleViewModel()
{
Model = new ExampleModel();
}
// this is only needed if you change your complete model
// and need to update the change on the UI
public ExampleModel Model
{
get { return model; }
set
{
model = value;
RaisePropertyChanged();
}
}
}
Also, if you change your ViewModelBase
class to something like the one shown here, you can simplify the property getters/setters a bit to the following for example:
public ExampleModel Model
{
get { return model; }
set { SetProperty<ExampleModel >(ref model, value); }
}
CodePudding user response:
The following works in WPF and also UWP:
// The Base Class that implements INotifyPropertyChanged to trigger UI-Updates from ViewModel & not from Code-Behind
public abstract class VMAppObject : System.ComponentModel.INotifyPropertyChanged
{
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string property= "")
{
this.PropertyChanged?.Invoke(this,new System.ComponentModel.PropertyChangedEventArgs(property));
}
}
// The Model
public class ModelObj{
private string _Content;
public string Content
{
get => _Content;
set => _Content = value;
}
}
// Bindable-Collection of Models
public class ModelObjs : System.Collections.ObjectModel.ObservableCollection<ModelObj>{};
// MainViewModel which handels the current state of the application
public class ApplicationMainVM: VMAppObject {
private ModelObjs _BindingModels = new ModelObjs();
public ModelObjs BindingModels
{
get {
if(_BindingModels == null) {
_BindingModels = // load from database or api
}
return _BindingModels;
}
set { _BindingModels = value; this.OnPropertyChanged(); }
}
}
when you got that infrastructure, then you have to set the window.datacontext to an new instance of the applicationMainVM in the application-startup and then you should be able to bind the Model to the View. Inside the mainpage.xaml
<ListView ItemsSource="{Binding BindingModels}">
<ListView.ItemTemplate>
<DataTemplate >
<TextBlock Text="{Binding Content}" FontSize="15">
</TextBlock>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
the PropertyChanged only indicates that the appication needs to be redrawn. u can use it inside the model to update ui, when a single value of the model changes, or use it when the collection is set.
inside a model you should only store the data like a app-cache while the viewmodel holds the businesslogic.
if your mainviewmodel gets to big you can create independent nested viewmodels but then you would have to do the binding right
ItemsSource="{Binding NestedVM.BindingModels}"
hope its helpfull :)