.Net v4 DataGridTextColumn.IsReadOnly seems to be faulty

拟墨画扇 提交于 2019-11-27 08:51:10

Same as codekaizen but simpler:

<DataGridTextColumn>
  <DataGridTextColumn.CellStyle>
    <Style>
      <Setter Property="UIElement.IsEnabled" Value="{Binding IsEditable}" />
    </Style>
  </DataGridTextColumn.CellStyle>
</DataGridTextColumn>
codekaizen

DataGridColumns are not part of the visual tree, and don't participate in binding like this. The way I get around it is to use DataGridTemplateColumn.

<DataGridTemplateColumn>
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Path=myProperty}" />
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
    <DataGridTemplateColumn.CellEditingTemplate>
        <DataTemplate>
            <TextBox IsEnabled="{Binding Path=myBool}" Text="{Binding Path=myProperty, Mode=TwoWay}" />
        </DataTemplate>
    </DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>

There are other workarounds, which I've found a bit too hackish, but they do work; to wit: http://blogs.msdn.com/b/jaimer/archive/2008/11/22/forwarding-the-datagrid-s-datacontext-to-its-columns.aspx

I found this solution which allows you to bind to data when the DataContext is not inherited: http://www.thomaslevesque.com/2011/03/21/wpf-how-to-bind-to-data-when-the-datacontext-is-not-inherited/

Add the BindingProxy class Thomas wrote and add this resource to your DataGrid:

<DataGrid.Resources>
    <local:BindingProxy x:Key="proxy" Data="{Binding}" />
</DataGrid.Resources>

Now you can bind to your DataContex via the Data property of the BindingProxy just as you would expect.

<DataGridTextColumn Header="Price"
                    Binding="{Binding Price}"
                    IsReadOnly="{Binding Data.LockFields, Source={StaticResource proxy}}"/>

The Binding of the DataGridTextColumn works only for the Text property, but not for the other properties of DataGridTextColumn.

Solution: DataGridTextColumn tells the DataGrid to create a TextBlock for every row and that column. You can define a style for TextBlock and link the Style with the Style.Key to the TextBlock of that column (ElementStyle).

Of course, the TextBlock needs now to find the object from the datalist. It can do that with a RelativeSource Binding with the AncestorType=DataGridRow. The DataGridRow then provides access to the object.

Something like this:

<Window.Resources>
  <Style x:Key="IsReadOnlyStyle" TargetType="TextBlock">
    <Setter Property="IsReadOnly" 
      Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGridRow}}, 
      Path =Item.NoOutput/>
  </Style>
</Window.Resources>

<DataGrid>
  <DataGrid.Columns>
    <DataGridTextColumn Header="Value" Width="*" Binding="{Binding Value}" ElementStyle="{StaticResource IsReadOnlyStyle}"/>
</DataGrid.Columns>

Complicated right ? I recommend you to read my detailed article about datagrid formatting at: http://www.codeproject.com/Articles/683429/Guide-to-WPF-DataGrid-formatting-using-bindings?msg=5037235#xx5037235xx

Good luck, you need it :-)

If you like @codekaizen's solution but will have the look of a disabled TextBox, then this will do the trick:

<DataGridTemplateColumn>
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <TextBox IsEnabled="{Binding Path=myBool}" Text="{Binding Path=myProperty}" />
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
    <DataGridTemplateColumn.CellEditingTemplate>
        <DataTemplate>
            <TextBox IsEnabled="{Binding Path=myBool}" Text="{Binding Path=myProperty, Mode=TwoWay}" />
        </DataTemplate>
    </DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>

I've found a nice solution to use DataGridColumns with binding by using a MarkupExtension. This way Bindings with converters could be used: https://stackoverflow.com/a/27465022/9758687

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!