2

Is there a simpeler way to bind many properties?

So if you have a Person class with properties: lastname, firstname, birthday, gender, title, ...

Now I do this for every property on the ViewModel:

 public string _LastName;
 public string LastName
 {
    get { return _LastName; }
    set { _LastName = value;
          RaisePropertyChanged("LastName"); }
 } 

And on the XAML page this binding:

 <TextBlock Text="{Binding FirstName}" />

Now image if Person object has like 20 properties.. So my question is can I do this in a simpeler way?

user7998549
  • 131
  • 3
  • 15
  • Possible duplicate of [Automatically INotifyPropertyChanged](https://stackoverflow.com/questions/527602/automatically-inotifypropertychanged) – ASh Jun 08 '17 at 20:46

4 Answers4

2

You only need to raise the PropertyChanged event from the setter of a data-bound property if you actually intend to update the property dynamically at runtime. Otherwise you could use auto-implemented properties without any custom logic:

public FirstName { get; set; }

There is also a NuGet package called Fody that can turn simple public properties into full INotifyPropertyChanged implementations for you automatically: https://github.com/Fody/PropertyChanged

mm8
  • 163,881
  • 10
  • 57
  • 88
0

If you use a third party MVVM framework, it also might have a code snippet to create property with INotifyPropertyChanged.

If you use Catel, you can download templates and snippets here: http://catelproject.com/downloads/general-files/

And here's implementation for Caliburn.Micro: https://github.com/winterdouglas/propc

0

The simplest solution is to use the POCO mechanism provided by a free DevExpress MVVM Framework. POCO will automatically implement INotifyPropertyChanged and raise the PropertyChanged event for all public virtual properties in your view model.

All magic happens when you use the ViewModelSource class to create your view model. You can create your view model in XAML:

<UserControl ...
    DataContext="{dxmvvm:ViewModelSource Type=local:MyViewModel}"> 

Or in code-behind:

this.DataContext = ViewModelSource.Create(() => new MyViewModel());
Alex Russkov
  • 323
  • 2
  • 8
0

PREMISE

In a default MVVM scenario, your ViewModel don't have to raise notifications on every property.

Typical case: you get some Person from a database, show them on a View, modify them via TextBoxes and other controls, and click "Save" re-sending them to the database. You can do this by setting the DataContext on the View every time you call the database. This action raises a first update on the bound properties of the control and of every sub-control, so all the getters of the ViewModel's bound properties are called one time and the View get populated with the ViewModel's values. When you modify something on the View, that binding carries the modification to the corresponding ViewModel's property (even a simple plain get-set property).

In this case, you're just fine with something like:

public class Person
{
    public string Name { get; set; }
    public string Surname { get; set; }
    //and so on...
}

You need to raise notifications for the ViewModel's properties only if the View must listen to some property's change. For example, this feature: the Button "Save" is enabled if and only if the Name on the Person is not empty. Here, clearly the Button must be able to see when the Name property changes, so that property setter must raise the PropertyChanged event.


A possible implementation:

Use this as base class for ViewModels:

protected abstract BaseViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    protected void SetAndNotifyIfChanged<T>(
        ref T field, T value, [CallerMemberName] string propertyName = null)
    {
        if (!EqualityComparer<T>.Default.Equals(field, value))
        {
            field = value;
            NotifyPropertyChanged(propertyName);
        }
    }
}

In a derived class you can write every get-set property like this:

class MyViewModel : BaseViewModel
{
    public string MyProp
    {
        get { return _MyProp; }
        set { SetAndNotifyIfChanged(ref _MyProp, value); }
    }
    private string _MyProp;
}

The type T and the parameter propertyName are automatically inferred.

This is the shortest piece of code you could write, and is not so different from a normal full-property:

    public string NormalProp
    {
        get { return _ NormalProp; }
        set { _NormalProp = value; }
    }
    private string _MyProp;

If you don't want to write all this code every time, use a code snippet.

Massimiliano Kraus
  • 3,638
  • 5
  • 27
  • 47