Sellorio
Sellorio

Reputation: 1960

Binding in GroupStyle header not updated when collection changes

I have an ItemsControl which is bound to a CollectionViewSource bound to a property on the View Model.

The ItemsControl has a GroupStyle set which looks like this:

<GroupStyle HeaderTemplate="{StaticResource TotalDurationTemplate}" />

Where TotalDurationTemplate is:

<DataTemplate x:Key="TotalDurationTemplate">
    <Border BorderBrush="Black" BorderThickness="0 1" Background="#EEE">
        <Grid>
            <TextBlock HorizontalAlignment="Center"
                                           FontSize="18" FontWeight="Bold"
                                           Text="{Binding Path=Items[0].Start, Converter={StaticResource DateTimeFormatConverter}, ConverterParameter='ddd dd/MM'}" />
            <TextBlock Margin="10 0" HorizontalAlignment="Right" VerticalAlignment="Center"
                                           FontSize="16" Foreground="#9000"
                                           Text="{Binding Items, Converter={StaticResource TotalDurationConverter}}" />
        </Grid>
    </Border>
</DataTemplate>

The issue is that the second TextBlock (the one bound to Items) is not re-evaluated when a new item is added to the View Model's collection (which is an ObservableCollection<>). The item is added to the ListView into the correct group but the Total Duration value is not updated.

The Converter for Total Duration looks like this:

public class TotalDurationConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return
            ((IEnumerable<object>)value)
                .Select(x => ((RecentTimingViewModel)x).Duration)
                .Aggregate((v1, v2) => v1 + v2)
                .TotalHours
                .ToString("F2") + "h";
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new InvalidOperationException();
    }
}

How do I make the binding refresh correctly when the items in the View Model are changed?

EDIT: The Solution

I took Solution 2 from the Accepted Answer and put it into my code. This is what ended up working:

<DataTemplate x:Key="TotalDurationTemplate">
    <Border BorderBrush="Black" BorderThickness="0 1" Background="#EEE">
        <Grid>
            <TextBlock HorizontalAlignment="Center"
                       FontSize="18" FontWeight="Bold"
                       Text="{Binding Path=Items[0].Start, Converter={StaticResource FormatDateIntelligentConverter}}" />
            <TextBlock Margin="10 0" HorizontalAlignment="Right" VerticalAlignment="Center"
                       FontSize="16" Foreground="#9000">
                <TextBlock.Text>
                    <MultiBinding Converter="{StaticResource TotalDurationConverter}">
                        <MultiBinding.Bindings>
                            <Binding Path="Items" />
                            <Binding Path="Items.Count" />
                        </MultiBinding.Bindings>
                    </MultiBinding>
                </TextBlock.Text>
            </TextBlock>
        </Grid>
    </Border>
</DataTemplate>

And changing TotalDurationConverter to IMultiValueConverter. The just ignore the second item in the Array.

Upvotes: 3

Views: 94

Answers (1)

Vishal Harne
Vishal Harne

Reputation: 191

So two possibilities and if you can try below simple solutions and let me know if it works.

Solution 1 - a very simple and basic one since you are using a textbloxk set the mode explicitly to Two way. I guess TextBlock default binding mode is One way.

Solution 2 - I have faced similar issue working with a combo box- here is a work around which worked for me For the second Text block use Multi Binding, first bind it to List as you have already done, second bind it to any property in View Model which will be triggered when your list is getting changed (example an int property returning List.Count) - This second dummy property will make sure that your converter is re evaluated.

I guess second option should work for you.

Let me know if it doesn't work.

regards, Vishal

Upvotes: 1

Related Questions