Wpf .NET 6 中的 ObservableGroupedCollection
这个问题基于:
- 使用 .NET 6 的 Wpf 项目
ObservableGroupedCollection<TKey, TElement>
来自 Microsoft 的 NuGet 包“CommunityToolkit.Mvvm”- 严格遵守MVVM模式
同时修补相对较新的 CommunityToolkit.Mvvm我遇到了ObservableGroupedCollection<TKey, TElement>
在 Wpf 中,该类是相当未记录的。我的 Wpf 知识充其量只是很差 - 我打算将其用作学习项目 - 并且我无法将现有的 UWP xaml 代码转移到工作的 Wpf 示例应用程序中。
上面的博客文章中引用的示例应用程序使用 CollectionViewSource
绑定(bind)到ObservableGroupedCollection<TKey, TElement>
在可滚动控件中显示分组的联系人列表。我尝试在 Wpf .NET 6 应用程序中复制此行为,结果仅显示每个集合的第一个值,而不是整个范围。
在遵守 MVVM 模式的同时以分组方式显示所有条目的正确方法是什么?!
下图左侧显示了 Microsoft Store 示例应用程序的摘录,右侧显示了所需的结果。
下面示例代码的结果
手动迭代组及其集合时的结果:
实际ListView中显示的值:
让我困惑的是 SemanticZoom
原文中使用Sample App (.xaml - UWP)以及相应的ViewModel.cs以某种方式能够显示所有条目,而不是刮掉集合的第一个元素。同时仍然使用基于模型的DataTemplate
.
示例代码
以下代码是一个快速但肮脏的示例应用程序,用于说明我的问题并为可能的参与者提供基础。
要求:
- Wpf 项目 -> .NET 6
- NuGet 软件包:Microsoft 的 CommunityToolkit.Mvvm
- 2 个新文件夹:Models 和 ViewModels
- 将“yourRootNamespace”的所有实例替换为您的实际根命名空间
SomeModel.cs
namespace "yourRootNamespace".Models;
public class SomeModel
{
public string SomeString { get; set; }
public SomeModel(string _s)
{
SomeString = _s;
}
}
MainWindowViewModel.cs
using CommunityToolkit.Mvvm.Collections;
using CommunityToolkit.Mvvm.ComponentModel;
using "yourRootNamespace".Models;
using System.Collections.Generic;
using System.Linq;
namespace "yourRootNamespace".ViewModels;
public partial class MainWindowViewModel : ObservableObject
{
[ObservableProperty]
private ObservableGroupedCollection<string, SomeModel>? m_someObservableGroupedCollection;
public MainWindowViewModel()
{
List<SomeModel> tempList = new List<SomeModel>()
{
new SomeModel("w_1"),
new SomeModel("b_0"),
new SomeModel("a_2"),
new SomeModel("e_0"),
new SomeModel("f_0"),
new SomeModel("f_1"),
new SomeModel("a_1"),
new SomeModel("a_0"),
new SomeModel("w_0"),
new SomeModel("f_2")
};
m_someObservableGroupedCollection = new ObservableGroupedCollection<string, SomeModel>(tempList
.GroupBy(c => char.ToUpperInvariant(c.SomeString[0]).ToString())
.OrderBy(g => g.Key));
}
}
MainWindow.xaml.cs
using "yourRootNamespace".ViewModels;
using System.Windows;
namespace "yourRootNamespace";
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new MainWindowViewModel();
}
}
MainWindow.xaml
<Window x:Class=""yourRootNamespace".MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:"yourRootNamespace""
xmlns:collections="clr-namespace:CommunityToolkit.Mvvm.Collections;assembly=CommunityToolkit.Mvvm"
xmlns:viewmodels="clr-namespace:"yourRootNamespace".ViewModels"
xmlns:models="clr-namespace:"yourRootNamespace".Models"
d:DataContext="{d:DesignInstance Type=viewmodels:MainWindowViewModel}"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<CollectionViewSource
x:Key="SomeListViewSource"
Source="{Binding SomeObservableGroupedCollection}"
IsLiveGroupingRequested="True"/>
<DataTemplate
x:Key="SomeTemplate"
DataType="{x:Type models:SomeModel}">
<TextBlock Text="{Binding SomeString}"/>
</DataTemplate>
</Window.Resources>
<Grid>
<ListView
ItemTemplate="{StaticResource SomeTemplate}"
ItemsSource="{Binding Source={StaticResource SomeListViewSource}, Mode=OneWay}"
SelectionMode="Single">
<ListView.GroupStyle>
<GroupStyle
HidesIfEmpty="True">
<GroupStyle.HeaderTemplate>
<DataTemplate
DataType="{x:Type collections:IReadOnlyObservableGroup}">
<TextBlock Text="{Binding Key}"/>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListView.GroupStyle>
</ListView>
</Grid>
</Window>
最佳答案
我不确定 CommunityToolkit 开发人员的意图,它通过将 CollectionViewSource.GroupDescriptions
指定为 CollectionViewSource
来工作。
<Window.Resources>
<CollectionViewSource x:Key="SomeListViewSource"
Source="{Binding SomeObservableGroupedCollection}"
IsLiveGroupingRequested="True">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="Key"/>
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
<DataTemplate x:Key="SomeTemplate">
<TextBlock Text="{Binding SomeString}"/>
</DataTemplate>
</Window.Resources>
<Grid>
<ListView ItemTemplate="{StaticResource SomeTemplate}"
ItemsSource="{Binding Source={StaticResource SomeListViewSource}, Mode=OneWay}"
SelectionMode="Single">
<ListView.GroupStyle>
<GroupStyle HidesIfEmpty="True">
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock Foreground="Red"
Text="{Binding Name}"/>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListView.GroupStyle>
</ListView>
</Grid>
关于c# - 使用 Wpf .NET 6 和 CommunityToolkit.Mvvm 包显示 ObservableGroupedCollection<string, TElement> 的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74425290/