[英]How to load a list into a ComboBox DataGrid and display selected value from another list?
Goal目标
I am aiming to achieve the following:我的目标是实现以下目标:
Visual Output视觉Output
Code...代码...
Models楷模
I have 2 models我有 2 个模型
public class Person
{
public string Name { get; set; }
public Position Position { get; set; }
}
public class Position
{
public int PositionId { get; set; }
public string PositionTitle { get; set; }
}
View Model查看 Model
public class ViewModel : BaseViewModel
{
public ViewModel()
{
People = new ObservableCollection<Person>();
People.Add(new Person { Name = "Name 1", Position = new Position { PositionId = 1, PositionTitle = "Position Title 1" } });
People.Add(new Person { Name = "Name 2", Position = new Position { PositionId = 1, PositionTitle = "Position Title 1" } });
People.Add(new Person { Name = "Name 3", Position = new Position { PositionId = 2, PositionTitle = "Position Title 2" } });
Positions = new ObservableCollection<Position>();
Positions.Add(new Position { PositionId = 1, PositionTitle = "Position Title 1" });
Positions.Add(new Position { PositionId = 2, PositionTitle = "Position Title 2" });
}
private ObservableCollection<Person> people;
public ObservableCollection<Person> People
{
get { return people; }
set
{
people = value;
OnPropertyChanged();
}
}
private ObservableCollection<Position> _positions;
public ObservableCollection<Position> Positions
{
get { return _positions; }
set
{
_positions = value;
OnPropertyChanged();
}
}
}
public class Person
{
public string Name { get; set; }
public Position Position { get; set; }
}
public class Position
{
public int PositionId { get; set; }
public string PositionTitle { get; set; }
}
View看法
<DataGrid ItemsSource="{Binding People}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding Name}" />
<DataGridTemplateColumn Header="Position Title">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding Path=DataContext.Positions, RelativeSource={RelativeSource AncestorType=DataGrid}}"
DisplayMemberPath="PositionTitle"
SelectedValue="{Binding Path=Position}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
Question问题
How do I set the SelectedItem/Index of Position to what the Person's Position is set to?如何将 Position 的 SelectedItem/Index 设置为 Person 的 Position 设置的值?
You could override the Equals
method of your Position
class to define that two objects with the same id should be considered equal:您可以覆盖
Position
class 的Equals
方法来定义具有相同 id 的两个对象应被视为相等:
public class Position
{
public int PositionId { get; set; }
public string PositionTitle { get; set; }
public override bool Equals(object obj) =>
obj is Position p && PositionId == p.PositionId;
public override int GetHashCode() => PositionId.GetHashCode();
}
<DataTemplate>
<ComboBox ItemsSource="{Binding Path=DataContext.Positions,
RelativeSource={RelativeSource AncestorType=DataGrid}}"
DisplayMemberPath="PositionTitle"
SelectedItem="{Binding Path=Position,
UpdateSourceTrigger=PropertyChanged,
Mode=TwoWay}" />
</DataTemplate>
Nope.. doesn't work
不行。。不行
Full answer, for all inconsistencies in the code:完整答案,对于代码中的所有不一致:
namespace PeoplePosition
{
public class Position
{
public int PositionId { get; }
public string PositionTitle { get; }
public Position(int positionId, string positionTitle)
{
PositionId = positionId;
PositionTitle = positionTitle;
}
}
}
using Simplified;
namespace PeoplePosition
{
public class Person : BaseInpc // Implementation of the "INPC" interface
{
private string _name;
private Position _position;
public string Name { get => _name; set => Set(ref _name, value); }
public Position Position { get => _position; set => Set(ref _position, value); }
}
}
If you need to ensure equality of instances by value, then you need to override the Equals and GetHashCode methods (as @mm8 already wrote).如果您需要按值确保实例的相等性,那么您需要覆盖 Equals 和 GetHashCode 方法(正如@mm8 已经写的那样)。 But for mutable types, this is a bad decision, which in some cases can lead to bugs.
但是对于可变类型,这是一个糟糕的决定,在某些情况下可能会导致错误。
If you need to set the values of a reference type corresponding to some collection, then you do not need to re-create instances of this type, but assign one of the elements of the collection that already contains all the valid values.如果需要设置某个集合对应的引用类型的值,则不需要重新创建该类型的实例,而是分配集合中已经包含所有有效值的元素之一。
using System.Collections.ObjectModel;
namespace PeoplePosition
{
public class ViewModel
{
public ViewModel()
{
Positions.Add(new Position(1, "Position Title 1"));
Positions.Add(new Position(2, "Position Title 2"));
People.Add(new Person { Name = "Name 1", Position = Positions[0] });
People.Add(new Person { Name = "Name 2", Position = Positions[0] });
People.Add(new Person { Name = "Name 3", Position = Positions[1] });
}
public ObservableCollection<Person> People { get; }
= new ObservableCollection<Person>();
public ObservableCollection<Position> Positions { get; }
= new ObservableCollection<Position>();
}
}
<Window x:Class="PeoplePosition.PeoplePositionsWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:PeoplePosition"
mc:Ignorable="d"
Title="PeoplePositionsWindow" Height="450" Width="800">
<Window.DataContext>
<local:ViewModel/>
</Window.DataContext>
<UniformGrid Columns="1">
<DataGrid ItemsSource="{Binding People}" AutoGenerateColumns="False" IsReadOnly="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding Name}" />
<DataGridTemplateColumn Header="Position Title">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding Path=DataContext.Positions,
RelativeSource={RelativeSource AncestorType=DataGrid}}"
DisplayMemberPath="PositionTitle"
SelectedItem="{Binding Path=Position,
UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
<DataGrid ItemsSource="{Binding People}" AutoGenerateColumns="False" IsReadOnly="True">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding Name}" />
<DataGridTextColumn Binding="{Binding Position.PositionId, Mode=OneWay}"
Header="PositionId"/>
<DataGridTextColumn Binding="{Binding Position.PositionTitle, Mode=OneWay}"
Header="Position Title"/>
</DataGrid.Columns>
</DataGrid>
</UniformGrid>
</Window>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.