You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CommunityToolkit.WinUI DataGrid绑定ObservableCollection后不更新问题

问题

我有一个包含“全部”“活跃”“非活跃”三个筛选选项的下拉框,切换选中值时会触发事件,调整ViewModel中绑定到用户展示DataGrid的ObservableCollection类型属性ProjectDbUsers。调试时发现ProjectDbUsers属性已成功变更,但DataGrid并未刷新以匹配修改后的集合。

环境说明:

  • 主UI项目使用CommunityToolkit.WinUI.Controls.DataGrid包
  • 包含ViewModel的业务层项目使用CommunityToolkit.Mvvm包

相关代码:

管理用户页面XAML中的ComboBox与DataGrid

<ComboBox x:Name="BasicUserFilter"  Grid.Row="0" Grid.Column="1"
           Height="30" Width="Auto" Margin="20,10,10,10"
          ItemsSource="{x:Bind ViewModel.Filters, Mode=OneWay}" 
          SelectedItem="{x:Bind ViewModel.SelectedFilter, Mode=TwoWay}"                      
          SelectionChanged="BasicUserFilter_SelectionChanged"/>

<controls:DataGrid x:Name="dataGrid1" Grid.Row="2"
Height="600" Margin="12"
AutoGenerateColumns="False"
ItemsSource="{x:Bind ViewModel.ProjectDbUsers, Mode=OneWay}">
    <controls:DataGrid.Columns>
        <controls:DataGridTextColumn 
            Header="Name" 
            Width="250"
            Binding="{Binding UserAddisplayName}" 
            FontSize="14" />
            ...
    </controls:DataGrid.Columns>
</controls:DataGrid> 

下拉框选择变更事件后台代码

private void BasicUserFilter_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    ViewModel.UpdateGridBasedOnFilter();
}

ViewModel类中的属性定义与筛选方法

[ObservableProperty]
private string _selectedFilter;   

public ObservableCollection<string> Filters { get; } = new ObservableCollection<string>(new List<string>() { "All", "Active", "Inactive" });

public ObservableCollection<UserAd> ProjectDbUsers { get; private set; }

public void UpdateGridBasedOnFilter()
{
    using (UnitOfWorkDbGlobal unitOfWorkDbGlobal = new(new MyDBContext()))
    {
        List<UserAd> users = new();
        switch (SelectedFilter)
        {
            case "All":
                users = unitOfWorkDbGlobal.UserAds.GetAllUsers().ToList();
                break;
            case "Active":
                users = unitOfWorkDbGlobal.UserAds.GetAllActiveUsers().ToList();
                break;
            case "Inactive":
                users = unitOfWorkDbGlobal.UserAds.GetAllInactiveUsers().ToList();
                break;
        }

        ProjectDbUsers = new ObservableCollection<UserAd>(users);
    }
}

请问需要补充什么配置或代码,才能让DataGrid在ProjectDbUsers变更时同步更新?


解决方案

问题核心是ProjectDbUsers属性重新赋值时未触发属性变更通知,DataGrid无法感知到属性已替换为新的ObservableCollection实例。结合你使用的CommunityToolkit.Mvvm包,提供以下几种解决方式:

方式一:使用[ObservableProperty]特性(推荐)

将ProjectDbUsers的手动定义改为MVVM Toolkit的自动实现,它会自动生成属性变更通知逻辑:

// 替换原来的手动属性定义
[ObservableProperty]
private ObservableCollection<UserAd> _projectDbUsers = new(); // 初始化空集合

在UpdateGridBasedOnFilter方法中直接给生成的属性赋值(Toolkit会自动生成首字母大写的ProjectDbUsers属性):

public void UpdateGridBasedOnFilter()
{
    using (UnitOfWorkDbGlobal unitOfWorkDbGlobal = new(new MyDBContext()))
    {
        List<UserAd> users = new();
        switch (SelectedFilter)
        {
            case "All":
                users = unitOfWorkDbGlobal.UserAds.GetAllUsers().ToList();
                break;
            case "Active":
                users = unitOfWorkDbGlobal.UserAds.GetAllActiveUsers().ToList();
                break;
            case "Inactive":
                users = unitOfWorkDbGlobal.UserAds.GetAllInactiveUsers().ToList();
                break;
        }

        ProjectDbUsers = new ObservableCollection<UserAd>(users);
    }
}

方式二:手动触发属性变更通知

如果不想使用[ObservableProperty],确保ViewModel继承ObservableObject(来自CommunityToolkit.Mvvm),并在ProjectDbUsers的setter中调用SetProperty触发通知:

public class YourViewModel : ObservableObject
{
    private ObservableCollection<UserAd> _projectDbUsers;
    public ObservableCollection<UserAd> ProjectDbUsers 
    { 
        get => _projectDbUsers; 
        private set => SetProperty(ref _projectDbUsers, value);
    }

    // 其余代码保持不变
}

额外优化:复用现有集合(可选)

如果不想每次筛选都创建新的ObservableCollection,可以清空现有集合再添加新数据,利用ObservableCollection自身的集合变更通知:

public void UpdateGridBasedOnFilter()
{
    using (UnitOfWorkDbGlobal unitOfWorkDbGlobal = new(new MyDBContext()))
    {
        List<UserAd> users = new();
        switch (SelectedFilter)
        {
            case "All":
                users = unitOfWorkDbGlobal.UserAds.GetAllUsers().ToList();
                break;
            case "Active":
                users = unitOfWorkDbGlobal.UserAds.GetAllActiveUsers().ToList();
                break;
            case "Inactive":
                users = unitOfWorkDbGlobal.UserAds.GetAllInactiveUsers().ToList();
                break;
        }

        ProjectDbUsers.Clear();
        foreach (var user in users)
        {
            ProjectDbUsers.Add(user);
        }
    }
}

这种方式下,只要集合内容变化,DataGrid就会更新,无需触发属性变更通知(前提是ProjectDbUsers初始化后未被重新赋值)。


内容的提问来源于stack exchange,提问作者E. A. Bagby

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 01:05:23