我有以下WPF示例程序:
的Xaml:
<Window x:Class="AncestorArie.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVis" />
</Window.Resources>
<Grid>
<DataGrid AutoGenerateColumns="False" Name="Blumen"
ItemsSource="{Binding Leaves}">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Color}"
Header="Farbe" Width="160" />
<DataGridTextColumn Binding="{Binding Size}"
Header="Größe" Width="60"
Visibility="{Binding Path=DataContext.Flag,
RelativeSource={RelativeSource Findancestor,
AncestorType={x:Type Window}},
Converter={StaticResource BoolToVis}}" />
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
代码背后:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Flowers rose = new Flowers();
rose.Leaves = new ObservableCollection<Leaf>();
rose.Flag = false;
Leaf L1 = new Leaf();
L1.Color = "rot";
L1.Size = 3;
rose.Leaves.Add(L1);
Leaf L2 = new Leaf();
L2.Color = "gelb";
L2.Size = 2;
rose.Leaves.Add(L2);
this.DataContext = rose;
}
}
模型类是:
public class Leaf
{
public string Color { get; set; }
public int Size { get; set; }
}
public class Flowers
{
public bool Flag { get; set; }
public ObservableCollection<Leaf> Leaves { get; set; }
}
如您所见,如果Flag
属性设置为false,我想隐藏第二个datagrid列。但它不起作用。我在Visual Studio输出窗口中收到以下绑定错误:
System.Windows.Data错误:4:找不到绑定源 参考'RelativeSource FindAncestor, AncestorType ='System.Windows.Window',AncestorLevel ='1''。 BindingExpression:路径= DataContext.Flag;的DataItem = NULL;目标要素 是'DataGridTextColumn'(HashCode = 44856655);目标属性是 '可见性'(类型'可见性')
我的代码中有关Visibility
属性的错误是什么?
答案 0 :(得分:48)
数据网格中的列是一个抽象对象,它不会出现在可视化树中,因此您无法使用RelativeSource
- 绑定,ElementName
将无法工作,因为它无法找到一个管理FrameworkContentElement所以你是一个约束。
一种有效的方法是通过Source
和x:Reference
,为此您需要命名窗口并将列移动到其资源以避免出现周期性依赖性错误:
<Window Name="_window" ...>
<Window.Resources>
<DataGridTextColumn x:Key="ThatPeskyColumn"
Binding="{Binding Size}"
Visibility="{Binding DataContext.Flag, Source={x:Reference _window}, Converter={StaticResource BoolToVis}}"/>
</Window.Resources>
<!-- ... -->
<DataGrid AutoGenerateColumns="False" Name="Blumen"
ItemsSource="{Binding Leaves}">
<DataGrid.Columns>
<StaticResource ResourceKey="ThatPeskyColumn"/>
<!-- ... -->
很有趣。
答案 1 :(得分:6)
我希望采用更优雅的方法,包括使用Freezable
。
<Window.Resources>
<DiscreteObjectKeyFrame x:Key="FlagKey" Value="{Binding Flag}"/>
</Window.Resources>
<DataGridTextColumn ... Visibility="{Binding Value, Source={StaticResource FlagKey}, ...}" />
答案 2 :(得分:4)
DataGridTextColumn上的可见性不是DependencyProperty,也不能是数据绑定。使用DataGridTemplateColumn并绑定模板中控件的可见性。
编辑:实际上,此声明仅适用于silverlight。有关详细信息,请参阅此其他问题。
How to bind DataGridColumn.Visibility?
我询问了最简单的判断属性是否依赖于此的方法。
How can I most easily determine whether a property is a dependency property?
答案 3 :(得分:0)
H.B.提出的解决方案非常好,并拥有真正的WPF MVVM精神。尽可能使用它。
在我的特定情况下出了问题所以我以不同的方式出来,因为我的项目不是严格的MVVM,所以我可以使用编码解决方案。
在分配给列的CustomView.xaml名称中:
<DataGrid>
<DataGrid.Columns>
<DataGridTemplateColumn x:Name="MachinesColumn" ... />
...
在CustomView.xaml.cs中,我们有一个简单的属性,可直接更改列的可见性:
public Visibility MachinesColumnVisible
{
get { return MachinesColumn.Visibility; }
set
{
if (value == MachinesColumn.Visibility)
return;
MachinesColumn.Visibility = value;
}
}
答案 4 :(得分:0)
如果您要自动生成列,则可以使用一个事件:
我正在更改为自动生成的列和此事件以解决几个问题!也可用于更改列上的标题。