在 WPF 中通过分组绑定列表框

发布于 2024-08-27 16:22:02 字数 2432 浏览 4 评论 0原文

我有一个 ViewModel 集合,想要将 ListBox 绑定到它们。经过一些调查,我发现了这个

所以我的 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 呢?

I've got a collection of ViewModels and want to bind a ListBox to them. Doing some investigation I found this.

So my ViewModel look like this (Pseudo Code)

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;
 }
}

And this 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>

This works somehow, exept of the fact that the binding of the HeaderTemplate does not work. Anyhow I'd prefer omitting the TypeConverter and the CollectionViewSource. Isn't there a way to use a property of the ViewModel for Grouping?

I know that in this sample scenario it would be easy to replace the GroupViewModel with a string an have it working, but that's not an option. So how can I bind the HeaderTemplate to the GroupViewModel?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

南…巷孤猫 2024-09-03 16:22:02

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

首先,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。

Ok, I finally solved it myself.

First of all the TypeConverter is unnecessary, because the PropertyGroupDescription can be bound on a PropertyName. So I added a Property 'Group' to IItemViewModel and modified XAML as follows:

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

Furthermore the HeaderTemplate's DataContext is a CollectionViewGroupInternal and the binding has to look like this:

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

Here CollectionViewGroupInternal.Name resolves the actual GroupViewModel.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文