6

我在 WPF 中有一个网格,自动生成列。如何使用数据注释动态隐藏列?

我想在我的模型中有一个属性来指定列是否可见,但我不知道该怎么做。

我的模型,绑定到网格:

public class Template
{
        public string County { get; set; }

        public string Operator { get; set; }

        public string Field { get; set; }
}
4

4 回答 4

6

这是一个使用属性隐藏列的示例。它使用附加属性来处理AutoGeneratingColumn事件。

HideColumnIfAutoGenerated.cs - 属性

namespace AutoHideColumn
{
    public class HideColumnIfAutoGenerated : System.Attribute
    {
        public HideColumnIfAutoGenerated()
        {
        }
    }
}

DataGridExtension.cs - 附加属性

using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;

namespace AutoHideColumn
{
    public static class DataGridExtension
    {
        public static readonly DependencyProperty HideAnnotatedColumnsProperty = DependencyProperty.RegisterAttached(
           "HideAnnotatedColumns",
           typeof(bool),
           typeof(DataGridExtension),
           new UIPropertyMetadata(false, OnHideAnnotatedColumns));

        public static bool GetHideAnnotatedColumns(DependencyObject d)
        {
            return (bool)d.GetValue(HideAnnotatedColumnsProperty);
        }

        public static void SetHideAnnotatedColumns(DependencyObject d, bool value)
        {
            d.SetValue(HideAnnotatedColumnsProperty, value);
        }

        private static void OnHideAnnotatedColumns(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            bool hideAnnotatedColumns = (bool)e.NewValue;

            DataGrid dataGrid = d as DataGrid;

            if (hideAnnotatedColumns)
            {
                dataGrid.AutoGeneratingColumn += dataGrid_AutoGeneratingColumn;
            }
            else
            {
                dataGrid.AutoGeneratingColumn -= dataGrid_AutoGeneratingColumn;
            }
        }

        private static void dataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
        {
            PropertyDescriptor propertyDescriptor = e.PropertyDescriptor as PropertyDescriptor;
            if (propertyDescriptor != null)
            {
                foreach (var item in propertyDescriptor.Attributes)
                {
                    if (item.GetType() == typeof(HideColumnIfAutoGenerated))
                    {
                        e.Cancel = true;
                    }
                }
            }
        }
    }
}

XAML

<Window x:Class="AutoHideColumn.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:AutoHideColumn"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
            <DataGrid Name="dg" local:DataGridExtension.HideAnnotatedColumns="True">

        </DataGrid>
        <DataGrid Grid.Row="1" Name="dg1">

        </DataGrid>
    </Grid>
</Window>

代码隐藏

using System.Collections.Generic;
using System.Windows;

namespace AutoHideColumn
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            this.dg.ItemsSource = new List<Customer>();
            this.dg1.ItemsSource = new List<Customer>();
        }
    }

    public class Customer
    {
        [HideColumnIfAutoGenerated()]
        public int ID { get; set; }

        public string Name { get; set; }
    }
}
于 2013-08-07T17:39:23.257 回答
2

尝试这个

public partial class MainWindow : Window
{
    private List<string> visibleColumns;
    public MainWindow()
    {
        InitializeComponent();
        InitializeList();
        visibleColumns = GetVisibleColumns();
        dg.AutoGeneratingColumn += dg_AutoGeneratingColumn;
        dg.ItemsSource = Templates;
    }

    void dg_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
    {
        if(!visibleColumns.Contains(e.Column.Header.ToString()))
            e.Column.Visibility=Visibility.Collapsed;

    }

    List<string> GetVisibleColumns()
    {
        return typeof(Template).GetProperties()
              .Where(p =>
               p.GetCustomAttributes(typeof(Visible), true)
               .Where(ca => ((Visible)ca).IsVisible).Any()
      ).Select(s => s.Name).ToList();
    }

    private void InitializeList()
    {
        Templates = new List<Template>();
        Templates.Add(new Template { County = "abc", Operator = "123", Field = "xyz" });
        Templates.Add(new Template { County = "abc", Operator = "123", Field = "xyz" });
        Templates.Add(new Template { County = "abc", Operator = "123", Field = "xyz" });
        Templates.Add(new Template { County = "abc", Operator = "123", Field = "xyz" });
    }

    public List<Template> Templates { get; set; }


}

>模板类

public class Template
{
    [Visible(false)]
    public string County { get; set; }

    [Visible(true)]
    public string Operator { get; set; }

    [Visible(true)]
    public string Field { get; set; }
}

>可见属性

public class Visible : Attribute
{
    public Visible(bool isVisible)
    {
        IsVisible = isVisible;
    }
    public bool IsVisible { get; set; }
}

>xml

<Grid>
    <DataGrid AutoGenerateColumns="True" x:Name="dg"/>
</Grid>
于 2013-08-07T17:35:53.823 回答
2

这将是迄今为止最接近数据注释的最简单的解决方法:省略 getter 和 setter。

public class Template
{
    public string County { get; set; }

    public string Operator { get; set; }

    public string Field; //This is now a field and not a property-> invisible in datadrid
}
于 2016-01-21T18:04:34.287 回答
0

属性不能在运行时更改,因此您不能使用数据注释动态隐藏列。但是可以动态隐藏列。这是一个演示它的示例。

XAML

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <DataGrid ItemsSource="{Binding AutoGenerateColumnDetails}" CanUserAddRows="False" CanUserDeleteRows="False">

    </DataGrid>
    <Button Grid.Row="1" Content="Refresh" Click="Button_Click" HorizontalAlignment="Left" Margin="5"/>
    <DataGrid Name="dg" Grid.Row="2" ItemsSource="{Binding TemplateList}" AutoGeneratingColumn="dg_AutoGeneratingColumn">

    </DataGrid>
</Grid>

背后的代码

using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;

namespace AutoHideDGColumn
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private ViewModel _ViewModel = null;

        public MainWindow()
        {
            InitializeComponent();
            _ViewModel = new ViewModel();
            this.DataContext = _ViewModel;
        }

        private void dg_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
        {
            if (_ViewModel.AutoGenerateColumnDetails.Where(d => d.HideColumn == true).Select(d => d.PropertyName).ToList().Contains(e.PropertyName))
                e.Cancel = true;
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            // Reset to trigger AutoGeneratingColumn event
            this.dg.AutoGenerateColumns = false;
            this.dg.AutoGenerateColumns = true;
        }
    }

    public class ViewModel
    {
        private List<Template> _TemplateList;

        public List<Template> TemplateList
        {
            get { return _TemplateList; }
            set { _TemplateList = value; }
        }

        private List<AutoGenerateColumnDetail> _AutoGenerateColumnDetails;

        public List<AutoGenerateColumnDetail> AutoGenerateColumnDetails
        {
            get { return _AutoGenerateColumnDetails; }
            set { _AutoGenerateColumnDetails = value; }
        }

        public ViewModel()
        {
            AutoGenerateColumnDetails = typeof(Template).GetProperties().Select(p => new AutoGenerateColumnDetail() { PropertyName = p.Name }).ToList();

            TemplateList = new List<Template>() 
            {
                new Template() { County = "Count1", Field = "Field1", Operator = "Operator1"},
                new Template() { County = "Count2", Field = "Field2", Operator = "Operator2"},
                new Template() { County = "Count3", Field = "Field2", Operator = "Operator3"},
            };
        }
    }

    public class Template
    {
        public string County { get; set; }
        public string Operator { get; set; }
        public string Field { get; set; }
    }

    public class AutoGenerateColumnDetail
    {
        public string PropertyName { get; set; }
        public bool HideColumn { get; set; }
    }
}
于 2013-08-08T16:33:42.397 回答