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

WPF DataGrid绑定SelectedItem后ViewModel属性更新无法同步至DataGrid

问题:WPF中VM属性更新无法同步至DataGrid

在WPF UserControl中,存在一个只读DataGrid绑定至ViewModel(VM),其SelectedItem绑定到VM的属性。同时有两个TextBox:一个绑定SelectedItem的属性,修改后可同步至DataGrid;另一个绑定VM的属性,修改后无法同步到DataGrid。

相关XAML代码

<UserControl
    x:Class="PhoneAssistant.WPF.Features.ServiceRequests.ServiceRequestsMainView"
    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:local="clr-namespace:PhoneAssistant.WPF.Features.ServiceRequests"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    d:DataContext="{d:DesignInstance Type=local:ServiceRequestsMainViewModel}"
    d:DesignHeight="450"
    d:DesignWidth="800"
    mc:Ignorable="d">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Grid
            Grid.Row="0"
            Margin="16,20,0,15"
            d:Background="LightCoral">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="auto" />
                <ColumnDefinition Width="auto" />
            </Grid.ColumnDefinitions>
            <TextBox
                Grid.Column="0" Margin="0,0,5,0"
                Text="{Binding SelectedSR.BoundToSelected}" />
            <TextBox
                Grid.Column="1" Margin="0,0,5,0"
                Text="{Binding VmProperty}" />
        </Grid>
        <DataGrid
            Grid.Row="1" AutoGenerateColumns="False"
            IsReadOnly="true"
            ItemsSource="{Binding ServiceRequests}"
            SelectedItem="{Binding SelectedSR}"
            SelectionMode="Single" SelectionUnit="FullRow">
            <DataGrid.Columns>
                <DataGridTextColumn
                    Width="auto"
                    Binding="{Binding BoundToSelected}"
                    Header="BoundToSelected" />
                <DataGridTextColumn
                    Width="auto"
                    Binding="{Binding BoundToVMProperty}"
                    Header="BoundToVMProperty" />
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</UserControl>

相关C#代码

using System.Collections.ObjectModel;

using CommunityToolkit.Mvvm.ComponentModel;

namespace PhoneAssistant.WPF.Features.ServiceRequests;

public sealed partial class ServiceRequestsMainViewModel : ObservableObject, IServiceRequestsMainViewModel
{
    public ObservableCollection<ServiceRequest> ServiceRequests { get; } = new();

    [ObservableProperty]
    private ServiceRequest _selectedSR;

    partial void OnSelectedSRChanged(ServiceRequest value)
    {
        VmProperty = value.BoundToVMProperty;
    }

    [ObservableProperty]
    // Neither of these notifies update the datagrid
    [NotifyPropertyChangedFor(nameof(ServiceRequests))]   
    [NotifyPropertyChangedFor(nameof(SelectedSR))]
    private string _vmProperty;
    
    partial void OnVmPropertyChanged(string value)
    {
        SelectedSR.BoundToVMProperty = value;
    }

    public Task LoadAsync()
    {
        ServiceRequests.Add(new ServiceRequest() { Id = 1, BoundToSelected = "SomeValue1", BoundToVMProperty = "AnotherValee1"});
        ServiceRequests.Add(new ServiceRequest() { Id = 2, BoundToSelected = "SomeValue2", BoundToVMProperty = "AnotherValee2" });
        ServiceRequests.Add(new ServiceRequest() { Id = 3, BoundToSelected = "SomeValue3", BoundToVMProperty = "AnotherValee3" });
        return Task.CompletedTask;
    }
}


public sealed class ServiceRequest
{
    public int Id { get; init; }
    public string BoundToSelected { get; set; }
    public string BoundToVMProperty { get; set; }
}

解决方案

核心问题在于ServiceRequest类的属性没有实现属性更改通知,导致DataGrid无法感知到属性值的变化。WPF数据绑定依赖INotifyPropertyChanged接口来更新UI,当属性值变化时需要触发PropertyChanged事件。

步骤1:修改ServiceRequest类,实现属性更改通知

借助CommunityToolkit.Mvvm的ObservableObject基类和[ObservableProperty]特性,可以快速实现通知机制:

using CommunityToolkit.Mvvm.ComponentModel;

namespace PhoneAssistant.WPF.Features.ServiceRequests;

public sealed partial class ServiceRequest : ObservableObject
{
    public int Id { get; init; }

    [ObservableProperty]
    private string _boundToSelected;

    [ObservableProperty]
    private string _boundToVMProperty;
}

步骤2:调整ViewModel中的绑定逻辑(可选优化)

ViewModel中原来的[NotifyPropertyChangedFor]注解可以移除,因为它们对解决当前问题没有作用。修改后的ViewModel代码如下:

using System.Collections.ObjectModel;

using CommunityToolkit.Mvvm.ComponentModel;

namespace PhoneAssistant.WPF.Features.ServiceRequests;

public sealed partial class ServiceRequestsMainViewModel : ObservableObject, IServiceRequestsMainViewModel
{
    public ObservableCollection<ServiceRequest> ServiceRequests { get; } = new();

    [ObservableProperty]
    private ServiceRequest _selectedSR;

    partial void OnSelectedSRChanged(ServiceRequest value)
    {
        VmProperty = value.BoundToVMProperty;
    }

    [ObservableProperty]
    private string _vmProperty;
    
    partial void OnVmPropertyChanged(string value)
    {
        SelectedSR?.BoundToVMProperty = value;
    }

    public Task LoadAsync()
    {
        ServiceRequests.Add(new ServiceRequest() { Id = 1, BoundToSelected = "SomeValue1", BoundToVMProperty = "AnotherValee1"});
        ServiceRequests.Add(new ServiceRequest() { Id = 2, BoundToSelected = "SomeValue2", BoundToVMProperty = "AnotherValee2" });
        ServiceRequests.Add(new ServiceRequest() { Id = 3, BoundToSelected = "SomeValue3", BoundToVMProperty = "AnotherValee3" });
        return Task.CompletedTask;
    }
}

原理说明

  • 当VmProperty修改时,OnVmPropertyChanged会更新SelectedSR.BoundToVMProperty的值。
  • 由于ServiceRequest现在继承了ObservableObject,BoundToVMProperty属性变化时会自动触发PropertyChanged事件。
  • DataGrid的列绑定会监听该事件,从而自动更新对应单元格的显示内容。

内容的提问来源于stack exchange,提问作者JCL

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 22:07:56