根据列值隐藏DataGrid列

时间:2016-11-16 03:26:17

标签: c# wpf xaml

我有一个带有DataGrid的窗口,我希望根据ObservableCollection的内容隐藏某些列,这些内容是DataGrid的ItemSource。

基于这个问题: 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都为null。我希望这些列隐藏在数据网格中,但它们仍然可见。我在VisbilityConverter中添加了一个断点并通过调试器运行它,但它看起来不像是被调用了。

1 个答案:

答案 0 :(得分: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,因为它会自动发生。