I'm at a learning project right now in which I have two models. User and Role. User has a reference to one Role object. I have a collection of both stored in my ViewModel as an IObservableCollection (Users and Roles). In my View, I have a DataGrid in which I set the DataContext/ItemsSource to the Users collection from my ViewModel using Caliburn.Micro, in the DataGrid I have a DataGridComboBoxColumn that is supposed to display all the entries of the Roles Collection from my ViewModel, but I just can't access them.
I've already tried everything I found on the Internet. RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}
and every variation I found of that, using the DataGridComboBoxColumn.ElementStyle / DataGridComboBoxColumn.EditingElementStyle
method where I set the ItemsSource through them, DisplayMember etc. Nothing worked even remotely.
This is my current view
<UserControl x:Class="UserModule.Views.User.ListUsersView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:UserModule.Views.User"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<StackPanel>
<DataGrid x:Name="Users" AutoGenerateColumns="False" CanUserAddRows="True">
<DataGrid.Columns>
<DataGridTextColumn x:Name="Username" Header="Username" Binding="{Binding Username}"/>
<DataGridTextColumn x:Name="Role" Header="Role" Binding="{Binding Role.RoleName}"/> <!--This is the current Role the User has-->
<DataGridComboBoxColumn Header="Group"
ItemsSource="{Binding Path=DataContext.Roles, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" DisplayMemberPath="RoleName" />
</DataGrid.Columns>
</DataGrid>
</StackPanel>
</UserControl>
And this is (the relevant part of) my current ViewModel where I get the data from
namespace UserModule.ViewModels.User
{
using Caliburn.Micro;
public class ListUsersViewModel : Screen
{
private IObservableCollection<User> users;
private User selectedUser;
/// <summary>
/// Constructor for ListUserViewModel
/// </summary>
public ListUsersViewModel()
{
this.LoadData(); //Loads data from database into Users and Roles
}
/// <summary>
/// Loaded User model-objects from database
/// </summary>
public IObservableCollection<User> Users
{
get => this.users;
set
{
this.users = value;
this.NotifyOfPropertyChange();
}
}
public IObservableCollection<Role> Roles { get; set; }
}
}
Both Collections are populated with data. The Username and RoleName are shown properly, but I can't get the ComboBox to show any information about the Roles, not even the Caliburn.Micro error message "No View found for x". If I use an ComboBox outside of my DataGrid on the other hand, while simply binding to Roles, of course I get this error message for each Role in Roles.
Okay, I kind of solved this now...by not using DataGridComboBoxColumn but rather making my own ComboBoxColumn through the DataGridTemplateColumn which has a TextBlock in the CellTemplate and a ComboBox in the CellEditingTemplate
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Username}"/>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Role.RoleName}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding Path=DataContext.Roles, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" DisplayMemberPath="RoleName"/>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>