2

i would like to bind a xaml DataGrid to a Model containing somthing like that:

TheModel{
  instanceOfClassA
}

ClassA{
  someProps
  Dictionary<string, classB>
}

ClassB{
  someOtherProps
  Dictionary<string, classC>
}

ClassC{
  someMoreProps
}

This Means inside the DataGrid there will be a row foreach ClassC in ClassB in ClassA with columns containing data of all three dictionarys.

I dont want to implement a TOList method inside the Model because that would break the separation between Model and View.

Is there a xaml element i can use?

Thanks Philipp.

JPhil
  • 68
  • 6

1 Answers1

1

I think you will need to represent your data as hierarchical rows in the DataGrid. You can do that like this.

<DataGrid AutoGenerateColumns="False"
          ItemsSource="{Binding Data}"
          RowDetailsVisibilityMode="Visible">

  <DataGrid.Columns>
    <DataGridTextColumn Binding="{Binding P1}" />
    <DataGridTextColumn Binding="{Binding P2}" />
  </DataGrid.Columns>

  <DataGrid.RowDetailsTemplate>

    <DataTemplate>

      <DataGrid AutoGenerateColumns="False"
                ItemsSource="{Binding DictionaryInA.Values}"
                RowDetailsVisibilityMode="Visible">

        <DataGrid.RowDetailsTemplate>

          <DataTemplate>

            <DataGrid AutoGenerateColumns="False"
                      ItemsSource="{Binding DictionaryInB.Values}">

              <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding P1}" />
                <DataGridTextColumn Binding="{Binding P2}" />
              </DataGrid.Columns>

            </DataGrid>

          </DataTemplate>

        </DataGrid.RowDetailsTemplate>

        <DataGrid.Columns>
          <DataGridTextColumn Binding="{Binding P1}" />
          <DataGridTextColumn Binding="{Binding P2}" />
        </DataGrid.Columns>

      </DataGrid>
    </DataTemplate>
  </DataGrid.RowDetailsTemplate>
</DataGrid>

Your data will look something like this.

- Class A Row 1
  - Class B Row 1
      - Class C Row 1
      - Class C Row 2
      - Class C Row N
  - Class B Row 2
      - Class C Row 1
      - Class C Row 2
      - Class C Row N
  - Class B Row N
      Class C Row 1
      Class C Row 2
      Class C Row N
- Class A Row 2
  - Class B Row 1
      - Class C Row 1
      - Class C Row 2
      - Class C Row N
  - Class B Row 2
      - Class C Row 1
      - Class C Row 2
      - Class C Row N
  - Class B Row N
      Class C Row 1
      Class C Row 2
      Class C Row N
- Class A Row N
  - Class B Row 1
      - Class C Row 1
      - Class C Row 2
      - Class C Row N
  - Class B Row 2
      - Class C Row 1
      - Class C Row 2
      - Class C Row N
  - Class B Row N
      Class C Row 1
      Class C Row 2
      Class C Row N

If you want expand/collapse functionality, take a look at this link.

Displaying hierarchal parent child data in WPF DataGrid

If you have access to infragistics controls, I would highly recommend using the XamDataGrid instead of the .NET DataGrid. You can pretty much do anything you want with that control.

http://www.infragistics.com/products/wpf/data-grid/

Update

For flat data, you can can create a wrapper for your model like this.

public IEnumerable FlattenedModel
{
    get
    {
        return (from b in TheModel.InstanceOfClassA.DictionaryInA.Values
                from c in b.DictionaryInB.Values
                select new
                {
                    PropertyA1 = TheModel.PropertyA1,
                    PropertyA2 = TheModel.PropertyA2,
                    PropertyB1 = b.PropertyB1,
                    PropertyB2 = b.PropertyB2,
                    PropertyC1 = c.PropertyC1,
                    PropertyC2 = c.PropertyC2
                }).ToList();
    }
}

If you can't do a wrapper, then a converter will work as well.

public class FlattenTheModelConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        var InstanceOfTheModel = value as TheModel;

        return (from b in InstanceOfTheModel.InstanceOfClassA.DictionaryInA.Values
                from c in b.DictionaryInB.Values
                select new
                {
                    PropertyA1 = InstanceOfTheModel .PropertyA1,
                    PropertyA2 = InstanceOfTheModel .PropertyA2,
                    PropertyB1 = b.PropertyB1,
                    PropertyB2 = b.PropertyB2,
                    PropertyC1 = c.PropertyC1,
                    PropertyC2 = c.PropertyC2
                }).ToList();
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

If you decide to use a converter, you will need to modify your XAML as follows.

<DataGrid ItemsSource="{Binding TheModel, Converter={StaticResource FlattenTheModelConverter}, Mode=OneWay}">
Community
  • 1
  • 1
Timothy Schoonover
  • 3,195
  • 4
  • 29
  • 44