ItemsControl (WrapPanel) 分组应该拆分 GroupItems
ItemsControl (WrapPanel) Grouping should split GroupItems
我有一个带有 WrapPanel 作为 ItemsHost 和多个分组的 ItemsControl。
使用以下模板到目前为止:
<GroupStyle.ContainerStyle>
<Style TargetType="GroupItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="GroupItem">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ContentPresenter Grid.Row="0" x:Name="PART_Header" Content="{TemplateBinding Content}" />
<ItemsPresenter Grid.Row="1" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
<GroupStyle.Panel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True" Orientation="Vertical" />
</ItemsPanelTemplate>
</GroupStyle.Panel>
现在我遇到了一个问题,即每个组都会开始一个新的列,为什么我希望它在最后一个 GroupItem 的下方继续并在 GroupItem 的中间而不是在开头换行。
它应该类似于 Windows 8 Apps 概览(如果您转到概览,则不是起始页)
这可能吗?
我在 ViewModel 中解决了这个问题。我将 GroupItem 添加到 ObservableCollection 中,其样式类似于(可扩展的)GroupHeader。
比我为 GroupHeader 添加了一个单独的 DataTemplate,它在组上设置了一个 IsCollapsed 属性。所有项目现在都有对父组的引用,并将可见性绑定到父组的 IsCollapsed 属性。
遗憾的是我无法使用 CollectionViewSource 实现此目的。
这是XAML:
<ItemsControl ItemsSource="{Binding Items}">
<ItemsControl.DataContext>
<local:ViewModel/>
</ItemsControl.DataContext>
<ItemsControl.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
<DataTemplate DataType="{x:Type local:GroupViewModel}">
<StackPanel>
<CheckBox IsChecked="{Binding IsExtended}" />
<!--Restyle to look like a extender-->
</StackPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type local:ItemViewModel}">
<TextBlock Text="{Binding Name}"
Visibility="{Binding Group.IsExtended, Converter={StaticResource BooleanToVisibilityConverter}}"/>
</DataTemplate>
</ItemsControl.Resources>
</ItemsControl>
这是视图模型:
public class ViewModel
{
public ViewModel()
{
//Some Test data
GroupViewModel group1 = new GroupViewModel("Group1");
GroupViewModel group2 = new GroupViewModel("Group2");
this.Items = new ObservableCollection<object>(new[]
{
new ItemViewModel("Item1", group1),
new ItemViewModel("Item2", group1),
new ItemViewModel("Item3", group2),
new ItemViewModel("Item4", group2)
});
string groupName = string.Empty;
foreach (ItemViewModel item in this.Items.ToArray())
{
//Insert Group headers
if (item.Group.Name != groupName)
{
groupName = item.Group.Name;
this.Items.Insert(this.Items.IndexOf(item), item.Group);
}
}
}
public ObservableCollection<object> Items { get; }
}
public class GroupViewModel : ViewModelBase
{
private bool isExtended = true;
public GroupViewModel(string name)
{
this.Name = name;
}
public string Name { get; }
public bool IsExtended
{
get { return this.isExtended; }
set { this.SetProperty(ref this.isExtended, value); }
}
}
public class ItemViewModel
{
public ItemViewModel(string name, GroupViewModel group)
{
this.Name = name;
this.Group = group;
}
public string Name { get; }
public GroupViewModel Group { get; }
}
您不能直接进行这种包装,因为组在一个面板中,而每个组中的项目在各自的面板中。
您有两个选择:
使用视图模型和数据模板的组合来模拟分组。 ItemsSource 不会分组 CollectionView,只是简单的 collection,但项目将包含组名称。在 DataTemplate 中,您将为每个组中的第一个项目显示组 Header。
创建您自己的控件,它会立即将 children 排列成组。相当多的工作,但更好的可重用性。我相信这就是 WinRT GridView 和 ListView 分组的工作方式。也许你可以在 WPF
中找到类似的第 3 方控件
我有一个带有 WrapPanel 作为 ItemsHost 和多个分组的 ItemsControl。 使用以下模板到目前为止:
<GroupStyle.ContainerStyle>
<Style TargetType="GroupItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="GroupItem">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ContentPresenter Grid.Row="0" x:Name="PART_Header" Content="{TemplateBinding Content}" />
<ItemsPresenter Grid.Row="1" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
<GroupStyle.Panel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True" Orientation="Vertical" />
</ItemsPanelTemplate>
</GroupStyle.Panel>
现在我遇到了一个问题,即每个组都会开始一个新的列,为什么我希望它在最后一个 GroupItem 的下方继续并在 GroupItem 的中间而不是在开头换行。
它应该类似于 Windows 8 Apps 概览(如果您转到概览,则不是起始页)
这可能吗?
我在 ViewModel 中解决了这个问题。我将 GroupItem 添加到 ObservableCollection 中,其样式类似于(可扩展的)GroupHeader。 比我为 GroupHeader 添加了一个单独的 DataTemplate,它在组上设置了一个 IsCollapsed 属性。所有项目现在都有对父组的引用,并将可见性绑定到父组的 IsCollapsed 属性。
遗憾的是我无法使用 CollectionViewSource 实现此目的。
这是XAML:
<ItemsControl ItemsSource="{Binding Items}">
<ItemsControl.DataContext>
<local:ViewModel/>
</ItemsControl.DataContext>
<ItemsControl.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
<DataTemplate DataType="{x:Type local:GroupViewModel}">
<StackPanel>
<CheckBox IsChecked="{Binding IsExtended}" />
<!--Restyle to look like a extender-->
</StackPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type local:ItemViewModel}">
<TextBlock Text="{Binding Name}"
Visibility="{Binding Group.IsExtended, Converter={StaticResource BooleanToVisibilityConverter}}"/>
</DataTemplate>
</ItemsControl.Resources>
</ItemsControl>
这是视图模型:
public class ViewModel
{
public ViewModel()
{
//Some Test data
GroupViewModel group1 = new GroupViewModel("Group1");
GroupViewModel group2 = new GroupViewModel("Group2");
this.Items = new ObservableCollection<object>(new[]
{
new ItemViewModel("Item1", group1),
new ItemViewModel("Item2", group1),
new ItemViewModel("Item3", group2),
new ItemViewModel("Item4", group2)
});
string groupName = string.Empty;
foreach (ItemViewModel item in this.Items.ToArray())
{
//Insert Group headers
if (item.Group.Name != groupName)
{
groupName = item.Group.Name;
this.Items.Insert(this.Items.IndexOf(item), item.Group);
}
}
}
public ObservableCollection<object> Items { get; }
}
public class GroupViewModel : ViewModelBase
{
private bool isExtended = true;
public GroupViewModel(string name)
{
this.Name = name;
}
public string Name { get; }
public bool IsExtended
{
get { return this.isExtended; }
set { this.SetProperty(ref this.isExtended, value); }
}
}
public class ItemViewModel
{
public ItemViewModel(string name, GroupViewModel group)
{
this.Name = name;
this.Group = group;
}
public string Name { get; }
public GroupViewModel Group { get; }
}
您不能直接进行这种包装,因为组在一个面板中,而每个组中的项目在各自的面板中。
您有两个选择:
使用视图模型和数据模板的组合来模拟分组。 ItemsSource 不会分组 CollectionView,只是简单的 collection,但项目将包含组名称。在 DataTemplate 中,您将为每个组中的第一个项目显示组 Header。
创建您自己的控件,它会立即将 children 排列成组。相当多的工作,但更好的可重用性。我相信这就是 WinRT GridView 和 ListView 分组的工作方式。也许你可以在 WPF
中找到类似的第 3 方控件