如何绑定 DataGridColumn.Visibility? [英] How to bind DataGridColumn.Visibility?

查看:16
本文介绍了如何绑定 DataGridColumn.Visibility?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个类似于以下帖子的问题:

I have an issue similar to the following post:

Silverlight DataGridTextColumn 绑定可见性

我需要根据 ViewModel 中的值显示/折叠 Silverlight DataGrid 中的一个列.为此,我尝试将 Visibility 属性绑定到 ViewModel.但是我很快发现 Visibility 属性不是 DependencyProperty,因此无法绑定.

I need to have a Column within a Silverlight DataGrid be visibile/collapsed based on a value within a ViewModel. To accomplish this I am attempting to Bind the Visibility property to a ViewModel. However I soon discovered that the Visibility property is not a DependencyProperty, therefore it cannot be bound.

为了解决这个问题,我尝试对我自己的 DataGridTextColumn 进行子类化.使用这个新类,我创建了一个 DependencyProperty,它最终将更改推送到 DataGridTextColumn.Visibility 属性.如果我不进行数据绑定,这很有效.当我将数据绑定到我的新属性时,它失败了,并出现 AG_E_PARSER_BAD_PROPERTY_VALUE 异常.

To solve this, I attempted to subclass my own DataGridTextColumn. With this new class, I have created a DependencyProperty, which ultimately pushes the changes to the DataGridTextColumn.Visibility property. This works well, if I don't databind. The moment I databind to my new property, it fails, with a AG_E_PARSER_BAD_PROPERTY_VALUE exception.

public class MyDataGridTextColumn : DataGridTextColumn
{
    #region public Visibility MyVisibility

    public static readonly DependencyProperty MyVisibilityProperty =
        DependencyProperty.Register("MyVisibility", typeof(Visibility), typeof(MyDataGridTextColumn), new PropertyMetadata(Visibility.Visible, OnMyVisibilityPropertyChanged));

    private static void OnMyVisibilityPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var @this = d as MyDataGridTextColumn;

        if (@this != null)
        {
            @this.OnMyVisibilityChanged((Visibility)e.OldValue, (Visibility)e.NewValue);
        }
    }

    private void OnMyVisibilityChanged(Visibility oldValue, Visibility newValue)
    {
        Visibility = newValue;
    }

    public Visibility MyVisibility
    {
        get { return (Visibility)GetValue(MyVisibilityProperty); }
        set { SetValue(MyVisibilityProperty, value); }
    }

    #endregion public Visibility MyVisibility
}

这是 XAML 的一小段.

Here is a small snippet of the XAML.

<DataGrid ....>
    <DataGrid.Columns>
        <MyDataGridTextColumn Header="User Name"
                              Foreground="#FFFFFFFF"
                              Binding="{Binding User.UserName}"
                              MinWidth="150"
                              CanUserSort="True"
                              CanUserResize="False"
                              CanUserReorder="True"
                              MyVisibility="{Binding Converter={StaticResource BoolToVisibilityConverter}, Path=ShouldShowUser}"/>
        <DataGridTextColumn .../>
    </DataGrid.Columns>
</DataGrid>

几个重要的事实.

  • 转换器确实是在上面的本地资源中定义的.
  • 转换器是正确的,它在解决方案中的许多其他地方都使用过.
  • 如果我将 MyVisibility 属性的 {Binding} 语法替换为Collapsed",列实际上会消失.
  • 如果我创建一个新的 DependencyProperty(即字符串 Foo)并绑定到它,我也会收到 AG_E_PARSER_BAD_PROPERTY_VALUE 异常.

有人知道为什么这不起作用吗?

Does anybody have any ideas as to why this isn't working?

推荐答案

这是我使用小技巧想出的解决方案.

Here's the solution I've come up with using a little hack.

首先,您需要从 DataGrid 继承.

First, you need to inherit from DataGrid.

public class DataGridEx : DataGrid
{
    public IEnumerable<string> HiddenColumns
    {
        get { return (IEnumerable<string>)GetValue(HiddenColumnsProperty); }
        set { SetValue(HiddenColumnsProperty, value); }
    }

    public static readonly DependencyProperty HiddenColumnsProperty =
        DependencyProperty.Register ("HiddenColumns", 
                                     typeof (IEnumerable<string>), 
                                     typeof (DataGridEx),
                                     new PropertyMetadata (HiddenColumnsChanged));

    private static void HiddenColumnsChanged(object sender,
                                             DependencyPropertyChangedEventArgs args)
    {
        var dg = sender as DataGrid;
        if (dg==null || args.NewValue == args.OldValue)
            return;

        var hiddenColumns = (IEnumerable<string>)args.NewValue;
        foreach (var column in dg.Columns)
        {
            if (hiddenColumns.Contains ((string)column.GetValue (NameProperty)))
                column.Visibility = Visibility.Collapsed;
            else
                column.Visibility = Visibility.Visible;
        }
    }
}

DataGridEx 类添加了一个新的 DP,用于根据 DataGridColumn 及其后代的 x:Name 隐藏列.

The DataGridEx class adds a new DP for hiding columns based on the x:Name of a DataGridColumn and its descendants.

在您的 XAML 中使用:

To use in your XAML:

<my:DataGridEx x:Name="uiData"
               DataContext="{Binding SomeDataContextFromTheVM}"
               ItemsSource="{Binding Whatever}"
               HiddenColumns="{Binding HiddenColumns}">
    <sdk:DataGridTextColumn x:Name="uiDataCountOfItems">
                            Header="Count"
                            Binding={Binding CountOfItems}"
    </sdk:DataGridTextColumn>
</my:DataGridEx>

您需要将这些添加到您的 ViewModel 或您使用的任何数据上下文中.

You need to add these to your ViewModel or whatever data context you use.

private IEnumerable<string> _hiddenColumns;
public IEnumerable<string> HiddenColumns
{
    get { return _hiddenColumns; }
    private set
    {
        if (value == _hiddenColumns)
            return;

        _hiddenColumns = value;
        PropertyChanged (this, new PropertyChangedEventArgs("HiddenColumns"));
    }
}

public void SomeWhereInYourCode ()
{
    HiddenColumns = new List<string> {"uiDataCountOfItems"};
}

要取消隐藏,您只需从列表中删除相应的名称或重新创建它而不使用未隐藏的名称.

To unhide, you only need to remove the corresponding name from the list or recreate it without the unhidden name.

这篇关于如何绑定 DataGridColumn.Visibility?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆