5

I'm trying to bind a list of custom data objects to a data grid and achieve the following behavior.

  1. Populate the grid
  2. Disable certain cells based on object data.

Consider the following 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>

With a backing object like this...

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");
        }
    }
}

And you can consider the CustomObjectList to be populated like this...

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
});

So, of course the FieldName, Compare, and Tolerance properties are filling into the grid appropriately.

However, what I would like to achieve is, when MustCompare is true, then that cell is marked as read only. And when DisableTolerance is true, that cell is marked as read only.

Obviously this will vary from cell to cell and row to row with the 4 different combinations, but I was hoping to achieve this through binding.

I tried

IsReadOnly="{Binding Path=MustCompare}"

and

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

But neither of those worked.

Thanks.

4

1 回答 1

6

这是您遇到的一个有趣的错误/情况。

怎么了?好吧,绑定正在尝试绑定到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>

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

于 2013-05-05T18:20:54.667 回答