代码之家  ›  专栏  ›  技术社区  ›  Kelly

使用CollectionViewSource和数据绑定进行WPF分组

  •  2
  • Kelly  · 技术社区  · 15 年前

    我正在装订 CollectionViewSource ListView 分组项目。除了我更新了 ObservableCollection 这个 集合视图源 是基于。如果更新集合中对象的值,则永远不会更新UI。下面是一个例子:

    <ListView x:Name="MyListView" Margin="0,0,0,65">
        <ListView.GroupStyle>
            <GroupStyle>
                <GroupStyle.ContainerStyle>
                    <Style TargetType="{x:Type GroupItem}">
                        <Setter Property="Margin" Value="0,0,0,5"/>
                        <Setter Property="Template">
                            <Setter.Value>
                                <ControlTemplate TargetType="{x:Type GroupItem}">
                                    <Expander IsExpanded="true" BorderBrush="#FFA4B97F" BorderThickness="0,0,0,1">
                                        <Expander.Header>
                                            <DockPanel>
                                                <TextBlock FontWeight="Bold" Text="{Binding Name}" Margin="5,0,0,0" Width="80"/>
                                                <TextBlock FontWeight="Bold" Width="60" TextAlignment="Center" Margin="16,0,0,0" Text="{Binding Items, Converter={StaticResource Converter2}}" />
                                            </DockPanel>
                                        </Expander.Header>
                                        <ItemsPresenter />
                                    </Expander>
                                </ControlTemplate>
                            </Setter.Value>
                        </Setter>
                    </Style>
                </GroupStyle.ContainerStyle>
            </GroupStyle>
        </ListView.GroupStyle>
        <ListView.View>
            <GridView>
                <GridViewColumn Width="300" Header="Amount" >
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding Amount}" Margin="80,0,0,0"/>
                        </DataTemplate>
                     </GridViewColumn.CellTemplate>
                </GridViewColumn>
            </GridView>
        </ListView.View>
    </ListView>
    

    您会注意到它正在调用组中的转换器并将items集合提供给它。这样转换器就可以计算行的平均值并返回结果:

    public class AverageConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            IEnumerable<object> rows = (IEnumerable<object>) value;
            double average = rows.Average(a => ((DisplayRow) a).Amount);
            return average;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    

    在后面的代码中,我添加行并创建 集合视图源 :

    private readonly observableCollection displayRows=new observableCollection();

    public Window1()
    {
        InitializeComponent();
    
        displayRows.Add(new DisplayRow { Title = "Sales", Amount=16} );
        displayRows.Add(new DisplayRow { Title = "Marketing", Amount=14} );
        displayRows.Add(new DisplayRow { Title = "Technology", Amount=13} );
        displayRows.Add(new DisplayRow { Title = "Sales", Amount=11} );
        displayRows.Add(new DisplayRow { Title = "Marketing", Amount=13} );
        displayRows.Add(new DisplayRow { Title = "Technology", Amount=12} );
        CollectionViewSource viewSource = new CollectionViewSource { Source = displayRows };
        viewSource.GroupDescriptions.Add(new PropertyGroupDescription("Title"));
        MyListView.ItemsSource = viewSource.View;
    }
    

    这个 DisplayRow 对象实现 INotifyPropertyChanged 只是一个简单的类。

    一切正常,显示方式是我想要的,但是如果我在 可观测采集 用户界面不变。

    如果我将一个元素添加到集合中,我可以看到它出现在屏幕上,但从未调用转换器来重新计算平均值。有什么想法吗?

    3 回复  |  直到 15 年前
        1
  •  4
  •   Tri Q Tran    15 年前

    我找到了解决这个问题的方法。

    private CollectionViewSource _viewSource;
    
    private void ModifyData()
    {
        // Modify some data
    
        // This will cause the ListView to refresh its data and update the UI
        // and also cause the converter to be called to reformat the data.
        _viewSource.View.Refresh();
    }
    

    希望有帮助。

        2
  •  2
  •   Amir Burbea    15 年前

    如果不刷新整个视图,这仍然可以处理,我实现了这个。

    在CollectionView内创建数据绑定将允许组的更改通知。

    退房 http://stumblingaroundinwpf.blogspot.com/2009/11/building-smarter-wpf-collectionview-one.html

        3
  •  1
  •   Paul Pantea    13 年前

    如果数据源是一个可观察的集合,则每当集合更改时(即添加或删除其中的项时),视图都会更新。如果希望在编辑基础数据时更新视图,则该类必须实现inotifyPropertyChanged接口。

    在您的情况下,DisplayRow类必须实现InotifyPropertyChanged,并且DisplayRows应该是一个ObservableCollection。

    据我所知,这是官方的做法。我可能错了。

    推荐文章