MVF DataGridTemplateColumn MVVM下的可见性绑定

时间:2011-03-17 15:40:32

标签: wpf binding mvvm datagrid wpfdatagrid

我有一个DataGrid绑定到我的ViewModel中的ICollectionView。 DataGrid位于UserControl中,用于几种不同的数据场景,其中一些需要某些DataGrid列,而另一些则不需要。

我只想将DataGridTemplateColumn的Visibility属性绑定到内部标签的Content属性,因此如果没有任何行包含值,它将被隐藏。我有一个String to Visibility转换器集,但无法弄清楚如何找到内部lable的Content属性。

<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>

有什么建议吗?

5 个答案:

答案 0 :(得分:4)

我在Stack Overflow(无法找到确切的帖子)的某处读到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>

答案 1 :(得分:2)

要将RelativeSource.Self用作RelativeSource的{​​{1}}绑定,您需要将DataGridContextHelper添加到您的应用中。这仍然是WPF 4 DataGrid所必需的。

DataGridTemplateColumn

答案 2 :(得分:1)

通过ViewModel上的Groups属性可以更好地实现这一目标;因为这最终是Label正在使用的。

<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>

答案 3 :(得分:0)

你不能这样做。绑定/名称解析不起作用。为什么不,而不是StringToVisibilityConverter创建一个CollectionToVisibilityConverter来检查数据源(可能传入列/属性进行检查),查看该列/属性是否完全为空,然后转换那是一个可见性?

答案 4 :(得分:0)

感谢 SliverNinja 和本文DataGridContextHelper。链接到源代码已经无法正常工作且无法下载,因此我编写了自己的附加Proeprty,使其适用于所有可能的情况(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 RelativeSource Self

非常重要

只有我不喜欢当前的实现 - 处理DataGrid.Columns.CollectionChanged事件我创建了我的类的实例,并且不保留它的引用。因此理论上GC可能会在一定时间内将其杀死,目前无法确定如何正确处理它,会考虑并稍后更新我的帖子。任何想法和批评都是受欢迎的。