WPF DataGrid绑定的分组项目触发得太晚了

时间:2015-05-28 12:28:18

标签: c# wpf xaml datagrid

我正在使用WPF DataGrid来显示已经分为两级的数据。大多数XAML /代码都基于https://msdn.microsoft.com/en-us/library/ff407126%28v=vs.110%29.aspx上的MSDN示例。

除了这个例子,我还在每个第二级分组下面添加了一个摘要行来进行一些求和。用户能够更改影响一个或多个汇总的行。每次用户进行更改时,应直接重新评估摘要,以便查看更改的结果。

除摘要行更新外,所有功能都可以正常工作。在用户更新网格内的字段之后,不会重新评估总和。实际上,并不触发求和的绑定来调用转换器进行新的求和。我发现通过单击鼠标将焦点更改为DataGrid的另一部分(在更改的行之外!)时,触发器就会出现。

让我澄清一下我的XAML /代码的相关部分......

为了获取属于该组的行,我绑定到Items属性并将它们发送到转换器。在XAML中,此摘要行显示在元素的元素中:

<GroupStyle.ContainerStyle>
    <Style TargetType="{x:Type GroupItem}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type GroupItem}">
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*" />
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="20" />
                            <RowDefinition Height="1*" />
                            <RowDefinition Height="20" />
                        </Grid.RowDefinitions>

                        <TextBlock Grid.Row="0"
                                    Text="{Binding Path=Name}"
                                    FontWeight="Bold" FontSize="13"
                                    TextAlignment="Left" Margin="5,0,0,0"/>
                        <ItemsPresenter Grid.Row="1" />

                        <!-- Grid that represents the summary row -->
                        <Grid Grid.Row="2">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="100" />
                                <ColumnDefinition Width="*" />
                            </Grid.ColumnDefinitions>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="*" />
                            </Grid.RowDefinitions>
                            <!-- for simplicity, only one summation field-->
                            <!-- This binding isn't updated unless I change focus somewhere outside the edited row -->
                            <TextBlock Grid.Column="0" Margin="0,0,-2,0" HorizontalAlignment="Right" FontWeight="Bold" Text="{Binding Path=Items, 
                                        Converter={StaticResource decimalGroupSumConverter}, ConverterParameter=AmountPerYear}"/>
                        </Grid>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</GroupStyle.ContainerStyle>

调用求和的转换器:

public class DecimalGroupSumConverter : IValueConverter
{

    public object Convert(object value, System.Type targetType,
                          object parameter,
                          System.Globalization.CultureInfo culture)
    {
        if (null == value)
            return "null";

        ReadOnlyObservableCollection<object> items =
              (ReadOnlyObservableCollection<object>)value;

        if (parameter.ToString() == "AmountPerYear")
        {
            var sum = (from i in items
                       select ((ObservableCalculatedActivity)i).AmountPerYear).Sum();
            return string.Format("{0:c}", sum);

        }
        else
        {
            return null;
        }
    }

    public object ConvertBack(object value, System.Type targetType,
                              object parameter,
                              System.Globalization.CultureInfo culture)
    {
        throw new System.NotImplementedException();
    }
}

下一个列表显示我试图强制UI更新但没有任何成功:

请帮助我解决有关更新UI的这个微小但非常烦人的问题吗?

2 个答案:

答案 0 :(得分:0)

目前,您的绑定设置为在焦点丢失时更新绑定属性。要解决此问题,只需将UpdateSourceTrigger添加到绑定中即可。

Text="{Binding Path=Items, UpdateSourceTrigger=PropertyChanged ...

一旦属性发生变化,这将强制调用INotifyPropertyChanged,因此也会调用Converter。

答案 1 :(得分:0)

我发现当用户调整数据网格中的字段时,底层集合处于编辑模式。这些更改保留在内存中的某个位置,并且尚未刷新到我的XAML中组级别的绑定Items集合。要刷新更改并触发Items绑定,只需执行提交。在我的情况下,我首先必须将ICollectionView转换为ListCollectionView:

ICollectionView collectionView;
((ListCollectionView)collectionView).CommitEdit();
collectionView.Refresh();

不幸的是,提交时会产生副作用:相关字段离开编辑模式,用户应再次点击两次以进入编辑模式。