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”)。 我认为缺少一些东西可以告诉“the
Person.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); 
}