3

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.

4

1 回答 1

1

所以有两种可能性,如果你可以尝试以下简单的解决方案,让我知道它是否有效。

解决方案 1 - 一个非常简单和基本的解决方案,因为您使用的是 textbloxk,将模式显式设置为双向。我猜 TextBlock 默认绑定模式是一种方式。

解决方案 2 - 我在使用组合框时遇到了类似的问题 - 这是一个对我有用的解决方法 对于第二个文本块使用多重绑定,首先将它绑定到列表,就像你已经完成的那样,然后将它绑定到中的任何属性查看模型将在您的列表发生更改时触发(例如返回 List.Count 的 int 属性)-第二个虚拟属性将确保重新评估您的转换器。

我想第二个选项应该适合你。

让我知道它是否不起作用。

问候, 维沙尔

于 2016-07-07T06:25:29.677 回答