DataGrid: dynamic DataTemplate for dynamic DataGridTemplateColumn

Lukas Cenovsky picture Lukas Cenovsky · Jan 10, 2011 · Viewed 7.7k times · Source

I want to show data in a datagrid where the data is a collection of

public class Thing
{
    public string Foo { get; set; }
    public string Bar { get; set; }
    public List<Candidate> Candidates { get; set; }
}

public class Candidate
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    ...
}

where the number of candidates in Candidates list varies at runtime.

Desired grid layout looks like this

Foo | Bar | Candidate 1 | Candidate 2 | ... | Candidate N

I'd like to have a DataTemplate for each Candidate as I plan changing it during runtime - user can choose what info about candidate is displayed in different columns (candidate is just an example, I have different object). That means I also want to change the column templates in runtime although this can be achieved by one big template and collapsing its parts.

I know about two ways how to achieve my goals (both quite similar):

  1. Use AutoGeneratingColumn event and create Candidates columns
  2. Add Columns manually

In both cases I need to load the DataTemplate from string with XamlReader. Before that I have to edit the string to change the binding to wanted Candidate.

Is there a better way how to create a DataGrid with unknown number of DataGridTemplateColumn?

Note: This question is based on dynamic datatemplate with valueconverter

Edit: As I need to support both WPF and Silverlight, I've created my own DataGrid component which has DependencyProperty for bindig a collection of columns. When the collection changes, I update the columns.

Answer

Marco B. picture Marco B. · Jan 11, 2011

For example we create 2 DataTemplates and a ContentControl:

<DataTemplate DataType="{x:Type viewModel:VariantA}"> <dataGrid...> </DataTemplate>
<DataTemplate DataType="{x:Type viewModel:VariantB}"> <dataGrid...> </DataTemplate>

<ContentControl Content="{Binding Path=GridModel}" />

Now if you set your GridModel Property (for example type object) to VariantA or VariantB, it will switch the DataTemplate.

VariantA & B example Implementation:

public class VariantA
{
    public ObservableCollection<ViewModel1> DataList { get; set; }
}

public class VariantB
{
    public ObservableCollection<ViewModel2> DataList { get; set; }
}

Hope this helps.