C# Combobox将itemsource绑定到自定义列表,并将selecteditem绑定到该列表的实例;行不通
我尝试了很多不同的方法来让我的组合框工作,但我还是被卡住了:( 这是我的应用程序的一个非常简化的版本:(刚刚编辑,抱歉出错)C# Combobox将itemsource绑定到自定义列表,并将selecteditem绑定到该列表的实例;行不通,c#,wpf,data-binding,combobox,selecteditem,C#,Wpf,Data Binding,Combobox,Selecteditem,我尝试了很多不同的方法来让我的组合框工作,但我还是被卡住了:( 这是我的应用程序的一个非常简化的版本:(刚刚编辑,抱歉出错) 以及背后的代码: public class Person { private string name; public string Name { get { return name; } set { if (name != value) {
以及背后的代码:
public class Person
{
private string name;
public string Name
{
get { return name; }
set
{
if (name != value)
{
name = value;
NotifyPropertyChanged("Name");
}
}
}
private Grade myGrade;
public Grade MyGrade
{
get { return myGrade; }
set
{
if (myGrade != value)
{
myGrade = value;
NotifyPropertyChanged("MyGrade");
}
}
}
//-- INotifyPropertyChanged implementation
}
public class Grade
{
private string name;
public string Name
{
get { return name; }
set
{
if (name != value)
{
name = value;
NotifyPropertyChanged("Name");
}
}
}
private int prop;
public int Prop
{
get { return prop; }
set
{
if (prop != value)
{
prop = value;
NotifyPropertyChanged("Prop");
}
}
}
//-- INotifyPropertyChanged implementation
}
public partial class MainWindow : Window
{
public ObservableCollection<Person> People { get; set; }
public ObservableCollection<Grade> Grades { get; set; }
private Person selectedPerson;
public Person SelectedPerson
{
get { return selectedPerson; }
set
{
if (selectedPerson != value)
{
selectedPerson = value;
NotifyPropertyChanged("SelectedPerson");
}
}
}
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
People = new ObservableCollection<Person>();
Grades = new ObservableCollection<Grade>();
Grades.Add(new Grade() { Name = "Grade 1", Prop = 1 });
Grades.Add(new Grade() { Name = "Grade 2", Prop = 2 });
People.Add(new Person() { Name = "guy 1", MyGrade = Grades[0] });
People.Add(new Person() { Name = "guy 2", MyGrade = Grades[0] });
People.Add(new Person() { Name = "guy 3", MyGrade = Grades[1] });
}
//-- INotifyPropertyChanged implementation
}
公共类人物
{
私有字符串名称;
公共字符串名
{
获取{返回名称;}
设置
{
如果(名称!=值)
{
名称=值;
NotifyPropertyChanged(“名称”);
}
}
}
私家职系;
公共职系MyGrade
{
获取{return myGrade;}
设置
{
如果(myGrade!=值)
{
myGrade=数值;
通知物业变更(“MyGrade”);
}
}
}
//--INotifyPropertyChanged实现
}
公营班级
{
私有字符串名称;
公共字符串名
{
获取{返回名称;}
设置
{
如果(名称!=值)
{
名称=值;
NotifyPropertyChanged(“名称”);
}
}
}
私人int道具;
公共int道具
{
获取{return prop;}
设置
{
if(prop!=值)
{
道具=价值;
通知财产变更(“财产”);
}
}
}
//--INotifyPropertyChanged实现
}
公共部分类主窗口:窗口
{
公共可观察集合人员{get;set;}
公共可观测收集等级{get;set;}
私人选择的人;
公众人士
{
获取{返回selectedPerson;}
设置
{
如果(selectedPerson!=值)
{
selectedPerson=值;
NotifyPropertyChanged(“选定人员”);
}
}
}
公共主窗口()
{
初始化组件();
this.DataContext=this;
人员=新的可观察集合();
等级=新的可观察集合();
Grades.Add(newgrade(){Name=“Grade 1”,Prop=1});
Grades.Add(新的Grade(){Name=“Grade 2”,Prop=2});
添加(newperson(){Name=“guy 1”,MyGrade=Grades[0]});
添加(newperson(){Name=“guy 2”,MyGrade=Grades[0]});
添加(newperson(){Name=“guy 3”,MyGrade=Grades[1]});
}
//--INotifyPropertyChanged实现
}
问题是,当我在listview中选择一个项目时,组合框仍然是空的。
itemsource是OK(如果我点击组合框,我可以看到“grade 1”和“grade 2”)。
我认为缺少一些东西可以告诉“thePerson.Grade
是Grades
列表的一部分”,但我找不到什么
希望您能帮助我;)有几件事,首先您绑定到
Grade
,您的属性名为MyGrade
。其次,在Grades
列表中为grade实例化不同的对象,并使用不同的对象分配给每个人,如果希望正确映射,则需要使用相同的对象,如下所示:
Grades.Add(new Grade() { Name = "Grade 1", Prop = 1 });
Grades.Add(new Grade() { Name = "Grade 2", Prop = 2 });
People.Add(new Person() { Name = "guy 1", MyGrade = Grades[0] });
People.Add(new Person() { Name = "guy 2", MyGrade = Grades[0] });
People.Add(new Person() { Name = "guy 3", MyGrade = Grades[1] });
最后,如果要将Grades集合绑定到UI,您可能还需要将其设置为一个可观察集合。另外,您的RaisePropertyChanged
没有使用属性的名称,这似乎有点奇怪
可能还有其他错误,但这正是我马上想到的。请首先确保没有绑定错误。您可以通过在VisualStudio中打开“输出”窗口并检查是否没有与绑定表达式相关的错误消息来验证这一点
您应该能够轻松地发现这些错误,因为错误消息将包含以下文本:BindingExpression路径错误
作为一种替代方法,为什么不尝试将ComboBox中的选定项直接绑定到ListView中的选定项
下面是如何实现这一点的示例片段:
<ListView
x:Name="listView"
ItemsSource="{Binding People}"
DisplayMemberPath="Name" />
<ComboBox
ItemsSource="{Binding Grades}"
SelectedItem="{Binding SelectedItem.MyGrade, ElementName=listView}"
DisplayMemberPath="Name"/>
所选的SelectedItem
在内存中的引用是否与ItemsSource
中的项完全相同
默认情况下,WPF将通过引用将SelectedItem
与ItemsSource
中的项目进行比较,如果它们在内存中不是相同的引用,则不会返回匹配的项目
如果在代码中无法做到这一点,最常见的解决方法是:
- 将
SelectedValue
绑定到值类型而不是引用类型,并设置SelectedValuePath
<ComboBox ItemsSource="{Binding Grades}"
SelectedValue="{Binding SelectedPerson.MyGrade.GradeId}"
SelectedValuePath="GradeId"
DisplayMemberPath="Name"/>
是的,您希望等级
(在主窗口中
成为一个可观察集合
)。此外,还需要为其引发INotifyPropertyChanged
事件。正在设置Grades
属性,但没有通知绑定查找新集合。感谢您的错误:)我写“简化应用”太快了。。。不幸的是,问题依然存在。我将编辑我的帖子并更正SelectedItem
与ItemsSource
中的项目在内存中的引用是否完全相同?默认情况下,WPF将通过引用比较项目,因此这可能是您的问题。如果它们不同,我建议使用SelectedValue
或可能覆盖.Equals()
。请参见示例:)我认为问题来自这样的情况,我不认为selecteditem和itemssource来自相同的引用。今晚我会测试一下,让你知道;)真的真的非常感谢!!equals override方法救了我:):)很高兴为你找到了答案:)我将它作为一个答案发布在下面,以防其他人希望为你的答案解决相同的问题,但我没有绑定错误。我看不出捆绑t有什么意义
<ComboBox ItemsSource="{Binding Grades}"
SelectedValue="{Binding SelectedPerson.MyGrade.GradeId}"
SelectedValuePath="GradeId"
DisplayMemberPath="Name"/>
public override bool Equals(object obj)
{
if (obj == null || !(obj is Grade))
return false;
return ((Grade)obj).GradeId == this.GradeId);
}