【问题标题】:Hiding DataGrid Column based on Column values根据列值隐藏 DataGrid 列
【发布时间】:2016-11-16 03:26:16
【问题描述】:

我有一个带有 DataGrid 的窗口,我想根据作为 DataGrid 的 ItemSource 的 ObservableCollection 的内容隐藏某些列。

基于这个问题: Conditional element in xaml depending on the binding content

我写了一个 VisibilityConverter:

 public class StringLengthVisiblityConverter : IValueConverter
{
    public StringLengthVisiblityConverter() { }
    public Object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value == null || value.ToString().Length == 0)
        {
            return Visibility.Collapsed;
        }
        else
        {
            return Visibility.Visible;
        }
    }

    public Object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

这是 XAML:

        <DataGrid.Resources>
            <local:StringLengthVisiblityConverter x:Key="VisConverter"/>
        </DataGrid.Resources>
        <DataGrid.Columns>

            <DataGridTextColumn  Header="Switch Port" Binding="{Binding FCPort}"/>
            <DataGridTextColumn Width="*" Header="WWPN" Binding="{Binding Path=WWPN}" 
                         Visibility="{Binding Path=WWPN, Converter={StaticResource VisConverter}}"/>
            <DataGridTextColumn Header="FCID" Binding="{Binding Path=FCID}"
            Visibility="{Binding Path=FCID, Converter={StaticResource VisConverter}}"/>

        </DataGrid.Columns>
    </DataGrid>

我用 WWPN 和 FCID 都为空的类的实例加载了集合。我希望这些列隐藏在数据网格中,但它们仍然可见。我在 VisbilityConverter 中添加了一个断点并通过调试器运行它,但它看起来不像被调用。

【问题讨论】:

  • 如果所有项目都是空字符串或空值,您想隐藏整个列吗?然后你可以绑定到项目(让路径为空)并创建一个 MultiValueConverter 迭代你的项目。
  • 这是因为DataGridColumn直接派生自DependencyObject而不是FrameworkElementFrameworkContentElement,因此数据上下文没有被继承。查看输出窗口,您应该可以在那里找到System.Windows.Data: Error: 2 消息。
  • Here's a good article 为您的确切问题提供解释和解决方法。
  • @Grx70 - 谢谢。这回答了这个问题。

标签: c# wpf xaml


【解决方案1】:

您需要检查DataGridTextColumn 中的每个值并相应地设置Column.Visibility。 包装我从 DataGrid 派生的所有逻辑。

public class MyDataGrid : DataGrid
{
    private void ValidateColumnVisibility()
    {
        if (Items.Count == 0 || Items[0] == CollectionView.NewItemPlaceholder) return;
        var itemClass = Items[0].GetType();
        foreach (var column in Columns)
        {
            if (column.GetType() == typeof(DataGridTextColumn))
            {
                // find the property that this column is bound to
                DataGridBoundColumn boundColumn = column as DataGridBoundColumn;
                Binding binding = boundColumn.Binding as Binding;
                string boundPropertyName = binding.Path.Path;
                var prop = itemClass.GetProperty(boundPropertyName);

                // Validating Column.Visibility when first value is null
                // when all values are null -> Visibility.Collapsed
                // bound value not a string -> Visibility.Visible
                // all bound strings empty  -> Visibility.Collapsed
                if (prop.GetValue(Items[0]) == null)
                {
                    column.Visibility = Visibility.Collapsed;
                    foreach (var item in Items)
                    {
                        if (item != CollectionView.NewItemPlaceholder)
                        {
                            if (prop.GetValue(item) != null)
                            {
                                if (prop.GetValue(item).GetType() != typeof(String))
                                    column.Visibility = Visibility.Visible;
                                else if (String.IsNullOrEmpty(prop.GetValue(item) as String) == false)
                                    column.Visibility = Visibility.Visible;
                            }
                        }
                    }
                }

                // First value not null and all bound strings empty -> Visibility.Collapsed
                else if (prop.GetValue(Items[0]).GetType() == typeof(String))
                {
                    column.Visibility = Visibility.Collapsed;
                    foreach (var item in Items)
                    {
                        if (item != CollectionView.NewItemPlaceholder)
                        {
                            if (String.IsNullOrEmpty(prop.GetValue(item) as String) == false)
                                column.Visibility = Visibility.Visible;
                        }
                    }
                }
            }
        }
    }

    protected override void OnItemsSourceChanged(
        IEnumerable oldValue, IEnumerable newValue)
    {
        base.OnItemsSourceChanged(oldValue, newValue);
        ValidateColumnVisibility();
    }

    protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)
    {
        base.OnItemsChanged(e);
        ValidateColumnVisibility();
    }
}

使用 MyDataGrid,您不再需要在 XAML 中设置 Column.Visibility,因为它会自动发生。

【讨论】:

  • 这很干净,我想我会这样做。它也会清理 XAML。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多