C# 如何使WPF Listview与Photoshop图层工作相同

C# 如何使WPF Listview与Photoshop图层工作相同,c#,wpf,listview,header,C#,Wpf,Listview,Header,正如我们在Photoshop图层窗口(或其他图像编辑工具)中看到的 它有几个特点: 具有类似文件夹标题的组 (可折叠/可扩展) 未分组的项目(无标题) 通过拖动“手动”排序 对于No 1,我使用expander控件创建了groupped项。 () 在3号情况下,可使用此代码解决手动排序问题。 () 但我不知道如何将未分组的项目列在一起。 当然,未分组的项目可能没有标题 我正在使用ICollectionView和MVVM ICollectionView可以吗?ICollectionView不能。可

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

它有几个特点:

  • 具有类似文件夹标题的组 (可折叠/可扩展)
  • 未分组的项目(无标题)
  • 通过拖动“手动”排序
  • 对于No 1,我使用expander控件创建了groupped项。 ()

    在3号情况下,可使用此代码解决手动排序问题。 ()

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

    我正在使用ICollectionView和MVVM


    ICollectionView可以吗?

    ICollectionView
    不能。可以这里有一个例子

    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>
    
    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;
        }
      }
    }
    
    
    
    CS:

    <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>
    
    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;
        }
      }
    }
    
    使用系统;
    使用System.Collections.ObjectModel;
    使用系统组件模型;
    使用System.Windows;
    使用System.Windows.Controls;
    使用System.Windows.Data;
    命名空间WpfWindow
    {
    公共部分类Window1:Window
    {
    私有常量int NumberOfRecords=20;
    私有只读可观察收集列表;
    公共窗口1()
    {
    初始化组件();
    var国家=新[]{”、“美国”、“中国”、“印度”、“日本”、“乌克兰”};
    var countriescont=国家/地区。长度;
    _myList=新的ObservableCollection();
    var rnd=新随机数();
    for(int i=0;i
    但请记住,让项目组自动禁用虚拟化并影响性能。如果你需要的东西里面有成千上万的东西,你可能会写你自己的控制或寻找第三方


    干杯,安瓦卡。

    安瓦卡,谢谢你的帮助。我成功地用您的代码显示分组和取消分组的项目。但是,我的问题是,分组项目总是位于底部。在我看来,组本身并没有任何排序描述,以便在未分组的项之间定位。但是如何在列表视图中混合(排序)未分组和分组的项目呢?Youngjae,您可以使用两种排序描述,如下所述:than previous。我认为需要一个全新的方法。我将尝试使用naive stackpanel解决我的问题。