OnPropertyUpdate Schennanigans

The WPF application I’m working on at the moment has functionality to display multiple chart windows in a main application window page. The chart windows can be resized and moved around inside their window. I wanted to take the resizing and positioning behavior and abstract it so could apply it to other types of child windows besides just charts.

The application structure is based on an MVVM approach so this mean taking the positional pieces of a ‘ChartViewModel’ and abstracting them into a ‘PositionalViewModelBase’ that the ‘ChartViewModel’ and any other view models that would back views that are placed and manipulated on a page would inherit from.

To keep the view models agnostic to their views and to allow positioning change driven by business logic instead of just user interaction, the ‘INotifyPropertyChanged’ interfaced is implemented by the ‘PositionalViewModelBase’ type. What goofed me up was that I had to override the positional properties in the ‘ChartViewModel’ because the ‘ChartViewModel’ data is backed up by a persistence class specific to the ‘ChartViewModel’. I wanted to keep the ‘PropertyChanged’ event code in the base class though, so I came up with the below, using just width as an example:

//--base Positional class behavior.
 public virtual double Width
        {
            get { return this._Width; }
            set
            {
                this._Width = value;
                this.OnPropertyChanged("Width");
                SetParentDirty();
            }
        }


//--chart view model override
 public override double Width
        {
            get
            {
                return this.Model.Width;
            }
            set
            {
                base.Width = value;    //--What turned out to be the issue
                this.Model.Width = value;       
            }
        }

I set the property in the actual data class and the base, I do this so the base can handle setting the parent dirty and firing the changed event. However, I goofed. My chart windows were freaking out when I resized them. After investigating many conspiracy theories and trying to find ways to blame someone else, I realized my error. First I didn’t have any unit tests confirming the behavior, I just assumed it worked.

After adding a unit test I realized that when the property changed event was fired the property showed the old value? The test led me quickly to spot my error. I was setting the base value, and causing property changed event to get fired, before updating the actual data store. Any code fired by the property changed event that wanted the new value, actually got the old one, since I had not updated the data store yet. Dooh!

    
 public override double Width
        {
            get
            {
                return this.Model.Width;
            }
            set
            {
                 this.Model.Width = value;     //--setting data store first fixed problem
                base.Width = value;  
                
            }
        }

The PropertyChanged event driven behavior can be tricky to debug since flow of behavior is not immediately evident. This is why testing it even more important, and hopefully the lesson I have learned here is to test first better. As usual I didn’t save time by not testing adequately, I lost time.

Making UI Notice Change in ObservableCollection Item

I’ve been doing a lot of WPF work lately. I’m getting my head more and more around binding, especially binding to ObservableCollections. It’s interesting how the binding in XAML automagically detects additions and deletions to a collection and updates the UI appropriately. However, I ran into an issue where the update was not to the collection itself, but to item in the collection.

As an example suppose you had the ItemSource of a listbox bound to an ObervableCollection of ‘Coach’ objects.

<ListBox x:Name="lbCoaches"  
                         VerticalAlignment="Stretch" 
                         HorizontalAlignment="Stretch" 
                         DockPanel.Dock="Top"
                         ItemsSource="{Binding Path=Coaches}"
                         SelectedItem="{Binding Path=ActiveCoach}" >
      <ListBox.ItemTemplate>
      <DataTemplate>
            <StackPanel  Orientation="Horizontal">
                <TextBlock Text="{Binding Path=LastName}"></TextBlock>
                <TextBlock Text="{Binding Path=FistName}"></TextBlock>
                <TextBlock Text="{Binding Path=Age}" ></TextBlock>
            </StackPanel>
        </DataTemplate>
       </ListBox.ItemTemplate>
<ListBox>

If you add, or delete, or move a coach in the collection no problem, listbox items are updated. If you change a coaches last name, nothing. I realized that in order to get the binding to update I had to force the UI to know the ObservableCollection updated. I initially tried firing OnPropertyChanged on the collection, but that did not seem to do anything. What I realized what I needed to allow for checks to changes to the items themselves. I could have put a data trigger in place to do this, and I may yet go that route. I think for large lists this is the way to go. For my purposes, since my lists were small, I just cleared and rewrote this lists, hence forcing the UI to realize the collection had changed. Thanks to LINQ I can do this in very few lines.

    //-- coaches is observablecollection backing listbox.
     Coaches[0].LastName = "Thompson";
     var newList = Coaches.ToList();
     Coaches.Clear();
     newList.ForEach(item => Coaches.Add(item));

I think the data trigger is probably the right way to go. The above code will probably confuse people reviewing it and feels like a hack to me. Glad I thought about it, I’ll probably change it now that I was forced to think it through for this post.