我有一个ListBox基于这样的属性进行分组的地方:
CollectionView view = (CollectionView)CollectionViewSource.GetDefaultView(listbox.ItemsSource);
PropertyGroupDescription groupDescription = new PropertyGroupDescription("CurrentDate");
view.GroupDescriptions.Add(groupDescription);
Run Code Online (Sandbox Code Playgroud)
分组后我想在组之间添加一个垂直分隔符,我写了一个这样的代码:
<ListBox.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Separator Style="{StaticResource {x:Static ToolBar.SeparatorStyleKey}}" />
<TextBlock Text="{Binding Path=Name}"
FontWeight="Bold"/>
</StackPanel>
</DataTemplate>
</GroupStyle.HeaderTemplate>
<GroupStyle.Panel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</GroupStyle.Panel>
</GroupStyle>
</ListBox.GroupStyle>
Run Code Online (Sandbox Code Playgroud)
但它看起来像这样:
虽然我想要一个分隔符完全下降,但当我试图增加分隔符的高度时,项目随之下降.
当你组一个项目ListBox使用CollectionView+ GroupStyle会发生什么是ListBox屏幕列表GroupItem控件,每个代表一组项目.A GroupItem基本上由一个ContentPresenter(用于呈现标题)和一个ItemsPresenter(用于呈现分组项目)放在一个StackPanel.
当您指定时GroupStyle.HeaderTemplate,它将用于ContentTemplate提到的ContentPresenter.因此,如果你增加它的高度,Separator它仍将被包含在ContentPresenter导致它垂直生长,并且物品仍将堆叠在它下面 - 因此你的结果.
为实现目标,您需要做的是重新模板化,GroupItem以便Separator在ContentPresenter和旁边显示ItemsPresenter,然后使用它进行连线GroupStyle.ContainerStyle.为方便起见,我们把它放在ListBox.Resources字典中:
<ListBox (...)>
<ListBox.Resources>
<ControlTemplate x:Key="GroupItemTemplate" TargetType="{x:Type GroupItem}">
<DockPanel>
<Separator DockPanel.Dock="Left"
Style="{StaticResource {x:Static ToolBar.SeparatorStyleKey}}" />
<StackPanel>
<ContentPresenter /><!-- This will be automatically wired -->
<ItemsPresenter Margin="5,0,0,0" /><!-- So will this -->
</StackPanel>
</DockPanel>
</ControlTemplate>
</ListBox.Resource>
<ListBox.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Name}" FontWeight="Bold" />
</DataTemplate>
</GroupStyle.HeaderTemplate>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Template"
Value="{StaticResource GroupItemTemplate}" />
</Style>
</GroupStyle.ContainerStyle>
(...)
</GroupStyle>
</ListBox.GroupStyle>
(...)
</ListBox>
Run Code Online (Sandbox Code Playgroud)
请注意,我从标题模板中删除了分隔符.
以下是您可能想要获得的结果(我在周围设置了蓝色边框ListBox以区分#3和#4):
默认情况下,我提供的代码摘录将为您提供#1(所有分隔符在整个范围内垂直拉伸ListBox).
要实现#2(分隔符仅向下拉伸到相应组的最后一项),您应该添加<Setter Property="VerticalAlignment" Value="Top" />到GroupStyle.ContainerStyle.或者,您可以将其放在模板DockPanel内部GroupItem.
要获得#3(分隔符伸展到最大组的高度),您应该添加VerticalAlignment="Top"到GroupStyle.Panel(VirtualizingStackPanel在您的情况下)内的面板.
最后#4(ListBox本身被限制为最大群体的大小)可以通过将被achievied VerticalAlignment="Top"的ListBox本身.
我无法想象一个开箱即用的解决方案,因为您正在尝试调整组。我做了一个例子,但它无法在不使用分隔符的情况下调整项目区域内的列宽度,但在标题处:
代码隐藏
public partial class Window1 {
public Window1() {
InitializeComponent();
this._items.Add(new Item { Name = "one", DateTime = DateTime.Today });
this._items.Add(new Item { Name = "two", DateTime = DateTime.Today.Subtract(new TimeSpan(1, 0, 0, 0)) });
this._items.Add(new Item { Name = "three", DateTime = DateTime.Today.Subtract(new TimeSpan(1, 0, 0, 0)) });
this._items.Add(new Item { Name = "four", DateTime = DateTime.Today.Add(new TimeSpan(1, 0, 0, 0)) });
this._items.Add(new Item { Name = "five", DateTime = DateTime.Today.Add(new TimeSpan(1, 0, 0, 0)) });
this.DataContext = this;
}
private ObservableCollection<Item> _items = new ObservableCollection<Item>();
public ObservableCollection<Item> Items => _items;
}
public abstract class ViewModelBase : INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) {
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public class Item : ViewModelBase {
private string _name;
private DateTime _dateTime;
public string Name {
get {
return this._name;
}
set {
if (value == this._name)
return;
this._name = value;
this.OnPropertyChanged();
}
}
public DateTime DateTime {
get {
return this._dateTime;
}
set {
if (value.Equals(this._dateTime))
return;
this._dateTime = value;
this.OnPropertyChanged();
}
}
}
Run Code Online (Sandbox Code Playgroud)
资源分组
<Window.Resources>
<CollectionViewSource x:Key="CollectionViewSource" Source="{Binding Items}">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="DateTime" />
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
</Window.Resources>
Run Code Online (Sandbox Code Playgroud)
列表框
<ListBox ItemsSource="{Binding Source={StaticResource CollectionViewSource}}" Width="400" Height="200">
<ListBox.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<GridViewColumnHeader Content="{Binding Name}"/>
</DataTemplate>
</GroupStyle.HeaderTemplate>
<GroupStyle.Panel >
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</GroupStyle.Panel>
</GroupStyle>
</ListBox.GroupStyle>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
<Setter Property="VerticalContentAlignment" Value="Stretch"></Setter>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderBrush="DarkGray" BorderThickness="0,0,1,0" Margin="-6,-2,-6,-2">
<StackPanel Margin="6,2,6,2">
<TextBlock Text="{Binding Name}"/>
</StackPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Run Code Online (Sandbox Code Playgroud)
此解决方法的关键是使用GridViewColumnHeaderGroupStyle 作为 HeaderTemplate。
可能更好的解决方案是将 ListBox 更改为 ListView 并将 ListView 的View-Property 设置为GridView。但这需要更改您的数据结构。
笔记
列表框的分组从来都不是为了执行您想要执行的任务。列表框和分组的默认方式是在列表框的内容区域中包含扩展器,如此处所述
| 归档时间: |
|
| 查看次数: |
566 次 |
| 最近记录: |