Reputation: 105
I tried really different ways to make my combobox working but I'm still stuck :(
Here is a very simplified version of my app : (just edited, sorry for mistakes)
<ListView ItemsSource="{Binding People}" SelectedItem="{Binding SelectedPerson}"/>
<ComboBox ItemsSource="{Binding Grades}" SelectedItem="{Binding SelectedPerson.MyGrade}"
DisplayMemberPath="Name"/>
And the code behind :
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
}
The problem is that the combobox is still empty when I select an item in the listview.
The itemsource is OK (If I click on the combobox, I can see "grade 1" and "grade 2").
I think there is something missing to tell "the Person.Grade
is part of the Grades
list" but I cannot find what.
Hope you can help me ;)
Upvotes: 5
Views: 4086
Reputation: 132548
Is the SelectedItem
the exact same reference in memory as the item in the ItemsSource
?
By default, WPF will compare the SelectedItem
to the items in the ItemsSource
by reference, and if they're not the same reference in memory, it will return no matching item.
If you are unable to do this in your code, the most common workarounds are to either:
Bind the SelectedValue
to a value type instead of a reference type, and set the SelectedValuePath
<ComboBox ItemsSource="{Binding Grades}"
SelectedValue="{Binding SelectedPerson.MyGrade.GradeId}"
SelectedValuePath="GradeId"
DisplayMemberPath="Name"/>
Or override the .Equals()
to ensure the two objects are considered equal when specific properties match, as opposed to being considered equal when the reference in memory matches.
public override bool Equals(object obj)
{
if (obj == null || !(obj is Grade))
return false;
return ((Grade)obj).GradeId == this.GradeId);
}
Upvotes: 8
Reputation: 186
Please make sure you have no binding errors in the first place. You can verify this by opening up the output window in Visual studio and check you have no errors messages relating to binding expressions.
You should be able to easily spot these because the error message will contain the following text: BindingExpression path error
As an alternative approach why don't you try and bind the ComboBox selected item directly with the selected item from the ListView.
Below is a sample snippet of how one would achieve this:
<ListView
x:Name="listView"
ItemsSource="{Binding People}"
DisplayMemberPath="Name" />
<ComboBox
ItemsSource="{Binding Grades}"
SelectedItem="{Binding SelectedItem.MyGrade, ElementName=listView}"
DisplayMemberPath="Name"/>
Upvotes: 0
Reputation: 26058
A couple things, first you are binding to Grade
and your property is called MyGrade
. Second you are instantiating different objects for grade in the Grades
list and using different objects to assign to each person, you want to use the same objects if you want them to map correctly, something like this:
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] });
Lastly you might want to make the Grades collection an ObservableCollection
as well if you are going to bind it to the UI. Also it seems a bit odd that your RaisePropertyChanged
doesn't take in the name of the property.
There may be other mistakes as well but that is what jumped out to me right away.
Upvotes: 2