I need to display all the information of an object in a DataGrid
ItemsCollectionA, ItemsCollectionB and ItemsCollectionC are all ObservableCollections
.
I have a datagrid:
<DataGrid ItemsSource="{Binding Path=itemscollectionA}" HeadersVisibility="All" />
This displays all properties in grid format but the ItemsCollectionB and ItemsCollectionC are appearing as (collection).
How can I get ItemsCollectionB and ItemsCollectionC to expand the grid downward and out to show their properties as well
If you can specify the columns instead of auto-generating them, this could be very easy.
Here's an example:
<DataGrid ItemsSource="{Binding Employees}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding EmployeeName}"/>
<!-- Displays the items of the first collection-->
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ListBox ItemsSource="{Binding Dogs}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<!-- Displays the items of the second collection-->
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ListBox ItemsSource="{Binding Cats}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
ViewModel:
public class MainWindowViewModel : NotificationObject
{
public MainWindowViewModel()
{
Employees = new ObservableCollection<Employee>
{
new Employee { EmployeeName = "Steven"},
new Employee { EmployeeName = "Josh"},
};
}
public ObservableCollection<Employee> Employees { get; set; }
}
Models:
public class Employee
{
public Employee()
{
Dogs = new ObservableCollection<Dog>
{
new Dog { Gender = 'M'},
new Dog { Gender = 'F'},
};
Cats = new ObservableCollection<Cat>
{
new Cat { Name = "Mitzy" , Kind = "Street Cat"},
new Cat { Name = "Mitzy" , Kind = "House Cat"}
};
}
public string EmployeeName { get; set; }
public ObservableCollection<Dog> Dogs { get; set; }
public ObservableCollection<Cat> Cats { get; set; }
}
public class Dog
{
public char Gender { get; set; }
public override string ToString()
{
return "Dog is a '" + Gender + "'";
}
}
public class Cat
{
public string Name { get; set; }
public string Kind { get; set; }
public override string ToString()
{
return "Cat name is " + Name + " and it is a " + Kind;
}
}
Consider ItemsCollectionA
as Employees
and ItemsCollectionB
and ItemsCollectionC
as Dogs
and Cats
. It still uses the ToString
to display the Dogs
and Cats
object's that I overridden, But you can simply set a DataTemplate
to the listBox's within the columns to decide how to display your models. Also notice the AutoGenerateColumns="False"
on the DataGrid
to avoid creating the columns twice.
Hope this helps
A DataGrid can only manage one item source. Everything is row based and the columns are not that intelligent.
Two ways:
- to combine your data into a new object with both sets of fields (would be the easiest).
- synchronise 2 datagrids side-by-side.
Ok it seems like datagrid was entirely the wrong thing I needed here. I made a stackpanel of listbox with the itemssource set to each binding and it's displaying fine
<StackPanel Background="white" HorizontalAlignment="Stretch" Margin="0">
<ListBox Background="white" x:Name="BetsListBox" VerticalAlignment="Stretch" BorderThickness="0"
ItemsSource="{Binding Path=ItemsCollectionA}" Margin="0" Width="Auto" HorizontalAlignment="Stretch" >
<ListBox.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="#F0F0F0"/>
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="#F0F0F0"/>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Black"/>
</ListBox.Resources>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel >
<ListBox ItemsSource="{Binding Path=ItemsCollectionB}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlockText="{Binding Path=varA}" />
<TextBlockText="{Binding Path=varB}" />
<TextBlockText="{Binding Path=varC}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<ListBox BorderThickness="0" ItemsSource="{Binding Path=ItemsCollectionC}" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" >
<TextBlock Text="{Binding Path=VarA}" ToolTip="{Binding Name}"/>
<TextBlock Text="{Binding Path=VarB}" ToolTip="{Binding Name}"/>
<TextBlock Text="{Binding Path=VarC}" ToolTip="{Binding Name}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox >
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>