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

WPF DataGridColumn绑定IsReadOnly时DataContext为null问题

问题原因

DataGridColumn 及其派生类(包括DataGridTextColumn、第三方的DataGridComboBoxColumn)的实例不属于WPF可视化树范畴,不会沿着控件树继承父级DataGrid的DataContext,因此直接在列属性上写{Binding IsLocked}找不到绑定源,会因为源为null失效。

你代码里两类绑定正常工作的逻辑非常明确:

  • 列的Binding属性(比如{Binding Name}、SelectedValueBinding这类)是列给生成的单元格/编辑控件传递的专用绑定配置,单元格加载时会自动将当前行的数据项作为绑定源,不需要列本身拿到DataContext
  • CellTemplate内的控件属于单元格可视化树的一部分,加载时DataContext就是当前行对应的数据项,因此{Binding IsLocked}可以正常取值

解决方案

根据IsLocked是全局ViewModel属性还是行级数据属性,选择对应方案即可:

方案1:全局统一控制列只读(所有行状态一致)

利用Freezable类可跨可视化树传递DataContext的特性,实现轻量绑定代理:

  1. 先在项目中添加代理类:
public class BindingProxy : Freezable
{
    protected override Freezable CreateInstanceCore() => new BindingProxy();

    public object Data
    {
        get => GetValue(DataProperty);
        set => SetValue(DataProperty, value);
    }
    public static readonly DependencyProperty DataProperty =
        DependencyProperty.Register(nameof(Data), typeof(object), typeof(BindingProxy), new PropertyMetadata(null));
}
  1. 在DataGrid所在的页面/窗口资源中声明代理实例,绑定到当前全局DataContext:
<UserControl.Resources>
    <local:BindingProxy x:Key="GridDataContextProxy" Data="{Binding}" />
</UserControl.Resources>
  1. 修改列上的IsReadOnly绑定,指定源为代理资源:
<DataGridTextColumn x:Name="NameColumn" 
                    Header="Name" 
                    Binding="{Binding Name, UpdateSourceTrigger=PropertyChanged}" 
                    IsReadOnly="{Binding Data.IsLocked, Source={StaticResource GridDataContextProxy}}" />

<materialDesign:DataGridComboBoxColumn
    Header="Produktart" 
    IsReadOnly="{Binding Data.IsLocked, Source={StaticResource GridDataContextProxy}, UpdateSourceTrigger=PropertyChanged}"
    IsEditable="True"
    Width="100"
    SelectedValueBinding="{Binding ProductType, UpdateSourceTrigger=PropertyChanged}"   
    ItemsSourceBinding="{Binding ProducerTypesValues, UpdateSourceTrigger=PropertyChanged }" />

方案2:行级控制只读(不同行根据自身IsLocked单独控制是否可编辑)

从你代码中IsLocked用于控制锁图标显示的逻辑判断,该场景更符合你的需求,最稳妥无额外依赖的方式是通过BeginningEdit事件拦截:

  1. 给DataGrid挂载事件,删掉列上原本失效的IsReadOnly="{Binding IsLocked}"配置:
<DataGrid BeginningEdit="DataGrid_OnBeginningEdit" 其余属性保持原有配置即可>
    <!-- 原有列代码 -->
</DataGrid>
  1. 在后台代码编写事件逻辑,判断当前行数据的IsLocked状态,锁定行直接取消编辑:
private void DataGrid_OnBeginningEdit(object sender, DataGridBeginningEditEventArgs e)
{
    if (e.Row.Item is 你的行数据实际类型 item && item.IsLocked)
    {
        e.Cancel = true;
    }
}

该方案对所有类型的列都生效,不需要额外编写代理类,也不需要逐列修改绑定配置。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 14:18:19