R-nold
R-nold

Reputation: 242

DataGrid - Binding to a list of lists with MVVM

I have a 'Person' class that can have a list of Items.

Person.cs

public class Person : ObservableObject
{
  private string _id;
  public string Id
  {
    get { return _id; }
    set
    {
      _id = value;
      RaisePropertyChangedEvent("Id");
    }
  }

  ...

  Private IList<Item> _items;
  public IList<Item> Items
  {
    get { return _items; }
    set
    {
      _items = value;
      RaisePropertyChangedEvent("Items");
    }
  }
}

Item.cs

public class Item : ObservableObject
{
  private string _id;
  public string Id
  {
    get { return _id; }
    set
    {
      _id = value;
      RaisePropertyChangedEvent("Id");
    }
  } 

  ...
}

I am trying to display this in a tabbed data grid. First Tab is "Person" and the second tab is "Items".

.XAML

    <Window.DataContext>
      <viewModels:PersonViewModel />
    </Window.DataContext>

    <TabControl>
        <TabItem Header="Person">
            <DataGrid ItemsSource="{Binding Person}" Width="1700" Height="800" AutoGenerateColumns="False" CanUserAddRows="false"
                      VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" RowHeight="20">
                <DataGrid.Columns>
                    <DataGridTextColumn Header="Id" Binding="{Binding Id}" IsReadOnly="True"/>
                    ...
                </DataGrid.Columns>
            </DataGrid>
         </TabItem>

        <TabItem Header="Items">
            <DataGrid ItemsSource="{Binding Person.Items}" Width="1700" Height="800" AutoGenerateColumns="False" CanUserAddRows="false"
                      VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" RowHeight="20">
                <DataGrid.Columns>
                    <DataGridTextColumn Header="Person Id" Binding="{Binding Person.Id}" IsReadOnly="True"/>
                    <DataGridTextColumn Header="Id" Binding="{Binding Id}" IsReadOnly="True"/>
                    ...
                </DataGrid.Columns>
            </DataGrid>
        </TabItem>
    </TabControl>

View Model.cs

    private ObservableCollection<Person> _persons = new ObservableCollection<Person>();

public ObservableCollection<Person> Person
{
  get { return _persons; }
  set
  {
    _persons = value;
    RaisePropertyChangedEvent("Person");
  }
}

This is as far as I have gotten. I'm assuming I need to somehow loop through the Person objects and then do Person.Items but am not sure.

I am able to display my "Person" object perfectly fine, it is just the "Items" tab I am having issues with. I get the error "cannot resolve property "Items" in datacontext of type ObservableCollection"

Thank you for any help

Upvotes: 1

Views: 3200

Answers (1)

mm8
mm8

Reputation: 169420

Create a view model class that keeps track of the currently selected Person as well as all people to be displayed in the first DataGrid:

public class ViewModel : ObservableObject
{
    public ViewModel()
    {
        Persons = new ObservableCollection<Person>();
        //populate your collection here...
        Persons.Add(new Person() { });
        //...
    }

    private Person _selectedPerson;
    public Person SelectedPerson
    {
        get { return _selectedPerson; }
        set
        {
            _selectedPerson = value;
            RaisePropertyChangedEvent("SelectedPerson");
        }
    }

    public ObservableCollection<Person> Persons { get; private set; }
}

Set the DataContext of the TabControl, or its parent window, to an instance of this view model class:

tc.DataContext = new ViewModel();

And bind to the view model properties:

<TabControl x:Name="tc">
    <TabItem Header="Person">
        <DataGrid ItemsSource="{Binding Persons}"
                          SelectedItem="{Binding SelectedPerson}"
                          Width="1700" Height="800" AutoGenerateColumns="False" CanUserAddRows="false"
                      VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" RowHeight="20">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Id" Binding="{Binding Id}" IsReadOnly="True"/>
            </DataGrid.Columns>
        </DataGrid>
    </TabItem>

    <TabItem Header="Items">
        <DataGrid ItemsSource="{Binding SelectedPerson.Items}" Width="1700" Height="800" AutoGenerateColumns="False" CanUserAddRows="false"
                      VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" RowHeight="20">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Person Id" Binding="{Binding Person.Id}" IsReadOnly="True"/>
                <DataGridTextColumn Header="Id" Binding="{Binding Id}" IsReadOnly="True"/>
            </DataGrid.Columns>
        </DataGrid>
    </TabItem>
</TabControl>

Upvotes: 2

Related Questions