绑定 datagrid 列可见性 MVVM
Posted
技术标签:
【中文标题】绑定 datagrid 列可见性 MVVM【英文标题】:Bind datagrid column visibility MVVM 【发布时间】:2011-12-04 09:45:10 【问题描述】:.Net 3.5
我知道这些列不继承数据上下文,通过阅读其他帖子,我认为这会起作用:
Visibility="Binding RelativeSource=x:Static RelativeSource.Self,
Path=(FrameworkElement.DataContext).IsColumnNameVisible,
Converter=StaticResource boolToVisConverter"
当然不是.. 输出窗口没有报错,似乎是我找到的资源,但是viewmodel属性是新调用的。
这是整个 DG:
<tk:DataGrid
VirtualizingStackPanel.IsVirtualizing="False"
Grid.Column="0"
AlternationCount="2"
AreRowDetailsFrozen="True"
AutoGenerateColumns="False"
Background="Transparent"
BorderThickness="0"
CanUserAddRows="False"
CanUserReorderColumns="True"
CanUserResizeRows="False"
GridLinesVisibility="None"
ItemsSource="Binding Employees"
SelectionMode="Single"
ColumnHeaderStyle="StaticResource columnHeaderStyle"
RowHeaderStyle="StaticResource rowHeaderStyle"
CellStyle="StaticResource cellStyle"
RowStyle="StaticResource rowStyle"
ContextMenu="StaticResource columnHeaderContextMenu">
<tk:DataGrid.Resources>
<ContextMenu x:Key="columnHeaderContextMenu" ItemsSource="Binding ColumnHeaderContextMenuItems" />
<Style TargetType="x:Type ScrollBar">
<Setter Property="Background" Value="Transparent"/>
</Style>
<Style TargetType="x:Type tk:DataGridColumnHeader">
<Setter Property="Background" Value="Transparent"/>
</Style>
</tk:DataGrid.Resources>
<tk:DataGrid.Triggers>
<EventTrigger RoutedEvent="tk:DataGridRow.MouseDoubleClick">
<EventTrigger.Actions>
<BeginStoryboard Storyboard="StaticResource showDetailGrid"/>
</EventTrigger.Actions>
</EventTrigger>
</tk:DataGrid.Triggers>
<tk:DataGrid.Columns>
<tk:DataGridTextColumn IsReadOnly="True" Header="test" Binding="Binding Name, Mode=OneWay" Visibility="Binding RelativeSource=x:Static RelativeSource.Self, Path=(FrameworkElement.DataContext).IsColumnNameVisible, Converter=StaticResource boolToVisConverter" />
</tk:DataGrid.Columns>
</tk:DataGrid>
我已经阅读了该问题的几乎所有解决方案,但没有任何效果..
【问题讨论】:
如果您的问题有点不清楚。您是否只是试图根据绑定的 ViewModel 属性使数据列可见或不可见? 您在<tk:DataGrid.Resources>
中更改了 ContextMenu - 难怪您的窗口 DataContext 无法访问。
@ChrisBD:是的,就是这个想法。 VM 属性是通过 datacontext 设置的。
@Felix:什么意思?它是一个上下文菜单。为什么这会影响数据上下文的可用性?
【参考方案1】:
DataGridColumn
s 不是可视化树的一部分,因此它们没有连接到 DataGrid
的数据上下文。
让他们连接一起使用像这样的代理元素方法...
-
在祖先面板的
Resources
中添加代理FrameworkElement
。
将其托管到绑定到其Content
的不可见ContentControl
中。
将此ProxyElement
用作StaticResource
作为可见性绑定中的数据上下文源。
<StackPanel>
<StackPanel.Resources>
<local:BooleanToVisibilityConverter
x:Key="BooleanToVisibilityConverter" />
<FrameworkElement x:Key="ProxyElement"
DataContext="Binding"/>
</StackPanel.Resources>
<ContentControl Visibility="Collapsed"
Content="StaticResource ProxyElement"/>
<DataGrid AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn
Visibility="Binding DataContext.IsTextColumnVisibile,
Source=StaticResource ProxyElement,
Converter=StaticResource
BooleanToVisibilityConverter"
Binding="Binding Text"/>
</DataGrid.Columns>
</DataGrid>
</StackPanel>
除了DataGridColumn
,上述方法还可以很好地将DataContext
连接到Popup
s 和ContextMenu
s(即任何未连接到可视化树的元素)。
Silverlight 用户
遗憾的是,silverlight 中不允许使用任何框架元素设置内容控件的内容。所以解决方法是(这只是silverlight的指导代码)......
将框架元素资源更改为像Textblock
这样的轻量级元素。 (Silverlight 不允许指定 FrameworkElement
类型的静态资源。)
<StackPanel.Resources>
<TextBlock x:Key="MyTextBlock" />
编写一个附加属性以将文本块与内容控件保持一致。
<ContentControl Visibility="Collapsed"
local:MyAttachedBehavior.ProxyElement="StaticResource MyTextBlock" />
在附加的依赖属性更改事件处理程序中,设置将内容控件的数据上下文绑定到文本块的。
private static void OnProxyElementPropertyChanged(
DependencyObject depObj, DependencyPropertyChangedEventArgs e)
if (depObj is ContentControl && e.NewValue is TextBlock)
var binding = new Binding("DataContext");
binding.Source = depObj;
binding.Mode = OneWay;
BindingOperations.SetBinding(
(TextBlock)e.NewValue, TextBlock.DataContextProperty, binding);
因此,这样文本块可能不会连接到可视化树,但会可能知道数据上下文的变化。
希望这会有所帮助。
【讨论】:
取消选择和重新选择时出现异常:指定元素已经是另一个元素的逻辑子元素。先断开它。你知道为什么吗? 可能是你的ContextMenu
...它只能附加到一个父母。
将 ContextMenu 更改为 DataGrid CM 而不是 DGColumnHeader CM,但它没有帮助。如果这很重要,我会在多个列上使用它..
@WPF-如果我们仍然使用ProxyElement
,你能解释一下为什么这里需要ContentControl
吗? This 解决方案使用类似的方法,但不需要ContentControl
。
@monstr,Freezable 类破解了DataContext
...在我们的例子中,'proxyelement' 不是 Freezable,所以如果它托管在@987654346 中,它可以获得DataContext
的唯一方法@ 如果它是 Content
或 ContentControl
,则这是可能的。同样对于链接中的第二个解决方案,NameScoping
没有像DataGridColumnHeaderTemplate
一样在Template
中解析,所以ElementName
不起作用。我提供的解决方案可以解决这两种情况。以上是关于绑定 datagrid 列可见性 MVVM的主要内容,如果未能解决你的问题,请参考以下文章
如何将 WPF DataGrid DataColumns 可见性绑定到 UserControl 的 ViewModel 上的属性?