Как сделать так, чтобы WPF Listview работал так же, как слой Photoshop - PullRequest
0 голосов
/ 08 июня 2010

Как мы видим в окне слоя Photoshop (или в другом инструменте редактирования изображений),

имеет несколько функций:

  1. групп с папкообразным заголовком (Коллапс / расширяемый)
  2. элемент без группировки (без заголовка)
  3. сортировка "вручную" путем перетаскивания.

В случае № 1 я сделал сгруппированный предмет с контролем экспандера. ( исх )

В случае № 3 сортировка вручную может быть решена с помощью этого кода. ( ссылка )

но я не знаю, как перечислить неразобранные элементы вместе. Конечно, не сгруппированные элементы могут не иметь заголовка.

Я использую ICollectionView и MVVM.

Может ли ICollectionView сделать это?

1 Ответ

2 голосов
/ 08 июня 2010

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

Имейте в виду, что наличие группы элементов автоматически отключает виртуализацию и влияет на производительность. Если вам нужно что-то действительно быстрое с тысячами предметов внутри, вы, вероятно, напишите свой собственный элемент управления или поищете сторонние организации.

Приветствия, Анвака.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...