MVVM下的WPF DataGridTemplateColumn可见性绑定
我的ViewModel中有一个绑定到ICollectionView的DataGrid。DataGrid位于UserControl内部,UserControl用于几个不同的数据场景,其中一些场景需要特定的DataGrid列,而其他场景则不需要 我只想将DataGridTemplateColumn的Visibility属性绑定到内部标签的Content属性,这样,如果所有行都不包含值,它将被隐藏。我设置了一个字符串到可见性转换器,但无法找到内部标签的内容属性MVVM下的WPF DataGridTemplateColumn可见性绑定,wpf,binding,mvvm,datagrid,wpfdatagrid,Wpf,Binding,Mvvm,Datagrid,Wpfdatagrid,我的ViewModel中有一个绑定到ICollectionView的DataGrid。DataGrid位于UserControl内部,UserControl用于几个不同的数据场景,其中一些场景需要特定的DataGrid列,而其他场景则不需要 我只想将DataGridTemplateColumn的Visibility属性绑定到内部标签的Content属性,这样,如果所有行都不包含值,它将被隐藏。我设置了一个字符串到可见性转换器,但无法找到内部标签的内容属性 <DataGridTemplate
<DataGridTemplateColumn Header="Groups" Width="*" CanUserSort="True" SortMemberPath="Groups" Visibility="{Binding ElementName=lbl, Path=Content, Converter={StaticResource StringToVisibilityConverter}}">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Label Name="lbl" Content="{Binding Path=Groups}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
有什么建议吗?通过ViewModel上的
组
属性可以更好地实现这一点;因为无论怎样,标签
最终都是这样使用的
<DataGridTemplateColumn Header="Groups" Width="*" CanUserSort="True" SortMemberPath="Groups" Visibility="{Binding Groups, Converter={StaticResource SomeConverter}}">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Label Name="lbl" Content="{Binding Path=Groups}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
您不能这样做。绑定/名称解析不能以这种方式工作。为什么不使用StringToVisibilityConverter
创建一个CollectionToVisibilityConverter
,它检查数据源(可能传入要检查的列/属性),查看该列/属性是否完全为空,然后将其转换为可见性?我在堆栈溢出的某个地方读到了(找不到确切的帖子)DataGridColumn没有分配数据上下文,因为它们不是FrameworkElement。要解决这个问题,我必须使用与此类似的代码:
<DataGridTemplateColumn
Header="Groups"
Width="*"
CanUserSort="True"
SortMemberPath="Groups"
Visibility"{Binding RelativeSource={x:Static RelativeSource.Self},
Path=(FrameworkElement.DataContext).IsGroupsVisible,
Converter={StaticResource booleanToVisiblityConverter}}">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Label Name="lbl" Content="{Binding Path=Groups}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
Where
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="booleanToVisibilityConverter" />
</UserControl.Resources>
哪里
要使用相对资源.Self
作为数据网格模板列的相对资源
绑定,您需要将添加到应用程序中。这对于WPF 4数据网格仍然是必需的
<DataGridTemplateColumn
Header="Groups"
Width="*"
CanUserSort="True"
SortMemberPath="Groups"
Visibility"{Binding RelativeSource={x:Static RelativeSource.Self},
Path=(FrameworkElement.DataContext).IsGroupsVisible,
Converter={StaticResource booleanToVisiblityConverter}}">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Label Name="lbl" Content="{Binding Path=Groups}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
100感谢SliverNinja和本文。源代码的链接已经不起作用,无法下载,因此我编写了自己的附件,使其适用于所有可能的情况(DataContext更改、附件属性值更改、添加列)
我的应用程序将DataGrid与AutoGenerateColumns=False一起使用,并使用DataGridTemplateColumn,因此DataContext是在将列添加到网格之前设置的
以下是附加的属性类别:
public sealed class DataGridColumnDataContextForwardBehavior
{
private DataGrid dataGrid = null;
public DataGridColumnDataContextForwardBehavior(DataGrid dataGrid)
{
this.dataGrid = dataGrid;
dataGrid.Columns.CollectionChanged += DataGridColumns_CollectionChanged;
}
private void DataGridColumns_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
var IsDataContextForwardingEnabled = GetIsDataContextForwardingEnabled(dataGrid);
if (IsDataContextForwardingEnabled && dataGrid.DataContext != null)
{
if (e.Action == NotifyCollectionChangedAction.Add)
{
foreach (DataGridColumn column in e.NewItems)
{
column.SetValue(FrameworkElement.DataContextProperty, dataGrid.DataContext);
}
}
}
}
static DataGridColumnDataContextForwardBehavior()
{
FrameworkElement.DataContextProperty.AddOwner(typeof(DataGridColumn));
FrameworkElement.DataContextProperty.OverrideMetadata(typeof(DataGrid),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits, new PropertyChangedCallback(OnDataContextChanged)));
}
public static readonly DependencyProperty IsDataContextForwardingEnabledProperty =
DependencyProperty.RegisterAttached("IsDataContextForwardingEnabled", typeof(bool), typeof(DataGridColumnDataContextForwardBehavior),
new FrameworkPropertyMetadata(false, OnIsDataContextForwardingEnabledChanged));
public static void OnDataContextChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
DataGrid dataGrid = obj as DataGrid;
if (dataGrid == null) return;
var IsDataContextForwardingEnabled = GetIsDataContextForwardingEnabled(dataGrid);
if (IsDataContextForwardingEnabled)
{
foreach (DataGridColumn col in dataGrid.Columns)
{
col.SetValue(FrameworkElement.DataContextProperty, e.NewValue);
}
}
}
static void OnIsDataContextForwardingEnabledChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
var dataGrid = obj as DataGrid;
if (dataGrid == null) return;
new DataGridColumnDataContextForwardBehavior(dataGrid);
if (!(e.NewValue is bool)) return;
if ((bool)e.NewValue && dataGrid.DataContext != null)
OnDataContextChanged(obj, new DependencyPropertyChangedEventArgs(FrameworkElement.DataContextProperty, dataGrid.DataContext, dataGrid.DataContext));
}
public static bool GetIsDataContextForwardingEnabled(DependencyObject dataGrid)
{
return (bool)dataGrid.GetValue(IsDataContextForwardingEnabledProperty);
}
public static void SetIsDataContextForwardingEnabled(DependencyObject dataGrid, bool value)
{
dataGrid.SetValue(IsDataContextForwardingEnabledProperty, value);
}
}
另一个不明显的问题是如何正确使用DataGridTemplateColumn的绑定:
<DataGrid bhv:DataGridColumnDataContextForwardBehavior.IsDataContextForwardingEnabled="True">
<DataGrid.Columns>
<DataGridTemplateColumn Visibility="{Binding Path=DataContext.Mode, RelativeSource={RelativeSource Self}, Converter={StaticResource SharedFilesModeToVisibilityConverter}, ConverterParameter={x:Static vmsf:SharedFilesMode.SharedOut}}"/>
使用Path=DataContext.MyProp和relativesourceself是很重要的
在当前的实现中,我唯一不喜欢的事情就是处理DataGrid.Columns.CollectionChanged事件,我创建了我的类的实例,并且没有保留对它的引用。因此理论上GC可能会在时间内杀死它,目前不确定如何正确处理它,稍后会考虑它并更新我的帖子。欢迎任何想法和评论 大家好,我已经试过了,在运行时遇到了这个错误:System.Windows.Data错误:2:找不到目标元素的治理FrameworkElement或FrameworkContentElement。BindingExpression:Path=Groups;DataItem=null;目标元素是“DataGridTemplateColumn”(HashCode=38907373);目标属性是“可见性”(类型“可见性”)令人沮丧的是,当我使用XAML中定义的CollectionViewSource时,通过将可见性绑定源设置为CollectionViewSource,这实际上起到了作用。我必须将CollectionViewSource移动到ViewModel中以处理排序/筛选,这打破了此可见性绑定。还有其他想法吗?CollectionViewSource是C的XAML代理CollectionView。在您的ViewModel中返回ICollectionView ala…CollectionViewSource.GetDefaultView(您的集合)抱歉,我的错误,这是我从ViewModel返回的数据网格的ItemsSource,它抛出了“System.Windows.Data Error:2”关于可见性绑定。我甚至尝试绑定到ViewModel中的一个专用属性,但它仍然找不到。这是在编译时…或运行时?它是否击中了您的转换器?嗨,Andy,很有趣。现在没有收到任何绑定错误,但它仍然不工作。转换器甚至没有被调用…是ViewMod上的一个属性吗是DataGrid绑定到的属性?还是DataGrid中的行绑定到的单个项上的属性?我假设两者都是,因为您希望在单个单元格中显示文本,并且网格中列的可见性只能绑定到一个属性。它是DataGrid中单个项上的属性llection设置为CollectionViewSource的源,并作为ICollectionView返回到DataGrid。我还尝试将其绑定到ViewModel上的一个名为IsGroupsVisible的属性权限,该属性不太优雅,但它也无法识别。我已将上述代码更改为使用IsGroupsVisible属性。它甚至没有调用ViewModel属性!我开始认为这是一个WPF错误。当我放置相同的代码时:Visibility=“{Binding RelativeSource={x:Static RelativeSource.Self},Path=(FrameworkElement.DataContext).IsGroupVisibility,Converter={StaticResource BootVisibilityConverter}”在我看来,在任何其他控件上,它都可以完美地工作。任何想要找到答案的人,请参阅