views:

93

answers:

5

Hi I just recently discovered an INotifyPropertyChange interface. I managed to implement this interface in my clss and everything works fine. However I was wondering if it is possible to intercept this event in code and fire a function Let's say that I have a function

DoStuff()

and I wan't to fire this function everytime property1, property2 or property3 changes. Of course I could put this function in set block in my class but this is not a good idea(I think).

+1  A: 

If you mean to internal method that'll handle this event you can do it by registering to the event in the class constructor. For example:

public class AnswerViewModel : IAnswerViewModel
{
    public event PropertyChangedEventHandler PropertyChanged;

    private string content;

    public AnswerViewModel()
    {
        PropertyChanged += (sender, args) => DoStuff();
    }

    public string Content
    {
        get { return content; }
        set
        {
            content = value;
            PropertyChanged(this, new PropertyChangedEventArgs("Content"));
        }
    }

    public void DoStuff()
    {
        // this method will be called whenever PropertyChanged event raised
    }
}

If the intercepting method belongs to other class:

public class PropertiesInterceptor
{
    private readonly AnswerViewModel viewModel;

    private readonly List<string> propertiesToIntercept =
        new List<string> { "property1", "property2", "property3" };

    public PropertiesInterceptor(AnswerViewModel viewModel)
    {
        this.viewModel = viewModel;
        viewModel.PropertyChanged += OnPropertyChanged;
    }

    private void OnPropertyChanged(object sender, PropertyChangedEventArgs args)
    {
        if (propertiesToIntercept.Contains(args.PropertyName))
        {
            DoStuff();
        }
    }

    private void DoStuff()
    {
        // Do something with viewModel
    }
}
Elisha
You may want to change your event to `PropertyChanged += (sender, args) => if(args.PropertyName == "property1" || args.PropertyName == "property2" || args.PropertyName == "property3") DoStuff();`
Scott Chamberlain
Hmm what if I the function I want to call is in other class?
Berial
@Berial, added example usage to interception from different class than the one raising the `PropertyChanged`
Elisha
@Scott Chamberlain, you're right, the example I posted doesn't filter the changed properties :) Updating my example.
Elisha
I suppose this "viewModel.PropertyChanged += (sender, args) " is some kind of LINQ code. I don't know LINQ good enough to understand this. Could You write it in regular c# please ? It would be more clear for me
Berial
@Berial, it's a lambda expression which is a syntax from writing anonymous methods. I updated the second example to register a named method instead of the lambda expression.
Elisha
A: 

Did you need it to replace the existing NotifyPropertyChanged event handlers, or just get called when NotifyPropertyChanged is called?

If you mean the second, you can simply register an event handler

edit

You can add an event handler that gets called on NotifyPropertyChanged, checks if the property parameter is equal to Property1, Property2, or Property3, and only then forwards it to the actual function you want to call.

Merlyn Morgan-Graham
I need to call function when NotifyPropertyChanged is called - but only if Property1,Property2 or Property3 was changed
Berial
A: 

You could fire the method from a RaisePropertyChanged() method:

public int Property1
{
    get { return this.property1; }
    set
    {
        if (this.property1 != value)
        {
            this.property1 = value;
            RaisePropertyChanged("Property1");
        }
    }
}

private void RaisePropertyChanged(string propertyName)
{
     if (PropertyChanged != null)
     {
         PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
     }

     DoStuff(); // Call DoStuff here.
}
Groky
A: 

Stealing Elisha's answer to answer your question in Merlyn's answer

public class AnswerViewModel : IAnswerViewModel
{
    public event PropertyChangedEventHandler PropertyChanged;

    private string property1;
    private string property2;
    private string propertyX;

    public AnswerViewModel()
    {
        PropertyChanged += (sender, args) => 
        {
            if(args.PropertyName == "Property1" || args.PropertyName == "Property2")
                DoStuff();
        }
    }

    public string Property1
    {
        get { return content; }
        set
        {
            property1 = value;
            PropertyChanged(this, new PropertyChangedEventArgs("Property1"));
        }
    }
    public string Property2
    {
        get { return content; }
        set
        {
            property2 = value;
            PropertyChanged(this, new PropertyChangedEventArgs("Property2"));
        }
    }
    public string PropertyX
    {
        get { return content; }
        set
        {
            propertyX = value;
            PropertyChanged(this, new PropertyChangedEventArgs("PropertyX"));
        }
    }

    public void DoStuff()
    {
        // this method will be called whenever PropertyChanged event raised from Property1 or Property2
    }
}

If the class DoStuff is in is a member you can do

    private otherClass
    public AnswerViewModel()
    {
        PropertyChanged += (sender, args) => 
        {
            if(args.PropertyName == "Property1" || args.PropertyName == "Property2")
                otherClass.DoStuff();
        }
    }

Otherwise you can just have otherClass register a event on its own in your main code.

Scott Chamberlain