.NET Framework Developer Center > .NET Development Forums > Windows Presentation Foundation (WPF) > How to make a ListView/GridView showing more than one kind of data
Ask a questionAsk a question
 

AnswerHow to make a ListView/GridView showing more than one kind of data

  • Friday, November 06, 2009 6:20 PMGrantaGuy Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    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

  • Saturday, November 07, 2009 9:19 AMOlaf Rabbachin Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer
    Hi there,

    you already mention DataTemplates, so I assume that you have also stumbled over DataTemplateSelectors. Have you seen the tutorials (i.e. this one or this one )?

    Cheers,
    Olaf
    • Marked As Answer byGrantaGuy Monday, November 09, 2009 2:18 PM
    •  
  • Saturday, November 07, 2009 4:34 PMStephanne Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     AnswerHas Code
    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

  • Saturday, November 07, 2009 9:19 AMOlaf Rabbachin Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer
    Hi there,

    you already mention DataTemplates, so I assume that you have also stumbled over DataTemplateSelectors. Have you seen the tutorials (i.e. this one or this one )?

    Cheers,
    Olaf
    • Marked As Answer byGrantaGuy Monday, November 09, 2009 2:18 PM
    •  
  • Saturday, November 07, 2009 4:34 PMStephanne Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     AnswerHas Code
    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
    •