2009-10-22 63 views
2

我将CollectionViewSource绑定到ListView以分组项目。这一切都很好,除非我更新ObservableCollectionCollectionViewSource是基于。如果我更新集合中的对象的值,UI永远不会更新。这里是一个例子:使用CollectionViewSource和DataBinding进行WPF分组

<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> 

你会注意到它调用了一个转换器在组中,并给它的项目集合。这是为了让转换器可以计算的平均行并返回结果:

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(); 
    } 
} 

后面的代码中我添加行和创建CollectionViewSource

私人只读的ObservableCollection displayRows =新的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,并且仅仅是一个简单的类。

一切正常,显示器是我想要的方式,但如果我更改ObservableCollection中的值,则UI不会更改。

如果我添加一个元素到集合中,我可以看到它出现在屏幕上,但转换器永远不会被调用来重新计算平均值。有任何想法吗?

回答

4

我发现了解决这个问题的方法。

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(); 
} 

希望有帮助。

+0

不错。是的,它确实有帮助。不幸的是,我需要更新整个事情,但至少它让我受到这个问题的困扰。谢谢。 – Kelly 2009-10-26 15:47:44

1

如果数据源是一个ObservableCollection,无论何时当有添加或删除它的项目集合更改即视图将被更新。如果希望在编辑底层数据时更新视图,那么该类必须实现INotifyPropertyChanged接口。

在你的情况DisplayRow类必须实现INotifyPropertyChanged和displayRows应该是一个ObservableCollection。

这是官方的做法,从我的理解。我可能错了。