我有一个ItemsControl,其中WrapPanel为ItemsHost和多个分组。 到目前为止,使用以下模板:
<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>
现在我遇到的问题是,每个Group都会启动一个新列,为什么我希望它在GroupItem的最后一个GroupItem和Wrap中继续,而不是在开头。
它应该看起来像Windows 8应用程序概述(如果您转到概述,则不是起始页面)
这可能吗?
答案 0 :(得分:2)
我在ViewModel中解决了这个问题。我将一个GroupItem添加到ObservableCollection中,其样式类似于(可扩展的)GroupHeader。 我为GroupHeader添加了一个单独的DataTemplate,用于在Group上设置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>
这是ViewModel:
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; }
}
答案 1 :(得分:1)
你不能直接进行那种包装,因为群组在一个面板中,而每个群组中的项目都在他们自己的面板中。
您有两种选择:
使用viewmodel和Datatemplates的组合来模拟分组。 ItemsSource不会被分组CollectionView,只是普通集合,但项目将包含组名。在DataTemplate中,您将显示每个组中第一个项目的Group Header。
创建您自己的控件,可以将子项安排到开箱即用的组中。相当一部分工作,但更好的可重用性。我相信这就是WinRT GridView和ListView分组的工作原理。也许你可以在WPF中找到simmilar第三方控件