问题
The code below creates two list boxes. When an item in the first list box is selected, I am trying to select the corresponding item in the second list box when there is a match between NameOne and NameTwo. However, it does not select my item in the second list box. Why is that?
XAML:
<Window x:Class="ListBoxTesting.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ListBox Name="ListBoxOne" Grid.Row="0" ItemsSource="{Binding ListOne}" SelectedItem="{Binding SelectedTypeOne}" DisplayMemberPath="NameOne"/>
<ListBox Name="ListBoxTwo" Grid.Row="1" ItemsSource="{Binding ListTwo}" SelectedItem="{Binding SelectedTypeTwo}" DisplayMemberPath="NameTwo"/>
</Grid>
</Window>
Code:
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public class TypeOne : INotifyPropertyChanged
{
public string NameOne { get; set; }
public TypeOne(string name)
{
NameOne = name;
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
}
public class TypeTwo : INotifyPropertyChanged
{
public string NameTwo { get; set; }
public TypeTwo(string name)
{
NameTwo = name;
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
}
TypeOne m_SelectedTypeOne;
public TypeOne SelectedTypeOne
{
get
{
return m_SelectedTypeOne;
}
set
{
m_SelectedTypeOne = value;
SelectedTypeOne.NotifyPropertyChanged("NameOne");
foreach (TypeTwo typeTwo in ListTwo)
{
if (typeTwo.NameTwo == value.NameOne)
{
SelectedTypeTwo = typeTwo;
}
}
}
}
TypeTwo m_SelectedTypeTwo;
public TypeTwo SelectedTypeTwo
{
get
{
return m_SelectedTypeTwo;
}
set
{
m_SelectedTypeTwo = value;
SelectedTypeTwo.NotifyPropertyChanged("NameTwo");
}
}
public List<TypeOne> ListOne { get; set; }
public List<TypeTwo> ListTwo { get; set; }
public MainWindow()
{
InitializeComponent();
DataContext = this;
ListOne = new List<TypeOne>();
ListOne.Add(new TypeOne("Mike"));
ListOne.Add(new TypeOne("Bobby"));
ListOne.Add(new TypeOne("Joe"));
ListTwo = new List<TypeTwo>();
ListTwo.Add(new TypeTwo("Mike"));
ListTwo.Add(new TypeTwo("Bobby"));
ListTwo.Add(new TypeTwo("Joe"));
}
}
回答1:
Create a "Container" ViewModel which implements INotifyPropertyChanged
instead of using the Window
itself as a container.
Doing DataContext = this;
is not recommended.
public class ViewModel: INotifyPropertyChanged
{
public TypeOne SelectedTypeOne
{
get { return m_SelectedTypeOne; }
set
{
m_SelectedTypeOne = value;
NotifyPropertyChanged("SelectedTypeOne");
//foreach (TypeTwo typeTwo in ListTwo)
//{
// if (typeTwo.NameTwo == value.NameOne)
// {
// SelectedTypeTwo = typeTwo;
// }
//}
//these kind of horrible for loops from 500 years ago are not needed in C#. Use proper LINQ:
SelectedTypeTwo = ListTwo.FirstOrDefault(x => x.NameTwo == value.NameOne);
}
}
TypeTwo m_SelectedTypeTwo;
public TypeTwo SelectedTypeTwo
{
get { return m_SelectedTypeTwo; }
set
{
m_SelectedTypeTwo = value;
NotifyPropertyChanged("SelectedTypeTwo");
}
}
}
Then, in the UI:
DataContext = new ViewModel();
来源:https://stackoverflow.com/questions/22208875/why-isnt-my-selected-items-data-binding-updating