在WPF中使用分组绑定列表框

3
我有一组ViewModel,并想将ListBox绑定到它们。经过一些调查,我发现了this
因此,我的ViewModel看起来像这样(伪代码):
interface IItemViewModel 
{
 string DisplayName { get; }
}

class AViewModel : IItemViewModel 
{
 string DisplayName { return "foo"; }
}

class BViewModel : IItemViewModel 
{
 string DisplayName { return "foo"; } 
}

class ParentViewModel 
{
 IEnumerable<IItemViewModel> Items 
 {
  get
  {
   return new IItemViewModel[] {
    new AItemViewModel(),
    new BItemViewModel()
   }
  }
 }
}

class GroupViewModel 
{
 static readonly GroupViewModel GroupA = new GroupViewModel(0);
 static readonly GroupViewModel GroupB = new GroupViewModel(1);

 int GroupIndex;
 GroupViewModel(int groupIndex) 
 {
  this.GroupIndex = groupIndex;
 }

 string DisplayName
 {
  get { return "This is group " + GroupIndex.ToString(); }
 }
}

class ItemGroupTypeConverter : IValueConverter
{
 object Convert(object value, Type targetType, object parameter, CultureInfo culture)
 {
  if (value is AItemViewModel)
   return GroupViewModel.GroupA;
  else 
   return GroupViewModel.GroupB;
 }
}

而这个XAML

<UserControl.Resources>
 <vm:ItemsGroupTypeConverter x:Key="ItemsGroupTypeConverter "/>
 <CollectionViewSource x:Key="GroupedItems" Source="{Binding Items}">
  <CollectionViewSource.GroupDescriptions>
   <PropertyGroupDescription Converter="{StaticResource ItemsGroupTypeConverter }"/>
  </CollectionViewSource.GroupDescriptions>
 </CollectionViewSource>
</UserControl.Resources>
<ListBox ItemsSource="{Binding Source={StaticResource GroupedItems}}">
 <ListBox.GroupStyle>
  <GroupStyle>
   <GroupStyle.HeaderTemplate>
    <DataTemplate>
     <TextBlock Text="{Binding DisplayName}" FontWeight="bold" />
    </DataTemplate>
   </GroupStyle.HeaderTemplate>
  </GroupStyle>              
 </ListBox.GroupStyle>
 <ListBox.ItemTemplate>
  <DataTemplate>
   <TextBlock Text="{Binding DisplayName}" />
  </DataTemplate>
 </ListBox.ItemTemplate>
</ListBox>

这个代码在某种程度上可用,但是HeaderTemplate的绑定却无法工作。不过我更愿意避免使用TypeConverter和CollectionViewSource。有没有办法可以使用ViewModel的属性进行分组呢?
我知道在这个示例场景中,很容易用字符串替换GroupViewModel并使其工作,但这并不是一个选项。那么该如何将HeaderTemplate绑定到GroupViewModel呢?
1个回答

11

好的,我终于自己解决了。

首先,TypeConverter是不必要的,因为PropertyGroupDescription可以绑定在PropertyName上。所以,我在IItemViewModel中添加了一个属性“Group”,并修改了XAML如下:

<UserControl.Resources>
 <CollectionViewSource x:Key="GroupedItems" Source="{Binding Items}">
  <CollectionViewSource.GroupDescriptions>
   <PropertyGroupDescription PropertyName="Group"/>
  </CollectionViewSource.GroupDescriptions>
 </CollectionViewSource>
</UserControl.Resources>

此外,HeaderTemplate的DataContext是一个CollectionViewGroupInternal,绑定应该像这样:

<DataTemplate>
 <TextBlock Text="{Binding Name.DisplayName}" FontWeight="bold" />
</DataTemplate>

这里的CollectionViewGroupInternal.Name解析了实际的GroupViewModel。


1
你为什么在TextBlock的Text绑定部分使用了Name.DisplayName?你从哪里获取到“Name”对象的? - Miles
1
Name是CollectionViewGroupInternal的一个参数。 - Michael Stoll

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接