WPF

How to Hide WPF ListView Columns in MVVM?

ListView control is a very popular control among WPF developers. Developers use ListView control for showing the data in tabular format. Sometimes, we need to hide WPF ListView columns, but wpf does not provide any default implementation for hide WPF ListView columns.

I have developed a WPF Behavior to hide WPF ListView columns through Attach property. An attached property named HideColumns is attached to the ListView gives us the column numbers needs to be hide.

Hide WPF ListView Columns solution steps:

  1. Cache/Stores all the ListView columns into the Tag property of the ListView.
  2. Clears all the columns from the ListView.
  3. Add all the columns into the ListView which get back ListView into their original view.
  4. Make a list of delete columns and stores them into a list.
  5. Delete columns from the ListView

Step 2 and 3 makes the ListView into their original view. These steps are necessary when we need to get back our hidden columns.

Below is the code for the ListViewBehavior

public static class ListViewBehavior
    {
        public static readonly DependencyProperty HideColumnsProperty = DependencyProperty.RegisterAttached("HideColumns", typeof(string), typeof(ListViewBehavior), new FrameworkPropertyMetadata(HideColumnsChangedCallback));

        public static string GetHideColumns(UIElement element)
        {
            return (string)element.GetValue(HideColumnsProperty);
        }

        public static void SetHideColumns(UIElement element, string value)
        {
            element.SetValue(HideColumnsProperty, value);
        }

        private static void HideColumnsChangedCallback(DependencyObject sender, DependencyPropertyChangedEventArgs args)
        {
            //create backup of the listview columns and save it into Tag property of ListView
            List<GridViewColumn> columnsCache = null;
            ListView lv = (ListView)sender;
            GridView gv = ((GridView)lv.View);
            if (lv.Tag == null)
            {
                columnsCache = new List<GridViewColumn>();
                foreach (GridViewColumn col in gv.Columns)
                {
                    columnsCache.Add(col);
                }
                lv.Tag = columnsCache;
            }
            else
            {
                columnsCache = ((List<GridViewColumn>)lv.Tag);
            }

            //clear all the columns and put ListView into their deafult columns.
            gv.Columns.Clear();
            foreach (GridViewColumn cl in columnsCache)
            {
                gv.Columns.Add(cl);
            }

            //make a list of delete columns
            string newColumnsToHide = (string)args.NewValue;
            List<GridViewColumn> columntoDeleteList = new List<GridViewColumn>();
            foreach (string s in newColumnsToHide.Split(','))
            {
                int columnToHide;
                if (int.TryParse(s, out columnToHide))
                {
                    columntoDeleteList.Add(gv.Columns[columnToHide]);
                }
            }

            //delete the columns
            columntoDeleteList.ForEach(w => gv.Columns.Remove(w));
        }
    }

For adding the behavior to the ListView, add below line of code to ListView.


local:ListViewBehavior.HideColumns="{Binding ColumnNumbers}"

ColumnsNumbers is a comma separated list of columns numbers that needs to be hide. You can also fixed this columns numbers like “0,2”.

Below I have shown full example of behavior.

Main Window XAML File

<Window x:Class="WpfApplication3.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication3"
        Title="MainWindow" Height="350" Width="525" WindowState="Maximized">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <ListView ItemsSource="{Binding Employees}" local:ListViewBehavior.HideColumns="{Binding ColumnNumbers}">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="Select">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <CheckBox IsChecked="{Binding IsSelected}" />
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                    <GridViewColumn Header="ID">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding ID}" />
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                    <GridViewColumn Header="Name">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding Name}" />
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                    <GridViewColumn Header="Age">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding Age}" />
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                    <GridViewColumn Header="Join Date">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding JoinDate, StringFormat=d}" />
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                    <GridViewColumn Header="Salary">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding Salary, StringFormat=c}" />
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                </GridView>
            </ListView.View>
        </ListView>

        <StackPanel Orientation="Horizontal" Grid.Row="1" Margin="0,10,0,10">
            <TextBlock Text="Enter Columns to Hide: " />
            <TextBox Text="{Binding ColumnNumbers}" Width="80" Margin="5,0,10,0" />
        </StackPanel>

    </Grid>
</Window>

In the above xaml file, I have bind TextBox Text property to a ColumnNumbers property that is also bind to HideColumns attached property of ListViewBehavior class.

Main Window code behind file

public partial class MainWindow : Window, INotifyPropertyChanged
    {
        private List<Employee> employees;
        private string columnNumbers;

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

        public List<Employee> Employees
        {
            get
            {
                if (employees == null)
                {
                    employees = Employee.GetEmployees();
                }
                return employees;
            }
        }

        public string ColumnNumbers
        {
            get
            {
                return columnNumbers;
            }
            set
            {
                columnNumbers = value;
                this.RaisePropertyChanged("ColumnNumbers");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        public void RaisePropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

Below is the screenshot for the Main Window.

WPF-Hide-ListView-Columns-through-Attach-Property-Image-1

Now, when I enter columns 0,3 into the textbox, it remove columns Select, Age from the ListBox.

WPF-Hide-ListView-Columns-through-Attach-Property-Image-2

Then, I cleared the textbox and enter 1, now ListView Behavior removes only the ID column and again show Select, and Age columns which we have removed in previous screenshot.

WPF-Hide-ListView-Columns-through-Attach-Property-Image-3