首先DataGridTextColumn
或任何其他支持的dataGrid列不在DataGrid
的可视化树中。因此,默认它不会继承的DataGrid
。但是,它仅适用于Binding
DP,而DataGridColumn不适用于其他DP。
因为它们不在同一个VisualTree中,因此任何使用RelativeSource
获取DataContext的尝试都不会起作用,因为DataGrid无法遍历到DataGrid。
有两种方式来实现,虽然:
首先使用Freezable
类 - Freezable
对象甚至可以继承DataContext的,当他们在视觉或逻辑树不是。所以,我们可以利用这个优势来使用。
首先创建类从Freezable
和Data
DP继承,我们可以用它来在XAML绑定:
public class BindingProxy : Freezable
{
#region Overrides of Freezable
protected override Freezable CreateInstanceCore()
{
return new BindingProxy();
}
#endregion
public object Data
{
get { return (object)GetValue(DataProperty); }
set { SetValue(DataProperty, value); }
}
public static readonly DependencyProperty DataProperty =
DependencyProperty.Register("Data", typeof(object),
typeof(BindingProxy));
}
现在,在数据网格资源添加一个实例,以便它能够继承DataGrid的DataContext的,然后可以绑定其数据DP:
<DataGrid>
<DataGrid.Resources>
<local:BindingProxy x:Key="proxy" Data="{Binding}"/>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn Visibility="{Binding Data.MyColumnVisibility,
Source={StaticResource proxy}}"/>
</DataGrid.Columns>
</DataGrid>
二,你可以参考的XAML中的y UI元素使用ElementName
或x:Reference
。但ElementName
只能在同一个可视化树中工作,而x:引用不具有这样的约束。
所以,我们也可以使用它,以及我们的优势。在可见性设置为折叠的XAML中创建虚拟FrameworkElement
。 FrameworkElement将从其父容器(可以是Window或UserControl)继承DataContext。
而且可以使用DataGrid中:
<FrameworkElement x:Name="dummyElement" Visibility="Collapsed"/>
<DataGrid>
<DataGrid.Columns>
<DataGridTextColumn Header="Test"
Binding="{Binding Name}"
Visibility="{Binding DataContext.IsEnable,
Source={x:Reference dummyElement}}"/>
</DataGrid.Columns>
</DataGrid>
我喜欢第二种方法。这很容易编写,我已经有了相同可见性的另一个控件,所以我可以给它一个'x:Name'并引用它的'Visibility'属性。不是直截了当的,更多的是在路上横向转弯,但仍然很简单。我想,当绑定到被引用元素的DataContext属性时,你“劫持”另一个元素来共享它的DataContext和其他不可访问的DataGridColumn,对吧? dummyElement只是一个桥梁。 – ygoe
@LonelyPixel - 是的,你说得对。我尝试劫持DataGrid从它的DataGrid兄弟孩子,因为他们都共享相同的DataContext,除非明确设置。我可以使用x:DataGrid自身的引用,但这会导致循环依赖。 –
+1为您的答案。对不起,我误解了这个问题。通过使用'x:Reference' - 在WPF 4.0中,至少在Visual Studio 2010中可能仍然出现异常:'服务提供者缺少INameResolver服务',它可以被忽略。据我了解,它是在WPF 4.5中修复的。 –