ListBox Grouping的研究(二):ContainerStyle 与 GroupItem的绑定对象

延续上文,我对代码略作了改动:

(1)增加了一个ControlStyleSelector,用来调试GroupItem真正的绑定对象。
(2)实现了GroupStyle.ContainerStyle。为了调试,我先实现了一个Auto-Apply的Style,在文章最后给出了真正的实现。


数据结构:

    class Data
    {
        public string Value { get; set; }
        public string Type { get; set; }
    }

XAML:

<Window x:Class="WpfApplication2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication2"    
        Title="MainWindow" SizeToContent="WidthAndHeight">

  <Window.Resources>

    <local:ControlStyleSelector x:Key="selector" />

    <Style TargetType="GroupItem">
      <Setter Property="Template">
        <Setter.Value>
          <ControlTemplate>
            <StackPanel>
              <Expander Header="{Binding Name}">
                <ItemsPresenter />
              </Expander>
            </StackPanel>
          </ControlTemplate>
        </Setter.Value>
      </Setter>
    </Style>

    <DataTemplate DataType="{x:Type local:Data}">
        <TextBlock Text="{Binding Value}"/>
    </DataTemplate>

  </Window.Resources>

  <StackPanel Margin="5">
    <ListBox ItemsSource="{StaticResource data}">
      <ListBox.GroupStyle>
        <GroupStyle ContainerStyleSelector="{StaticResource selector}">
        </GroupStyle>
      </ListBox.GroupStyle>
    </ListBox>
  </StackPanel>
</Window>

代码:

    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            ObservableCollection<Data> data = new ObservableCollection<Data>();
            for (int i = 1; i <= 9; i += 2)
                data.Add(new Data() { Value = i.ToString(), Type = "Odd" });

            for (int i = 0; i < 10; i += 2)
                data.Add(new Data() { Value = i.ToString(), Type = "Even" });

            this.Resources.Add("data", data);
            InitializeComponent();
            ICollectionView vw = CollectionViewSource.GetDefaultView(data);
            vw.GroupDescriptions.Add(new PropertyGroupDescription("Type"));
        }
    }

    class ControlStyleSelector : StyleSelector
    {
        public override Style SelectStyle(object item, DependencyObject container)
        {
            return base.SelectStyle(item, container);
        }
    }

运行截图:

        

可以看到分组展开与收缩的功能已经实现,原先GroupItem下的Visual Tree中的StackPanel也已经被替换成了Expander了。在Expander内,我直接把ItensPresenter放到里面,他自动显示出了分组的内容。根据调试,其实GroupItem绑定到的是一个MS内部结构:


MS.Internal.Data.CollectionViewGroupInternal,派生自CollectionViewGroup类型,父类提供了Name和Items属性,所以我可以用来做绑定!上面的XAML是调试性质,真真的写法应该把Style放在ListBox的GroupStyle内部,或者变成一个Resource,代码如下:

<Window x:Class="WpfApplication2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication2"    
        Title="MainWindow" SizeToContent="WidthAndHeight">

  <Window.Resources>


    <DataTemplate DataType="{x:Type local:Data}">
      <TextBlock Text="{Binding Value}"/>
    </DataTemplate>
  </Window.Resources>

  <StackPanel Margin="5">
    <ListBox ItemsSource="{StaticResource data}">
      <ListBox.GroupStyle>
        <GroupStyle>
          <GroupStyle.ContainerStyle>
            <Style TargetType="GroupItem">
              <Setter Property="Template">
                <Setter.Value>
                  <ControlTemplate>
                    <Expander Header="{Binding Name}">
                      <ItemsPresenter />
                    </Expander>
                  </ControlTemplate>
                </Setter.Value>
              </Setter>
            </Style>
          </GroupStyle.ContainerStyle>
        </GroupStyle>
      </ListBox.GroupStyle>
    </ListBox>
  </StackPanel>
</Window>



原文地址:https://www.cnblogs.com/puncha/p/3876995.html