tags:

views:

44

answers:

3

Hi all,

I have a label like this:

<Label Name="LblUsersWithHair">
    <Binding Path="Users" 
             ElementName="ElementSelf" 
             Converter="{StaticResource Converter_UsersWithHairPresenter}" />
</Label>

And the converter:

...

public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
    var users = value as ObservableCollection<Users>;
    if (users == null) return null;

    var usersWithHair = users.Count(user => user.HasHair == true);
    return "There are " + usersWithHair + " there has hair.";
}

...

The problem is now that the label of course isn't updated when the 'HasHair' property is changed, since the collection isn't changed. But how do I force the label to rebind, when this property is set?

The example above is very simplified, but hope that you can help me... :o)

+2  A: 

You'll need to implement INotifyPropertyChanged in your Users class for the HasHair property.

Check this post How to force ListBox to reload properties of ListBoxItems

Mike
Since your binding is to the actual collection, the converter will most likely only get fired whan the Collection itself changes. Without implementing INotifyPropertyChanged in the Users class, the ObservableCollection will not update when the properties of one of the Users items has changed, only when the number of Users items changes.
Mike
A: 

Mike is likely on target. The framework needs some way to know when a property has changed and INPC (INotifyPropertyChanged ) exists for just this reason. I say likely right because in this situation you are using an ObservableCollection which has INPC baked into it, and I am guessing you are adding / subtracting from the list based on the user checking something bound to HasHair. Please post your code and what you think should be happening if you are still having trouble.

While your at it, you can shorten up that label declaration to just:

<Label Content="{Binding Users, Converter={StaticResource Converter_UsersWithHairPresenter}"/>

You can also place a debug breakpoint inside of your converter and see firstly whether it's even being called, and also check your output window to see if any data binding errors are being reported.

HTH,
Berryl

Berryl
+1  A: 

Your Binding will only update, if the list fires a ListChanged-event. This does usually only occur on structural changes (add/remove/replace) in the list, not if a single list item changes - even if it does implement INotifyPropertyChanged. After you have implemented INotifyPropertyChanged for your item, you will still need to do one of the following two options:

  • Use a modified ObservableCollection, that listens to the PropertyChanged-Event of any item within (register on add/remove) and fires ListChanged on any Change.
  • Create a CollectionViewSource with a filter-predicate that evaluates HasHair, then bind your label to the item-count of this CollectionViewSource instead of the original list.
Simpzon
I have an app that has a ObservableCollection of a Custom type, and all i had to do was implement the INotifyPropertyChanged on the custom class, and the DataGrid updates properly when I change the items underneath through the binding, without doing anything extra. My app is written in WPF, so if the OP's app is in Silverlight, I don't know if it behaves different or not.
Mike
Yeah, your grid-row does update, because the DataGrid is an ItemsControl and each row implicitly creates a binding to the corresponding list-item.But a ContentControl (as the label) bound to the list (not the changed list-item) will not update on PropertyChange of a list-item.
Simpzon
oh ok. I see what you're saying. I've never tried it on anything other than DataGrids or TreeViews. Learn something new every day...
Mike