How do I use INotifyPropertyChanged in WinRT?

2020-08-01 07:41发布

问题:

I'm a total newbie, just learning the basics of DataContext and the MVVM model. I've now got a grid bound to a view model object which implements INotifyPropertyChanged, however it appears that UpdateSourceTrigger (which all the WPF tutorials tell me to use) is not available for WinRT / Metro Style apps!

How do I implement INotifyPropertyChanged then?

I'm at the end of my tether here. I've spend nearly the whole day on the most basic of app examples, simply trying to get a grid to update after I click something. The only way I've managed to do this so far is to create an entirely new instance of the view model and reassign the DataContext which I know is wrong

UPDATE:

I have made some progress, but things have gotten very weird. I have a view model, with a generic list of items. The items list is wired up with a PropertyChangedEventHandler. If I replace the entire collection with a new one, the listview updates.

model.Items = new List<DataItem>{ new DataItem{ Title = "new item" }};

This results in a one item list with the above item. However, if I try adding an item, nothing happens

model.Items.Add(new DataItem{ Title = "added item" });

I also tried creating a method which added an item and specifically fired PropertyChanged, but that also doesn't work

Here's where it gets weird. Next I tried this code.

model.Items.Add(new DataItem { Title = "added item" });
model.Items = new List<DataItem> { new DataItem { Title = "new item" }}; 

This results in a two item list:

- new item
- added item

How can this be? The code says, "add one item" then "replace the whole list" but it executes in the reverse order?

UPDATE 2:

I've switched to ObservableCollection as suggested, which has actually solved the original problem. I can now add an item and it shows up on the list.

However, the new weird behaviour is still in effect. Items added before the collection is reset are appended to the end of the new collection. Why is my code executing in reverse order?

回答1:

You need to implement the interface and send out the notification once the given property you care about changes.

        public event PropertyChangedEventHandler PropertyChanged;

        public string CustomerName
        {
            get
            {
                return this.customerNameValue;
            }

            set
            {
                if (value != this.customerNameValue)
                {
                    this.customerNameValue = value;
                    if (PropertyChanged != null)
                    {
                        PropertyChanged(this, new PropertyChangedEventArgs("CustomerName"));
                    }
                }
            }
        }

Keep in mind that for a collection, you should use an ObservableCollection as it will take care of the INotifyCollectionChanged being fired when an item is added or removed.

I would suggest to scale your sample back as far as possible. Don't start with a DataGrid but rather a simple TextBoxand Button, where the Button forces a change in your ViewModel which will then reflect on the UI.



回答2:

Code taken from here.

It's best to implement a parent class which implements it like this:

public class NotifyPropertyChangedBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged = delegate { };

    protected void RaisePropertyChanged(string propertyName)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

And then in your subclass (i.e. ViewModel) in your property do something like this:

public class MyViewModel : NotifyPropertyChangedBase
{
    private string _name;
    public string Name {
      get{ return _name; }
      set{ 
       _name = value;
       RaisePropertyChanged("Name");
      }
    }
}