.NET Framework Developer Center >
.NET Development Forums
>
Windows Presentation Foundation (WPF)
>
How to make a ListView/GridView showing more than one kind of data
How to make a ListView/GridView showing more than one kind of data
- Hi All,
I have a requirement to show (and edit) a list of data, but the data may be of more than one type. For example, one piece of data might just be a string, another might be a checkbox, and a third might be a combo box. I want to edit this data in a list, eg (hope you get the idea):
Data1: A String
Data2: [x]
Data3 Pick One \/
As you can see, each data item needs to line up, but each have a different data template, based on the type of the data. What is the best way to go about this?
Cheers
-N
Answers
- Hi GrantaGuy,
If you are using a ListView, you can retemplate its cells (using GridView - GridView.Column) using a datatemplate (GridViewColumn.CellTemplate) and basically defining your visual tree of your object as you wish (for bool types - a checkbox, DateTime types - a DatePicker and for other a TextBox). The recomended approach would be to set the DataTemplate in XAML, still...you can achieve this by adding C# code also. Here's a simple custom ListView that has "AutoGenerateColumns" property so 'twill automatically generate its columns and editable cells based on the underlying data properties and types.public class SGrid : ListView { public bool AutoGenerateColumns { get { return (bool)GetValue(AutoGenerateColumnsProperty); } set { SetValue(AutoGenerateColumnsProperty, value); } } // Using a DependencyProperty as the backing store for AutoGenerateColumns. This enables animation, styling, binding, etc... public static readonly DependencyProperty AutoGenerateColumnsProperty = DependencyProperty.Register("AutoGenerateColumns", typeof(bool), typeof(SGrid), new PropertyMetadata(false)); protected override void OnItemsSourceChanged(System.Collections.IEnumerable oldValue, System.Collections.IEnumerable newValue) { base.OnItemsSourceChanged(oldValue, newValue); if (AutoGenerateColumns) { GridView gridView = new GridView(); Type sourceItemType = ItemsSource.AsQueryable().ElementType; PropertyInfo[] properties = sourceItemType.GetProperties(); foreach (var prop in properties) { GridViewColumn column = new GridViewColumn { Header = prop.Name }; DataTemplate template = new DataTemplate(); if (prop.PropertyType == typeof(string)) { FrameworkElementFactory childFactory = new FrameworkElementFactory(typeof(TextBox)); childFactory.SetBinding(TextBox.TextProperty, new Binding(prop.Name)); childFactory.SetValue(TextBox.WidthProperty, 100.0); template.VisualTree = childFactory; } else if (prop.PropertyType == typeof(DateTime)) { FrameworkElementFactory childFactory = new FrameworkElementFactory(typeof(DatePicker)); childFactory.SetBinding(DatePicker.SelectedDateProperty, new Binding(prop.Name)); template.VisualTree = childFactory; } else if (prop.PropertyType == typeof(bool)) { FrameworkElementFactory childFactory = new FrameworkElementFactory(typeof(CheckBox)); childFactory.SetBinding(CheckBox.IsCheckedProperty, new Binding(prop.Name)); template.VisualTree = childFactory; } column.CellTemplate = template; gridView.Columns.Add(column); } View = gridView; } } }
- Marked As Answer byGrantaGuy Monday, November 09, 2009 2:18 PM
All Replies
- Hi GrantaGuy,
If you are using a ListView, you can retemplate its cells (using GridView - GridView.Column) using a datatemplate (GridViewColumn.CellTemplate) and basically defining your visual tree of your object as you wish (for bool types - a checkbox, DateTime types - a DatePicker and for other a TextBox). The recomended approach would be to set the DataTemplate in XAML, still...you can achieve this by adding C# code also. Here's a simple custom ListView that has "AutoGenerateColumns" property so 'twill automatically generate its columns and editable cells based on the underlying data properties and types.public class SGrid : ListView { public bool AutoGenerateColumns { get { return (bool)GetValue(AutoGenerateColumnsProperty); } set { SetValue(AutoGenerateColumnsProperty, value); } } // Using a DependencyProperty as the backing store for AutoGenerateColumns. This enables animation, styling, binding, etc... public static readonly DependencyProperty AutoGenerateColumnsProperty = DependencyProperty.Register("AutoGenerateColumns", typeof(bool), typeof(SGrid), new PropertyMetadata(false)); protected override void OnItemsSourceChanged(System.Collections.IEnumerable oldValue, System.Collections.IEnumerable newValue) { base.OnItemsSourceChanged(oldValue, newValue); if (AutoGenerateColumns) { GridView gridView = new GridView(); Type sourceItemType = ItemsSource.AsQueryable().ElementType; PropertyInfo[] properties = sourceItemType.GetProperties(); foreach (var prop in properties) { GridViewColumn column = new GridViewColumn { Header = prop.Name }; DataTemplate template = new DataTemplate(); if (prop.PropertyType == typeof(string)) { FrameworkElementFactory childFactory = new FrameworkElementFactory(typeof(TextBox)); childFactory.SetBinding(TextBox.TextProperty, new Binding(prop.Name)); childFactory.SetValue(TextBox.WidthProperty, 100.0); template.VisualTree = childFactory; } else if (prop.PropertyType == typeof(DateTime)) { FrameworkElementFactory childFactory = new FrameworkElementFactory(typeof(DatePicker)); childFactory.SetBinding(DatePicker.SelectedDateProperty, new Binding(prop.Name)); template.VisualTree = childFactory; } else if (prop.PropertyType == typeof(bool)) { FrameworkElementFactory childFactory = new FrameworkElementFactory(typeof(CheckBox)); childFactory.SetBinding(CheckBox.IsCheckedProperty, new Binding(prop.Name)); template.VisualTree = childFactory; } column.CellTemplate = template; gridView.Columns.Add(column); } View = gridView; } } }
- Marked As Answer byGrantaGuy Monday, November 09, 2009 2:18 PM


