集合视图

基于绑定源集合,它允许基于排序、筛选和分组查询来导航并显示源集合,而无需更改基础源集合本身。 集合视图还维护一个指向集合中当前项的指针。 

创建并使用视图的一种方式是直接实例化视图对象,然后将它用作绑定源。

<Window.Resources>
    <CollectionViewSource 
      Source="{Binding Source={x:Static Application.Current}, Path=AuctionItems}"   
      x:Key="listingDataView" />
</Window.Resources>

<ListBox Name="Master" Grid.Row="2" Grid.ColumnSpan="3" Margin="8" 
         ItemsSource="{Binding Source={StaticResource listingDataView}}" />

若要为同一集合创建另一个视图,则可以创建另一个 CollectionViewSource 实例,并为其提供不同的 x:Key 名称。

下表显示作为默认集合视图创建或由 CollectionViewSource 根据源集合类型创建的视图数据类型。

表 2
源集合类型集合视图类型说明
IEnumerable 基于 CollectionView 的内部类型 无法对项进行分组。
IList ListCollectionView 最快。
IBindingList BindingListCollectionView  

排序

private void AddSortCheckBox_Checked(object sender, RoutedEventArgs e)
{
    // Sort the items first by Category and then by StartDate
    listingDataView.SortDescriptions.Add(new SortDescription("Category", ListSortDirection.Ascending));
    listingDataView.SortDescriptions.Add(new SortDescription("StartDate", ListSortDirection.Ascending));
}

筛选

private void AddFilteringCheckBox_Checked(object sender, RoutedEventArgs e)
{
    if (((CheckBox)sender).IsChecked == true)
        listingDataView.Filter += ListingDataView_Filter;
    else
        listingDataView.Filter -= ListingDataView_Filter;
}
private void ListingDataView_Filter(object sender, FilterEventArgs e)
{
    // Start with everything excluded
    e.Accepted = false;

    // Only inlcude items with a price less than 25
    if (e.Item is AuctionItem product && product.CurrentPrice < 25)
        e.Accepted = true;
}

分组

// This groups the items in the view by the property "Category"
var groupDescription = new PropertyGroupDescription();
groupDescription.PropertyName = "Category";
listingDataView.GroupDescriptions.Add(groupDescription);
<Window.Resources>

  <src:Places x:Key="places"/>

  <CollectionViewSource Source="{StaticResource places}" x:Key="cvs">
    <CollectionViewSource.SortDescriptions>
      <scm:SortDescription PropertyName="CityName"/>
    </CollectionViewSource.SortDescriptions>
    <CollectionViewSource.GroupDescriptions>
      <dat:PropertyGroupDescription PropertyName="State"/>
    </CollectionViewSource.GroupDescriptions>
  </CollectionViewSource>

<ListBox ItemsSource="{Binding Source={StaticResource cvs}}"
         DisplayMemberPath="CityName" Name="lb">
  <ListBox.GroupStyle>
    <x:Static Member="GroupStyle.Default"/>
  </ListBox.GroupStyle>
</ListBox>
</Window.Resources>

数据变化时,排序、筛选、分组的结果并不会变化,需要手动调用CollectionViewRefresh方法:FindResource("cvsActors") as CollectionViewSource).View.Refresh();

可以使用LiveFilteringProperties等属性以获得实时变化

<CollectionViewSource x:Key="cvsActors" Source="{Binding ActorList}" IsLiveFilteringRequested="True">
            <CollectionViewSource.LiveFilteringProperties>
                <s:String>Name</s:String>
            </CollectionViewSource.LiveFilteringProperties>
        </CollectionViewSource>

当前项

由于 WPF 只通过使用视图(你指定的视图或集合的默认视图)绑定到集合,因此集合的所有绑定都有一个当前项指针。 绑定到视图时,Path 值中的斜杠(“/”)字符用于指定视图的当前项。 在下面的示例中,数据上下文是一个集合视图。 第一行绑定到集合。 第二行绑定到集合中的当前项。 第三行绑定到集合中当前项的 Description 属性。

<Button Content="{Binding }" />
<Button Content="{Binding Path=/}" />
<Button Content="{Binding Path=/Description}" />

只需将两个或更多控件绑定到同一视图即可实现主-从方案。

<ListBox Name="Master" Grid.Row="2" Grid.ColumnSpan="3" Margin="8" 
         ItemsSource="{Binding Source={StaticResource listingDataView}}" />
<ContentControl Name="Detail" Grid.Row="3" Grid.ColumnSpan="3"
                Content="{Binding Source={StaticResource listingDataView}}"
                ContentTemplate="{StaticResource detailsProductListingTemplate}" 
                Margin="9,0,0,0"/>

此绑定有效是因为将单一实例对象(在本例中为 ContentControl)绑定到集合视图时,它会自动绑定到该视图的 CurrentItem

    <DockPanel DataContext="{Binding Source={StaticResource MyList}}">
      <StackPanel>
        <Label>My Soccer Leagues</Label>
        <ListBox ItemsSource="{Binding}"
                 ItemTemplate="{StaticResource dataTemplate}"
                 IsSynchronizedWithCurrentItem="true"/>
      </StackPanel>

      <StackPanel>
        <Label Content="{Binding XPath=@name}"/>
        <ListBox Name="divisionsListBox"
                 ItemsSource="{Binding XPath=Division}"
                 ItemTemplate="{StaticResource dataTemplate}"
                 IsSynchronizedWithCurrentItem="true"/>
      </StackPanel>

      <StackPanel>
        <Label Content="{Binding XPath=@name}"/>
        <ListBox DataContext="{Binding ElementName=divisionsListBox,
                                       Path=SelectedItem}"
                 ItemsSource="{Binding XPath=Team}"
                 ItemTemplate="{StaticResource dataTemplate}"/>
      </StackPanel>
    </DockPanel>

在数据集合视图中导航

//OnButton is called whenever the Next or Previous buttons
//are clicked to change the currency
  private void OnButton(Object sender, RoutedEventArgs args)
  {
      Button b = sender as Button;

      switch (b.Name)
      {
          case "Previous":
              myCollectionView.MoveCurrentToPrevious();

              if (myCollectionView.IsCurrentBeforeFirst)
              {
                  myCollectionView.MoveCurrentToLast();
              }
              break;

          case "Next":
              myCollectionView.MoveCurrentToNext();
              if (myCollectionView.IsCurrentAfterLast)
              {
                  myCollectionView.MoveCurrentToFirst();
              }
              break;

          o = myCollectionView.CurrentItem as Order;
          // TODO: do something with the current Order o
      }
  }
原文地址:https://www.cnblogs.com/yetsen/p/13567780.html