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

如何在WPF DataGrid中绑定可变更属性并同步至服务器

WPF DataGrid单元格变更后同步数据到服务器的正确绑定方式

问题背景

我有一个存储从外部网络资源获取数据的表格,当表格单元格内容变更时,需要将新数据发送至服务器。请问如何正确绑定存储新数据的属性?

现有代码如下:

View层DataGrid的XAML代码

<DataGrid Grid.Row="2"
          ItemsSource="{Binding Properties, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
          AutoGenerateColumns="False"
          IsReadOnly="False">
    <DataGrid.Columns>
        <DataGridTemplateColumn Header="Name">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBox Text="{Binding Path=name}"
                             IsReadOnly="False"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTemplateColumn Header="Value">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBox Text="{Binding Path=value}"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>

ViewModel层绑定至DataGrid的集合属性代码

private ObservableCollection<IProperties> _Properties;
public ObservableCollection<IProperties> Properties
{
    get => _Properties;
    set
    {
        _Properties = value;
        OnPropertyChanged(nameof(Properties));
    }
}

解决方案

1. 给实体类加上属性变更通知

你的IProperties接口对应的实体类必须实现INotifyPropertyChanged接口——这是核心前提,否则单元格修改后,ViewModel根本感知不到单个数据项的变化,更没法触发服务器提交。

示例实现:

public class PropertiesModel : IProperties, INotifyPropertyChanged
{
    private string _name;
    private string _value;

    public string name
    {
        get => _name;
        set
        {
            _name = value;
            OnPropertyChanged(nameof(name));
        }
    }

    public string value
    {
        get => _value;
        set
        {
            _value = value;
            OnPropertyChanged(nameof(value));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

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

2. 修正TextBox的绑定规则

当前XAML里的TextBox绑定缺少双向同步和即时更新触发,需要补充Mode=TwoWay和UpdateSourceTrigger=PropertyChanged,确保修改单元格内容的同时立刻同步到绑定的实体属性:

修改后的XAML:

<DataGrid Grid.Row="2"
          ItemsSource="{Binding Properties, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
          AutoGenerateColumns="False"
          IsReadOnly="False">
    <DataGrid.Columns>
        <DataGridTemplateColumn Header="Name">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBox Text="{Binding Path=name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                             IsReadOnly="False"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTemplateColumn Header="Value">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBox Text="{Binding Path=value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>

3. 监听变化并提交到服务器

有两种常用的实现方式,根据需求选择:

方式一:在实体类里直接触发提交

在实体类的属性变更方法里直接调用服务器接口,或者通过事件通知外部处理:

protected virtual void OnPropertyChanged(string propertyName)
{
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    // 可添加防抖逻辑,比如延迟500ms提交,避免连续输入时频繁请求
    SubmitToServer(this);
}

private async void SubmitToServer(PropertiesModel model)
{
    // 替换成你的实际服务器API调用
    // await _yourApiService.UpdateProperty(model.name, model.value);
}

方式二:在ViewModel里统一监听所有元素的变化

在ViewModel初始化集合时,给每个元素订阅PropertyChanged事件,统一处理提交逻辑:

public YourViewModel()
{
    // 加载外部数据并初始化集合
    Properties = new ObservableCollection<IProperties>(LoadExternalDataFromNetwork());
    
    // 给现有元素订阅事件
    foreach (var prop in Properties)
    {
        if (prop is INotifyPropertyChanged notifyProp)
        {
            notifyProp.PropertyChanged += OnPropertyItemChanged;
        }
    }
    
    // 监听集合的新增/移除,自动给新元素订阅事件
    Properties.CollectionChanged += (s, e) =>
    {
        if (e.NewItems != null)
        {
            foreach (var item in e.NewItems)
            {
                if (item is INotifyPropertyChanged notifyItem)
                {
                    notifyItem.PropertyChanged += OnPropertyItemChanged;
                }
            }
        }
        if (e.OldItems != null)
        {
            foreach (var item in e.OldItems)
            {
                if (item is INotifyPropertyChanged notifyItem)
                {
                    notifyItem.PropertyChanged -= OnPropertyItemChanged;
                }
            }
        }
    };
}

private async void OnPropertyItemChanged(object sender, PropertyChangedEventArgs e)
{
    var propertyItem = sender as IProperties;
    if (propertyItem == null) return;
    
    // 执行服务器提交
    // await _yourApiService.UpdateProperty(propertyItem.name, propertyItem.value);
}

额外提示

  • 批量提交场景:建议加防抖逻辑(比如用DispatcherTimer延迟提交),避免用户连续输入时发起大量请求。
  • 异步处理:服务器请求一定要用异步方法,别阻塞UI线程导致界面卡顿。
  • ViewModel本身要确保实现了INotifyPropertyChanged(你的代码里已经调用了OnPropertyChanged,应该没问题)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 17:35:13