Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hide a Column Using Data Annotations in WPF

I have a grid in WPF, auto-generating columns. How can I dynamically hide columns using data annotations?

I thought of having a property in my model to specify whether the column is visible, but I'm not sure how to do it.

My model, bound to the grid:

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

        public string Operator { get; set; }

        public string Field { get; set; }
}
like image 526
joek1975 Avatar asked Aug 07 '13 16:08

joek1975


3 Answers

Here is a sample which uses attributes to hide columns. It uses an attached property to handle the AutoGeneratingColumn event.

HideColumnIfAutoGenerated.cs - Attribute

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

DataGridExtension.cs - Attached Property

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>

CodeBehind

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; }
    }
}
like image 159
Anand Murali Avatar answered Sep 17 '22 23:09

Anand Murali


Try this

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


}

>Template Class

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

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

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

>Visible Attribute

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

>xaml

<Grid>
    <DataGrid AutoGenerateColumns="True" x:Name="dg"/>
</Grid>
like image 28
yo chauhan Avatar answered Sep 21 '22 23:09

yo chauhan


this would be by far the most simplistic workaround which comes close to data annotation: omit the getter and 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
}
like image 32
Falco Alexander Avatar answered Sep 21 '22 23:09

Falco Alexander