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

.NET 6 WinUI 3 Community Toolkit DataGrid 编程更新值后UI不刷新如何解决?

问题:WinUI3 Community Toolkit DataGrid按钮文本无法随属性变更同步更新

我在.NET 6 WinUI 3项目中使用Community Toolkit DataGrid,表格内包含一个按钮。点击按钮会触发事件,调用ViewModel中的方法更新绑定到按钮文本的Selected属性——该属性属于DataGrid选中项SelectedAssignUsersGrid对应的TempUser对象。

需求是:当Selected属性通过代码修改时,DataGrid UI中的按钮文本能同步更新。但目前遇到的问题是:大多数情况下属性变更后UI不更新,表现异常;双击按钮时偶尔会变化,但显示的值和实际属性值也经常不一致。

想知道这是DataGrid的固有问题,还是有可行方法让UI随绑定属性的变化同步更新?


相关代码

XAML DataGrid代码

<controls:DataGrid x:Name="dataGridAssignUsers_Temp" 
        Margin="12" GridLinesVisibility="All" HorizontalGridLinesBrush="PowderBlue" VerticalGridLinesBrush="PowderBlue"
        BorderBrush="PowderBlue" ScrollViewer.HorizontalScrollBarVisibility="Auto" 
        AutoGenerateColumns="False" 
        SelectedItem="{x:Bind ViewModel.SelectedAssignUsersGrid, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
        ItemsSource="{x:Bind ViewModel.AssignUsersGrid, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
    <controls:DataGrid.Columns>
        
        <controls:DataGridTemplateColumn Header="Select" Width="75">
            <controls:DataGridTemplateColumn.CellTemplate>
                <DataTemplate x:DataType="viewmodels:ProjectViewModel">
                    <Grid>
                        <Button Click="DataGridAssignUserSelect_Click"  HorizontalContentAlignment="Left" 
                                VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
                            <TextBlock>                                                        
                                <Run FontSize="12" Text="{Binding Selected,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
                            </TextBlock>
                        </Button>
                    </Grid>
                </DataTemplate>
            </controls:DataGridTemplateColumn.CellTemplate>
        </controls:DataGridTemplateColumn>
      
        <controls:DataGridTextColumn   IsReadOnly="True"
            Header="AD User Name" 
            Width="250"
            Binding="{Binding UserAdazureAduserName}" 
            FontSize="14" />
        <controls:DataGridTextColumn   IsReadOnly="False"
            Header="User Initials" 
            Width="250"
            Binding="{Binding AppUserInitials}" 
            FontSize="14" />
    </controls:DataGrid.Columns>                        
</controls:DataGrid>

后端事件代码

private void DataGridAssignUserSelect_Click(object sender, RoutedEventArgs e)
{           
    ViewModel.SelectAssignableUser();
    dataGridAssignUsers.UpdateLayout();
}

ViewModel代码

public partial class ProjectViewModel : ObservableObject, IDisposable
{
    ...

    [ObservableProperty]
    private ObservableCollection<TempUser> _assignUsersGrid; //Project users datagrid source.

    [ObservableProperty]
    public TempUser _selectedAssignUsersGrid = new(); //Item selected in the datagrid.

    public void SelectAssignableUser()
    {
        if (SelectedAssignUsersGrid is null) return;
        SelectedAssignUsersGrid.Selected = !SelectedAssignUsersGrid.Selected;
    }
    ...
}

绑定的实体类代码

public class TempUser
{
    public bool Selected { get; set; }
    public string AppUserInitials { get; set; }
    public string UserAdazureAduserName { get; set; }

    public TempUser() { }
}

问题原因及解决方法

核心原因

TempUser类没有实现属性变更通知机制,UI无法感知Selected属性的变化,这是导致UI不同步的根本原因,和DataGrid本身无关。

解决步骤

1. 让TempUser支持属性变更通知

利用Community Toolkit的ObservableObject简化实现,修改TempUser类:

public partial class TempUser : ObservableObject
{
    [ObservableProperty]
    private bool _selected;

    [ObservableProperty]
    private string _appUserInitials;

    [ObservableProperty]
    private string _userAdazureAduserName;

    public TempUser() { }
}

如果不想依赖Community Toolkit,也可以手动实现INotifyPropertyChanged接口:

public class TempUser : INotifyPropertyChanged
{
    private bool _selected;
    public bool Selected
    {
        get => _selected;
        set
        {
            if (_selected != value)
            {
                _selected = value;
                OnPropertyChanged(nameof(Selected));
            }
        }
    }

    private string _appUserInitials;
    public string AppUserInitials
    {
        get => _appUserInitials;
        set
        {
            if (_appUserInitials != value)
            {
                _appUserInitials = value;
                OnPropertyChanged(nameof(AppUserInitials));
            }
        }
    }

    private string _userAdazureAduserName;
    public string UserAdazureAduserName
    {
        get => _userAdazureAduserName;
        set
        {
            if (_userAdazureAduserName != value)
            {
                _userAdazureAduserName = value;
                OnPropertyChanged(nameof(UserAdazureAduserName));
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    public TempUser() { }
}

2. 修正DataTemplate的x:DataType

当前DataTemplate的x:DataType="viewmodels:ProjectViewModel"是错误的,DataGrid每行的上下文是TempUser对象,需修改为:

<DataTemplate x:DataType="models:TempUser">

(注意替换models为你实际的命名空间)

3. 优化按钮点击逻辑(可选)

当前实现依赖DataGrid的SelectedItem,若点击按钮时该行未被选中,会导致修改失败。可以直接从按钮的DataContext获取对应实体:

private void DataGridAssignUserSelect_Click(object sender, RoutedEventArgs e)
{           
    if (sender is Button btn && btn.DataContext is TempUser user)
    {
        user.Selected = !user.Selected;
        // 无需手动调用UpdateLayout,属性变更通知会自动更新UI
        // dataGridAssignUsers.UpdateLayout();
    }
}

内容的提问来源于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.07.24 05:30:15