可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
If I create a binding to the IsReadOnly
property of the DataGridTextColumn
, it does not actualize. If I set it through markup, it works.
<DataGridTextColumn IsReadOnly="{Binding IsReferenceInactive}"/> <!-- NOP -->
<DataGridTextColumn IsReadOnly="True"/> <!-- Works as expected, cell is r/o -->
The IsReferenceInactive
property is a DP and works fine (For testing purposes I've bound it to a checkbox, that worked)
Is this a known limitation?
Update
Uups, other than I wrote, there is a message in the output window:
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=IsReferenceInactive; DataItem=null; target element is 'DataGridTextColumn' (HashCode=23836176); target property is 'IsReadOnly' (type 'Boolean')
Seems to be this one:
http://connect.microsoft.com/VisualStudio/feedback/details/530280/wpf-4-vs2010-datagrid-isreadonly-does-not-work-with-binding-to-boolean-property
回答1:
DataGridColumn
s 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
回答2:
Same as codekaizen but simpler:
<DataGridTextColumn>
<DataGridTextColumn.CellStyle>
<Style>
<Setter Property="UIElement.IsEnabled" Value="{Binding IsEditable}" />
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
回答3:
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}}"/>
回答4:
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 :-)
回答5:
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>
回答6:
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