禁用特定数据网格单元与绑定

本文关键字:网格 单元 绑定 数据网 数据 | 更新日期: 2023-09-27 18:09:45

我正在尝试将自定义数据对象列表绑定到数据网格并实现以下行为。

  1. 填充网格
  2. 基于对象数据禁用某些单元格。

考虑以下DataGrid

<DataGrid ItemsSource="{Binding Path=CustomObjectList}">
    <DataGrid.Columns>
        <DataGridTextColumn Binding="{Binding Path=FieldName}"
                            Header="Field Name"
                            IsReadOnly="True" />
        <DataGridCheckBoxColumn Binding="{Binding Path=Compare}"
                                Header="Compare" />
        <DataGridTextColumn Binding="{Binding Path=Tolerance}"
                            Header="Tolerance" />
    </DataGrid.Columns>
</DataGrid>

有了这样一个支持对象…

public class CustomObject: BaseModel
{
    private bool _compare;
    private bool _disableTolerance;
    private string _fieldName;
    private bool _mustCompare;
    private double _tolerance;
    /// <summary>
    /// Gets or sets the compare.
    /// </summary>
    /// <value>The compare.</value>
    public bool Compare
    {
        get
        {
            return this._compare;
        }
        set
        {
            this._compare = value;
            this.NotifyPropertyChange("Compare");
        }
    }
    /// <summary>
    /// Gets or sets the disable tolerance.
    /// </summary>
    /// <value>The disable tolerance.</value>
    public bool DisableTolerance
    {
        get
        {
            return this._disableTolerance;
        }
        set
        {
            this._disableTolerance = value;
            this.NotifyPropertyChange("DisableTolerance");
        }
    }
    /// <summary>
    /// Gets or sets the name of the field.
    /// </summary>
    /// <value>The name of the field.</value>
    public string FieldName
    {
        get
        {
            return this._fieldName;
        }
        set
        {
            this._fieldName = value;
            this.NotifyPropertyChange("FieldName");
        }
    }
    /// <summary>
    /// Gets or sets the must compare.
    /// </summary>
    /// <value>The must compare.</value>
    public bool MustCompare
    {
        get
        {
            return this._mustCompare;
        }
        set
        {
            this._mustCompare = value;
            this.NotifyPropertyChange("MustCompare");
        }
    }
    /// <summary>
    /// Gets or sets the tolerance.
    /// </summary>
    /// <value>The tolerance.</value>
    public double Tolerance
    {
        get
        {
            return this._tolerance;
        }
        set
        {
            this._tolerance = value;
            this.NotifyPropertyChange("Tolerance");
        }
    }
}

您可以考虑这样填充CustomObjectList…

this.ComparisonsAndTolerances.Add(new ComparisonSettingsTolerances()
{
    FieldName = "Alpha",
    Compare = true,
    MustCompare = true,
    Tolerance = 0,
    DisableTolerance = false
});
this.ComparisonsAndTolerances.Add(new ComparisonSettingsTolerances()
{
    FieldName = "Bravo",
    Compare = true,
    MustCompare = false,
    Tolerance = 0,
    DisableTolerance = true
});

因此,当然FieldName, Compare,和Tolerance属性被适当地填充到网格中。

然而,我想要实现的是,当MustCompare为true时,该单元格被标记为只读。当disablettolerance为true时,该单元格被标记为只读。

显然,这将因细胞和行与4种不同的组合而异,但我希望通过绑定来实现这一点。

我试着

IsReadOnly="{Binding Path=MustCompare}"

IsReadOnly="{Binding Path=CustomObjectList/MustCompare}"

但这两种方法都不起作用。

谢谢。

禁用特定数据网格单元与绑定

这是一个有趣的bug/情况。

会发生什么?好吧,绑定试图绑定到MustCompare属性(并且可能已经成功),但它找不到FrameworkElementFrameworkContentElement作为绑定的目标,因为没有数据网格的列在可视化树中。

有一个解决方案,尽管没有你(正确的)尝试做的那么优雅:

<DataGridTemplateColumn Header="Compare">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <TextBlock x:Name="TextHolder" />
            <DataTemplate.Triggers>
                <DataTrigger Binding="{Binding Path=Compare}"
                             Value="True">
                    <Setter TargetName="TextHolder"
                            Property="Text"
                            Value="True" />
                </DataTrigger>
                <DataTrigger Binding="{Binding Path=Compare}"
                             Value="False">
                    <Setter TargetName="TextHolder"
                            Property="Text"
                            Value="False" />
                </DataTrigger>
            </DataTemplate.Triggers>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
    <DataGridTemplateColumn.CellEditingTemplate>
        <DataTemplate>
            <CheckBox x:Name="Check"
                      IsChecked="{Binding Path=Compare}"
                      ToolTipService.ShowOnDisabled="True"/>
            <DataTemplate.Triggers>
                <DataTrigger Binding="{Binding Path=MustCompare}"
                             Value="True">
                    <Setter TargetName="Check"
                            Property="IsEnabled"
                            Value="False" />
                    <Setter TargetName="Check"
                            Property="ToolTip"
                            Value="You cannot change this value since this item must compare" />
                </DataTrigger>
            </DataTemplate.Triggers>
        </DataTemplate>
    </DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>

我已经改变了单元格,所以它在非编辑模式下显示文本,在编辑时显示复选框(只是为了看看单元格处于什么状态,你可以在两种情况下将其更改为复选框)。

这不是最优的,如果你(或任何人)找到一个更好的解决方案,我想听听你的意见。

编辑:

我想到了另一个解决方案:

<DataGridCheckBoxColumn Binding="{Binding Path=Compare}"
                        Header="Compare">
    <DataGridCheckBoxColumn.CellStyle>
        <Style TargetType="{x:Type DataGridCell}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding MustCompare}"
                             Value="True">
                    <Setter Property="IsEnabled"
                            Value="False" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </DataGridCheckBoxColumn.CellStyle>
</DataGridCheckBoxColumn>

这会使复选框在非编辑模式下被禁用,因此它看起来不同。这可能是好事,也可能是坏事,这取决于你的功能设计。