1

I have a WPF DataGrid to whose ItemsSource is bound to an ObservableCollection>.

Tuple is a simple class I made that stores 4 strings in an array. Here is a generic version:

public class Tuple<T>: INotifyPropertyChanged
    {
        private int _size = 0;

        public Tuple(int size)
        {
            this._size = size;
            _objs = new T[_size];
        }

        private T[] _objs;

        public T this[int i]
        {
            get
            {
                return _objs[i];
            }
            set
            {
                _objs[i] = value;
                OnPropertyChanged(".[" + i + "]");
            }
        }

        public void OnPropertyChanged(string name)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }

At compile time I know I will have 4 columns and so I bind them to an index of the Tuple. At runtime, Tuples are added to the ObservableCollection and also modified. However, I am running into a problem where my DataGrid only updates when the Tuple is created... That is I get output that looks like this:

enter image description here

The data is present in the ObservableCollection, as if you scroll the DataGrid in and out of view, the text inside the cells appears:

enter image description here

Any tips?

Cramja
  • 65
  • 1
  • 9
  • If its a different dataset, how do you know those blank spaces aren't suppose to be there? – Bob. Aug 15 '13 at 19:57
  • @Bob. updated it to reflect changing the same dataset. Also, I confirmed it using a Watch on my collection and breaking during runtime – Cramja Aug 15 '13 at 20:21
  • ObservableCollection.CollectionChanged event doesn't get triggered when an object inside changes, only when _itself_ changes. See [this answer](http://stackoverflow.com/a/10286028/1466627). – Bob. Aug 15 '13 at 20:31

1 Answers1

2

Your Tuple only updates when it's created as you don't notify that certain index changed but whole indexer property has changed:

public T this[int i]
{
   get { return _objs[i]; }
   set
   {
       _objs[i] = value;
       OnPropertyChanged(Binding.IndexerName);
   }
}

as for the second part where text appears when it comes back into view it's due to VirtualizingStackPanel which by default is true and means that items currently not in the view are not rendered and their bindings are not evaluated until they are in the view again

dkozl
  • 32,814
  • 8
  • 87
  • 89
  • First, this is great. By making the change to the OnPropertyChanged my datagrid updates properly. Am I understanding this correctly: Binding.IndexerName is a string representing the index in my tuple that changed. This string is received by the ObservableCollection's handler which then alerts the DataGrid? – Cramja Aug 15 '13 at 20:46
  • It's just a const string. Since indexer property doesn't have real name Binding class exposes this const so that you can notify binding that something in the indexer has changed – dkozl Aug 15 '13 at 20:57
  • Oh, so it says something like, "some Index of this object has changed" as opposed to: "Index n of this object has changed"? – Cramja Aug 15 '13 at 21:05
  • Yes, that is exactly what it does – dkozl Aug 15 '13 at 21:07