将 DataGridComboBoxCollumn 绑定到我的 ViewModel 中的 IObservableCollection
Binding a DataGridComboBoxCollumn to a IObservableCollection in my ViewModel
我现在正在进行一个学习项目,其中有两个模型。用户和角色。用户具有对一个角色对象的引用。我将两者的集合作为 IObservableCollection(用户和角色)存储在我的 ViewModel 中。
在我的视图中,我有一个 DataGrid,其中我使用 Caliburn.Micro 将 DataContext/ItemsSource 设置为我的 ViewModel 中的用户集合,在 DataGrid 中我有一个 DataGridComboBoxColumn,它应该显示角色的所有条目来自我的 ViewModel 的集合,但我无法访问它们。
我已经尝试了我在 Internet 上找到的所有内容。 RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}
以及我发现的每个变体,使用 DataGridComboBoxColumn.ElementStyle / DataGridComboBoxColumn.EditingElementStyle
方法,我通过它们设置 ItemsSource,DisplayMember 等。甚至远程都没有工作。
这是我目前的观点
<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>
这是我当前 ViewModel 的(相关部分),我从中获取数据
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; }
}
}
两个集合都填充了数据。用户名和角色名显示正确,但我无法让 ComboBox 显示有关角色的任何信息,甚至 Caliburn.Micro 错误消息 "No View found for x" 也没有。另一方面,如果我在我的 DataGrid 之外使用 ComboBox,同时简单地绑定到角色,我当然会为角色中的每个角色收到此错误消息。
好的,我现在有点解决了这个问题...通过不使用 DataGridComboBoxColumn 而是通过 DataGridTemplateColumn 创建我自己的 ComboBoxColumn,它在 CellTemplate 中有一个 TextBlock,在 CellEditingTemplate 中有一个 ComboBox
<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>
您正在让 setter 侦听 UI 中的更改,但没有触发更新以更改值:
使 class 继承自 INotifyPropertyChanged
并使用类似的东西:
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
并在 setter 中触发 OnPropertyChanged()
。
我现在正在进行一个学习项目,其中有两个模型。用户和角色。用户具有对一个角色对象的引用。我将两者的集合作为 IObservableCollection(用户和角色)存储在我的 ViewModel 中。 在我的视图中,我有一个 DataGrid,其中我使用 Caliburn.Micro 将 DataContext/ItemsSource 设置为我的 ViewModel 中的用户集合,在 DataGrid 中我有一个 DataGridComboBoxColumn,它应该显示角色的所有条目来自我的 ViewModel 的集合,但我无法访问它们。
我已经尝试了我在 Internet 上找到的所有内容。 RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}
以及我发现的每个变体,使用 DataGridComboBoxColumn.ElementStyle / DataGridComboBoxColumn.EditingElementStyle
方法,我通过它们设置 ItemsSource,DisplayMember 等。甚至远程都没有工作。
这是我目前的观点
<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>
这是我当前 ViewModel 的(相关部分),我从中获取数据
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; }
}
}
两个集合都填充了数据。用户名和角色名显示正确,但我无法让 ComboBox 显示有关角色的任何信息,甚至 Caliburn.Micro 错误消息 "No View found for x" 也没有。另一方面,如果我在我的 DataGrid 之外使用 ComboBox,同时简单地绑定到角色,我当然会为角色中的每个角色收到此错误消息。
好的,我现在有点解决了这个问题...通过不使用 DataGridComboBoxColumn 而是通过 DataGridTemplateColumn 创建我自己的 ComboBoxColumn,它在 CellTemplate 中有一个 TextBlock,在 CellEditingTemplate 中有一个 ComboBox
<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>
您正在让 setter 侦听 UI 中的更改,但没有触发更新以更改值:
使 class 继承自 INotifyPropertyChanged
并使用类似的东西:
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
并在 setter 中触发 OnPropertyChanged()
。