C# 如何将Datagrid列的可见性绑定到WPF中的复选框
我在DataGrid中有几个列,我希望根据该列的复选框显示或隐藏这些列。我事先搜索了不少,找到了许多不同的答案,但在每种情况下,它们要么不起作用,要么针对不同的情况 如果我理解正确,ElementName将无法工作,因为可视化树不可用。然而,我尝试设置源和相对源,但没有任何运气。在当前状态下,它返回错误:未解析的引用“filterDuration”。该错误使程序停止运行 更新了以下建议和更多信息,但仍未解决 这是转换器:(它甚至从来没有进入这一步) 以下是复选框:C# 如何将Datagrid列的可见性绑定到WPF中的复选框,c#,wpf,xaml,C#,Wpf,Xaml,我在DataGrid中有几个列,我希望根据该列的复选框显示或隐藏这些列。我事先搜索了不少,找到了许多不同的答案,但在每种情况下,它们要么不起作用,要么针对不同的情况 如果我理解正确,ElementName将无法工作,因为可视化树不可用。然而,我尝试设置源和相对源,但没有任何运气。在当前状态下,它返回错误:未解析的引用“filterDuration”。该错误使程序停止运行 更新了以下建议和更多信息,但仍未解决 这是转换器:(它甚至从来没有进入这一步) 以下是复选框: <DataTemplat
<DataTemplate x:Key="Settings">
<DockPanel>
<GroupBox Header="Filter Columns" DockPanel.Dock="Right">
<ag:AutoGrid Columns="150, 150, 150" RowCount="7" RowHeight="20">
<CheckBox Content="Id" />
<CheckBox Content="Desc" />
<CheckBox x:Name="filterDuration" Content="Duration" />
</ag:AutoGrid>
</GroupBox>
</DockPanel>
</DataTemplate>
这是DataGrid:(为了简洁起见,删除了额外的列和属性)
您的示例对我很有用,您不应该被设计器中的错误弄糊涂,在运行时它是有效的-x:引用绑定似乎让设计器有点困惑 除此之外,您的值转换器中还有一些小错误:
- 返回“value”的ConvertBack是错误的,它应该将可视性转换为布尔值。 您应该正确地实现这一点,因为您进行了双向绑定。(虽然我不知道为什么要这样做,但我认为单向绑定就足够了。列的可见性毕竟不是用户可以更改的,所以不需要将其更改传播回复选框,对吗?)
- 您应该声明值转换器在类的属性中处理的类型:
[ValueConversion(typeof(bool)、typeof(Visibility))]
通过更新的问题,您需要一种链接不同上下文的方法。如果无法通过向ViewModel添加属性来完成此操作,则仍然可以创建资源对象。Rohit Vats的另一个答案滥用复选框作为资源对象。如果您想要一种“更干净”的方法,只需为选中状态定义一个新的DependencyObject子类,该子类具有DependencyProperty,然后将该类的实例放入静态资源中。然后,可以使用此资源使控件相互通信。您的示例对我来说很有用,您不应该被设计器中的错误弄糊涂,在运行时它是有效的-x:引用绑定似乎会让设计器非常困惑 除此之外,您的值转换器中还有一些小错误:
- 返回“value”的ConvertBack是错误的,它应该将可视性转换为布尔值。 您应该正确地实现这一点,因为您进行了双向绑定。(虽然我不知道为什么要这样做,但我认为单向绑定就足够了。列的可见性毕竟不是用户可以更改的,所以不需要将其更改传播回复选框,对吗?)
- 您应该声明值转换器在类的属性中处理的类型:
[ValueConversion(typeof(bool)、typeof(Visibility))]
通过更新的问题,您需要一种链接不同上下文的方法。如果无法通过向ViewModel添加属性来完成此操作,则仍然可以创建资源对象。Rohit Vats的另一个答案滥用复选框作为资源对象。如果您想要一种“更干净”的方法,只需为选中状态定义一个新的DependencyObject子类,该子类具有DependencyProperty,然后将该类的实例放入静态资源中。然后可以使用此资源使控件相互通信。DataTemplate内的控件没有相同的名称范围,因此无法通过ElementName或x:Reference从其名称范围外的控件绑定 作为一种解决方法,您可以通过以下方式实现:
代码:
.........
.........
在数据模板中:
注意-如果无法从dataTemplate中的Dockpanel resources部分访问资源,您还可以在window resources部分下声明该资源
显然,理想的解决方案是:
DataTemplate内的控件没有相同的名称范围,因此不能通过ElementName或x:Reference从其名称范围外的控件绑定 作为一种解决方法,您可以通过以下方式实现:
代码:
.........
.........
在数据模板中:
注意-如果无法从dataTemplate中的Dockpanel resources部分访问资源,您还可以在window resources部分下声明该资源
显然,理想的解决方案是:
在小样本中进行了尝试,您的代码在我这边运行良好
<DataTemplate x:Key="Settings">
<DockPanel>
<GroupBox Header="Filter Columns" DockPanel.Dock="Right">
<ag:AutoGrid Columns="150, 150, 150" RowCount="7" RowHeight="20">
<CheckBox Content="Id" />
<CheckBox Content="Desc" />
<CheckBox x:Name="filterDuration" Content="Duration" />
</ag:AutoGrid>
</GroupBox>
</DockPanel>
</DataTemplate>
<DockPanel Grid.Row="0" Grid.Column="0">
<Expander DockPanel.Dock="Top" Header="{x:Static p:Resources.shSettings}" ContentTemplate="{StaticResource Settings}" IsExpanded="True" />
<Border DockPanel.Dock="Top" Background="#FF595959">
<TextBlock Text="{x:Static p:Resources.shViolations}" Style="{StaticResource SectionHeaderText}" />
</Border>
<DataGrid IsReadOnly="True" ItemsSource="{Binding items}" SelectedItem="{Binding Path=selecteditem}" AutoGenerateColumns="False" >
<DataGrid.Columns>
<DataGridTextColumn Header="Duration" Binding="{Binding Duration}" Visibility="{Binding Source={x:Reference filterDuration}, Path=IsChecked, Converter={StaticResource FilterVisibility}}" />
<DataGridTextColumn Header="CTG Id" Binding="{Binding Id}" />
</DataGrid.Columns>
</DataGrid>
</DockPanel>
<DockPanel .....>
<DockPanel.Resources>
<CheckBox x:Key="DummyCheckBox"/>
</DockPanel.Resources>
.........
<DataGridTextColumn Header="Duration" Binding="{Binding Duration}"
Visibility="{Binding Source={StaticResource DummyCheckBox},
Path=IsChecked, Converter={StaticResource FilterVisibility}}"/>
.........
</DockPanel>
<CheckBox x:Name="filterDuration" Content="Duration"
IsChecked="{Binding IsChecked, Source={StaticResource DummyCheckBox}}"/>