I try to grasp the essence of MVVM, considering the simplest examples and I do not understand some things, such as:

public event PropertyChangedEventHandler PropertyChanged; public void OnPropertyChanged([CallerMemberName]string prop = "") { if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(prop)); } 

It is also not clear how the INotifyPropertyChanged interface INotifyPropertyChanged Can anyone explain all this? PS on MSDN and other sites was and read, but it did not become clearer

  • And what you do not understand in this example? - Vlad
  • @Vlad Interfaces, Classes, Methods - Draktharon

2 answers 2

I'll try to explain.

Between the View (the graphical interface of the program (buttons, text fields, and so on.)) Using the so-called bunding (someone calls the binding, although this is a wrong pronunciation) a connection is established with the properties in the ViewModel. For example, we associate a property (ViewModel) with a text input field - public string Name { get; set; } public string Name { get; set; } public string Name { get; set; } using an entry in XAML (View) <TextBox Text="{Binding Name, Mode=TwoWay}" . In order to be able to notify the textbox that the data in the Name property has changed (for example, during any calculations) and the textbox "re-read" the data from Name in the set; block set; This variable needs to trigger the PropertyChanged event.

To do this, the ViewModel implement (inherit) from the standard INotifyPropertyChanged INotifyPropertyChanged . In your example, one of the following variants is used:

public event PropertyChangedEventHandler PropertyChanged; - Actually the announcement of the desired event.

public void OnPropertyChanged([CallerMemberName]string prop = "") is a helper method for triggering this event from the set; block set; .

[CallerMemberName] is an attribute of the parameter that allows you not to specify the name of the property to the programmer, the compiler will itself substitute the name of the property that calls the OnPropertyChanged method, i.e. You can call OnPropertyChanged("Name") or OnPropertyChanged() and then ("Name") compiler will replace you.

Further, in the method itself, the verification takes place; and if this event has subscribers? And if there are any (we have <TextBox Text="{Binding Name, Mode=TwoWay}" ), the event is called with transmission as arguments: the class that calls this event and the name of the property that has changed.

Such a variant of invoking an event is not the only one; on the Internet and in books one can find another couple of options. All this is a matter of taste. Personally, I love the direct challenge of the event, which is called head-on, I will show with an example, maybe it will become even clearer to you.

 public class MainViewModel : INotifyPropertyChanged //не забываем о наследовании 

We assign an empty delegate in the announcement of the event, so that later we don’t do the checking, and if there are any signatories to the event? They now always have at least one empty signer.

 public event PropertyChangedEventHandler PropertyChanged = delegate { }; 

And here is an example of a property with a call to this event (using the new nameof() construction to pass the property name)

 /// <summary> /// Имя скачиваемого видео файла /// </summary> private string _NameFileVideo; public string NameFileVideo { get { return _NameFileVideo; } set { if (_NameFileVideo == value) return; _NameFileVideo = value; PropertyChanged(this, new PropertyChangedEventArgs(nameof(NameFileVideo))); } } 

    I suspect that the main thing that scares you in this code is events.

    I'm not sure what it will be clear to explain, but I'll try to draw an analogy.

    Every day there are many events in the world, both global and local. But you will never know about most of them for the simple reason that they are not interesting to you. You only want to know the news that is important to you and your loved ones. Thus, by placing a "filter" you subscribe only to the events of interest to you - for example, the news of astronautics. The same thing makes the control of your application through the interface INotifyPropertyChanged . In other words, for the control this is the filter on the subject of news from the object. If the object has not implemented the interface, then it is not interesting to it.

    As for the data binding ( Binding ) ... if we take the analogy further, it will already be a more specific filter (for example, you are only interested in news from Mars). So the control is interested in actual data only from those properties of the object with which it works directly and it does not know anything and does not want to know about everything else that happens in your class.

    When you change the value of a property in code, it is already an event. But neither the control nor anyone else knows anything about it. That is why when you want to "publish" the news you write:

     OnPropertyChanged("Название свойства") 

    and the control that subscribed to receive news about this property will respond properly.


    The CallerMemberName attribute simply allows you to get the name of the method or property of the object that calls the method. In this case, it is used to avoid possible errors associated with the wrong name of the property to be updated.