Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React to changes of a view model property in the code behind

Tags:

c#

mvvm

wpf

What is the best way to react on a change of a property named foo of the view model (of unspecified type) in the code behind, assuming the view model implements INotifyPropertyChanged correctly?

Usually one can bind control elements to view model properties and everything works. But in this case, this is not enough and I need to execute some lines of c# when the property changes.

One could listen to the corresponding event of the DataContext, but then, I have also handle changes of the DataContext itself. Another possible solution would be to introduce a DependencyProperty in the code behind file. But isn't there a shorter way?

like image 907
MarkusParker Avatar asked Nov 18 '16 16:11

MarkusParker


2 Answers

I would recommend avoiding this when possible. If it is necessary, subscribe to the PropertyChanged event.

I would put this code in the code behinds constructor.

INotifyPropertyChanged viewModel = (INotifyPropertyChanged)this.DataContext; 
viewModel.PropertyChanged += (sender, args) => {
    if (!args.PropertyName.Equals("foo"))
        return;
    // execute code here.
};

Maintainability tip If you know for sure that the data context is a type that has the property, cast to that type and use the nameof operator rather than a magic string.

Edit (reacting to datacontext changes)

You should be able to subscribe to the DataContextChanged event to handle changes in the data context.

INotifyPropertyChanged previous;
// constructor
public SomeCodeBehindClass()
{
    previous = (INotifyPropertyChanged)this.DataContext;
    DataContextChanged += (sender, args) => SubscribeToFooChanges((INotifyPropertyChanged)args.NewValue);
    SubscribeToFooChanges(previous);
}

// subscriber
private void SubscribeToFooChanges(INotifyPropertyChanged viewModel)
{
    if (previous != null)
        previous.PropertyChanged -= FooChanged;
    previous = viewModel;
    if (viewModel != null)
        viewModel.PropertyChanged += FooChanged;
}

// event handler
private void FooChanged (object sender, PropertyChangedEventArgs args)
{
    if (!args.PropertyName.Equals("foo"))
        return;
    // execute code here.
}
like image 82
Kelson Ball Avatar answered Nov 16 '22 19:11

Kelson Ball


Possible solution, in you code behind you could do this

 (((dynamic)DataContext).foo as ObservableCollection<object>).CollectionChanged += (s, e) =>
        {
            if (e.Action == NotifyCollectionChangedAction.Replace)
            {

            }
            else
            {
               //and so on
            }
        };
like image 37
adminSoftDK Avatar answered Nov 16 '22 21:11

adminSoftDK