Recently I’ve been working with reflection and I’m beginning to realize how powerful this can be for my controls. In my previous posts I was using a ListView as a Grid to create columns, this is very easy but every time you make a change in the source type you will have to change the xaml for the ListView. I’ve been doing this a lot of times and then I did this question to myself: “what If I can generate the columns dynamically at runtime?”, and bingo!! no more repetitive code.
With this control I just need to set the datacontext to a collection and the control takes care of generate the columns according to the public properties of the data object (using reflection).
First I’ll show you the code for the control, in my solution this is allocated in a Project called MyControls so to use it in you main project you must add a reference to this project.
<UserControl x:Class=”MyControls.AutoGridListView”
xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”
xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”
Height=”auto” Width=”auto”>
<Grid x:Name=”grid”>
<ItemsControl x:Name=”ic” ItemsSource=”{Binding}” Visibility=”Hidden”>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Loaded=”Grid_Loaded”/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</UserControl>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Reflection;
using System.Collections.Specialized;
namespace MyControls
{
/// <summary>
/// Interaction logic for AutoGridListView.xaml
/// </summary>
public partial class AutoGridListView : UserControl
{
Type dataType;
public AutoGridListView()
{
InitializeComponent();
}
private void Grid_Loaded(object sender, RoutedEventArgs e)
{
if (dataType == null)
{
dataType = (sender as Grid).DataContext.GetType();
SetListView();
}
}
private void SetListView()
{
ListView lv = new ListView();
Binding binding = new Binding();
binding.Source = this.DataContext;
lv.SetBinding(ListView.ItemsSourceProperty, binding);
GridView gv = new GridView();
foreach (string colName in GetProperties())
{
GridViewColumn col = new GridViewColumn();
col.Header = colName;
col.DisplayMemberBinding = new Binding(colName);
gv.Columns.Add(col);
}
lv.View = gv;
grid.Children.Add(lv);
}
private StringCollection GetProperties()
{
StringCollection properties = new StringCollection();
foreach (PropertyInfo property in dataType.GetProperties())
properties.Add(property.Name);
return properties;
}
}
}
And this is the code for my window:
<Window x:Class=”AutoListView.Window1″
xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”
xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”
xmlns:ctrl=”clr-namespace:MyControls;assembly=MyControls”
Title=”AutoGridListView Test” Height=”300″ Width=”300″>
<Grid>
<ctrl:AutoGridListView/>
</Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Collections.ObjectModel;
namespace AutoListView
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
ObservableCollection<Guest> sourceList = new ObservableCollection<Guest>();
Random gen = new Random();
public Window1()
{
InitializeComponent();
//We set the DataContext for the window, therefore, for our grid control.
this.DataContext = sourceList;
sourceList.Add(new Guest() { Name = “Fernando Romero”, Age = 23, RandomNumber = gen.Next() });
sourceList.Add(new Guest() { Name = “Luis Del Vasto”, Age = 22, RandomNumber = gen.Next() });
sourceList.Add(new Guest() { Name = “Nestor Martinez”, Age = 26, RandomNumber = gen.Next() });
sourceList.Add(new Guest() { Name = “Zeythel Soto”, Age = 30, RandomNumber = gen.Next() });
sourceList.Add(new Guest() { Name = “Chuck Norris”, Age = Int32.MaxValue, RandomNumber = gen.Next() });
}
}
public class Guest
{
public string Name { get; set; }
public int Age { get; set; }
public int RandomNumber { get; set; }
}
}
And that’s all.
Please, if this is useful somehow leave a comment. Good luck!

Jean-Francois Peyroux said,
May 17, 2008 at 5:29 am
I have been looking for days for an auto resizeable ListView. Please, change the keywords so that it is easier to find this page with the search engines.
fernandojhoel said,
May 17, 2008 at 1:53 pm
It’s done Jean. Thanks!
Jean-Francois Peyroux said,
May 17, 2008 at 2:51 pm
What I really need is auto width for column. With a sligh change to the example above, I got what I needed:
XAML:
Code Behind:
// New Property
public GridView View { get { return null; } set { _gridView = value; } }
// Replaced the foreach using reflection on the type with a foreach on the prededfined columns
foreach (GridViewColumn source in _gridView.Columns)
{
GridViewColumn col = new GridViewColumn ();
col.Header = source.Header;
col.DisplayMemberBinding = source.DisplayMemberBinding;
gv.Columns.Add (col);
}
Ian Randall said,
August 9, 2008 at 10:15 am
Thanks so much!
WPF does not yet contain a DataGridView control, although we are led to believe that one is coming, and I do not have any inclination to buy a 3rd party one; this post explains neatly and simply how to set about building one myself.
So simple, when you know how
Thanks again,
Bob said,
August 19, 2008 at 9:21 pm
Nice simple control. Would be better if you add a simple way to sort the columns as well.. I think I will try my hand at that
still learning WPF though.