如何使WPF Listview与Photoshop图层一样工作

时间:2010-06-08 07:23:34

标签: c# wpf listview header

正如我们在Photoshop图层窗口(或其他图像编辑工具)中看到的那样,

它有几个功能:

  1. 具有类似文件夹标题的组 (折叠/可膨胀的)
  2. 未分组的项目(无标题)
  3. 通过拖动“手动”排序。
  4. 如果是1号,我用扩展器控件制作了分组项目。 (ref

    如果是No 3,可以使用此代码解决手动排序。 (ref

    但我不知道如何将未组合的项目列在一起。 当然,未分组的项目可能没有标题。

    我正在使用ICollectionView和MVVM。

    ICollectionView能做到吗?

1 个答案:

答案 0 :(得分:2)

ICollectionView不能。 GroupStyle.ContainerStyleSelector可以。这是一个例子。

<强> XAML:

<Window x:Class="WpfWindowDrag.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:WpfWindowDrag="clr-namespace:WpfWindowDrag"
        Title="Window1" Height="300" Width="300">
  <Window.Resources>
    <!--Container style for a groupped item-->
    <Style x:Key="RegularContainerStyle" TargetType="{x:Type GroupItem}">
      <Setter Property="Template">
        <Setter.Value>
          <ControlTemplate>
            <Expander Header="{Binding Name}" IsExpanded="True">
              <ItemsPresenter />
            </Expander>
          </ControlTemplate>
        </Setter.Value>
      </Setter>
    </Style>

    <!--Container style for root objects (i.e. non grouped)-->
    <Style x:Key="RootContainerStyle" TargetType="{x:Type GroupItem}">
      <Setter Property="Template">
        <Setter.Value>
          <ControlTemplate>
            <ItemsPresenter />
          </ControlTemplate>
        </Setter.Value>
      </Setter>
    </Style>

    <!--This guy lets us select choose proper group for an item.-->
    <WpfWindowDrag:CountryStyleSelector x:Key="ContainerStyleSelector"
                                        RegularGroupStyle="{StaticResource RegularContainerStyle}"
                                        RootGroup="{StaticResource RootContainerStyle}" />
  </Window.Resources>
  <Grid>
    <ListView x:Name="lv">
      <ListView.GroupStyle>
        <GroupStyle ContainerStyleSelector="{StaticResource ContainerStyleSelector}" />
      </ListView.GroupStyle>
      <ListView.View>
        <GridView>
          <GridViewColumn DisplayMemberBinding="{Binding Path=Name}" Header="Name" />
        </GridView>
      </ListView.View>
    </ListView>
  </Grid>
</Window>

<强> CS:

using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;

namespace WpfWindow
{
  public partial class Window1 : Window
  {
    private const int NumberOfRecords = 20;
    private readonly ObservableCollection<Person> _myList;

    public Window1()
    {
      InitializeComponent();

      var countries = new[] { "", "US", "China", "India", "Japan", "Ukraine" };

      var countriesCount = countries.Length;
      _myList = new ObservableCollection<Person>();
      var rnd = new Random();

      for (int i = 0; i < NumberOfRecords; i++)
      {
        int countryIndex = rnd.Next(countriesCount);
        _myList.Add(new Person() { Name = string.Format("Name {0}", i), Country = countries[countryIndex] });
      }

      ICollectionView view = CollectionViewSource.GetDefaultView(_myList);
      view.GroupDescriptions.Add(new PropertyGroupDescription("Country"));
      view.SortDescriptions.Add(new SortDescription("Country", ListSortDirection.Ascending));
      view.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Ascending));

      lv.ItemsSource = view;
    }
  }

  public class Person
  {
    public string Name { get; set; }
    public string Country { get; set; }
  }

  public class CountryStyleSelector : StyleSelector
  {
    public Style RegularGroupStyle { get; set; }

    public Style RootGroup { get; set; }

    public override Style SelectStyle(object item, DependencyObject container)
    {
      var cvg = item as CollectionViewGroup;
      if (cvg == null)
      {
        return base.SelectStyle(item, container);
      }
      return string.IsNullOrEmpty(cvg.Name as string) ? RootGroup : RegularGroupStyle;
    }
  }
}

请注意,让项目组自动禁用虚拟化并影响性能。如果你需要一些非常快速的内容,你可能会编写自己的控件或寻找第三方。

干杯,安瓦卡。