tags:

views:

101

answers:

3

I haven't implement this pattern for a while (and when I did it was in 2, as opposed to 3), and I have several examples that all seem straight forward, but I can't work out what I have done wrong in the below piece of code (The Items are not updated when the property event fires):

public partial class Index : Page
{
    private IndexViewModel _vm;

    public Index()
    {
        InitializeComponent();
        _vm = new IndexViewModel(19);           

        this.TheDataGrid.ItemsSource = _vm.Rows;
    }




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

        protected virtual void OnPropertyChanged(PropertyChangedEventArgs e) 
        {          
            this.PropertyChanged(this, e); 
        }

public SortableCollectionView Rows 
        { 
            get
        {
            return _rows;
        }
        set
        {
            if (_rows == value) 
                return;

            _rows = value;
            this.OnPropertyChanged(new  PropertyChangedEventArgs("Rows"));                                
        }
    }

This does not refresh my datagrid... as a 'hack' I have had to pass the datagrid object into my viewmodel and bind it there:

public IndexViewModel(int containerModelId, DataGrid shouldNotNeed)
        {
            ContainerModelId = containerModelId;

        LoadOperation<vwColumn> headings = _ttasContext.Load(_ttasContext.GetRecordColumnsQuery(ContainerModelId));
        headings.Completed += (sender2, e2) =>
        {
            //load data
            LoadOperation<vwDataValue> data = _ttasContext.Load(_ttasContext.GetRecordsQuery(ContainerModelId, null));
            data.Completed += (sender3, e3) =>
            {

                    Rows = FormatData(data, headings);
shouldNotNeed.ItemsSource = Rows;
                };
            };
        }
+2  A: 

Assigning _vm.Rows to TheDataGrid.ItemsSource does not wire any change notification callback automatically. Try this: in xaml:

<... x:Name=TheDataGrid ItemsSource={Binding Rows}>

In code:

this.DataContext = _vm;
Codism
A: 

As Codism points out your main problem is you need to use binding to take advantage of an INotifyPropertyChanged. However I would recommend this implementation pattern:-

public event PropertyChangedEventHandler PropertyChanged;

void NotifyPropertyChanged(string name) 
{          
   if (PropertyChanged != null)
     PropertyChanged(this, new PropertyChangedEventArgs(name); 
}

...

  set 
  {
     if (_rows != value)
     {
        _rows = value;
        NotifyPropertyChanged("Rows");
     }
  }

Note that this approach minimises the impact on a an object instance whose properties are not being observed. In the original pattern you create instances of PropertyChangedEventArgs and calls to the event delegate going off regardless of whether anything is actually listening.

AnthonyWJones
I read in another post somewhere that if you had the = delegate { } at the end of the declaration you did not need to have the if (property changed != null)However, even if that is the case you comment does hight that the code is less clear, so I have changed it back, thanks!
Grayson Mitchell
@Grayson: Yes there is some advantage to that delegate {} trick however the normal pattern for events in general is to use an "OnXXXX" virtual protected method that receives the appropriate EventArgs object. The problem with that approach for INotifyPropertyChanged is that property values can change rapidly (for example when being animated). This could cause a massive amount of PropertyChangedEventArgs instances to be created yet nothing is listening, this in turn would create an unnecessary burden on the GC.
AnthonyWJones
A: 

this.TheDataGrid.ItemsSource = _vm.Rows

When a collection is assigned as the ItemsSource of a DataGird , any changes made to the collection can be observed by the DataGrid if the source implements INotifyCollectionChanged.
From your code sample , I can't tell if the type SortableCollectionView implements INotifyCollectionChanged or inherits from ObservableCollection.
Implementing INotifyCollectionChanged would mean that you can't reset the backing field _rows for property Rows , you can clear items in the collection and add them as needed.
Hope this helps

Phani Raj