我有一个ListBox
我根据这样的属性进行分组:
CollectionView view = (CollectionView)CollectionViewSource.GetDefaultView(listbox.ItemsSource);
PropertyGroupDescription groupDescription = new PropertyGroupDescription("CurrentDate");
view.GroupDescriptions.Add(groupDescription);
分组后我想在组之间添加一个垂直分隔符,我写了一个这样的代码:
<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>
但它看起来像这样:
虽然我希望分隔符完全消失但是当我试图增加分隔符的高度时,项目会随之下降。
答案 0 :(得分:6)
当您使用ListBox
+ CollectionView
对GroupStyle
中的项目进行分组时,ListBox
会显示GroupItem
个控件列表,每个控件代表一个组的项目。 GroupItem
基本上由ContentPresenter
(用于显示标题)和ItemsPresenter
(用于展示分组的项目)组成StackPanel
。
当您指定GroupStyle.HeaderTemplate
时,它将用作上述ContentTemplate
的{{1}}。因此,如果你增加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>
周围加上蓝色边框以区分#3和#4):
我提供的代码摘录默认情况下会给你#1(所有分隔符在整个ListBox
中垂直拉伸)。
要实现#2(分隔符仅向下延伸到相应组的最后一项),您应该将ListBox
添加到<Setter Property="VerticalAlignment" Value="Top" />
。或者,您可以将其放在GroupStyle.ContainerStyle
模板内的DockPanel
上。
要获得#3(分隔符伸展到最大组的高度),您应该将GroupItem
添加到VerticalAlignment="Top"
(您的情况下为GroupStyle.Panel
)内的面板中。
最后,通过将VirtualizingStackPanel
放在ListBox
上,可以实现#4(VerticalAlignment="Top"
本身限制为最大组的大小)。
答案 1 :(得分:2)
我无法想象这是一个开箱即用的解决方案,因为你正试图转移群组。我已经做了一个例子,但它无法调整列的大小。 itemsarea中的宽度但不使用Seperators的标题:
<强>代码隐藏强>
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();
}
}
}
使用资源分组
<Window.Resources>
<CollectionViewSource x:Key="CollectionViewSource" Source="{Binding Items}">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="DateTime" />
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
</Window.Resources>
<强>列表框强>
<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>
此解决方法的基础是使用GridViewColumnHeader
作为GroupStyle的HeaderTemplate。
可能更好的解决方案可能是将ListBox更改为ListView并将ListView的View
- 属性设置为GridView
。这需要改变您的数据结构。
注意强>
ListBox的分组从未打算执行您尝试执行的任务。列表框和分组的默认方式是在ListBox的内容区域中使用扩展器,如here所述