为什么我所选项目的数据绑定不更新?

时间:2014-03-05 20:48:23

标签: c# wpf xaml binding listbox

下面的代码会创建两个列表框。当选择第一个列表框中的项目时,我试图在NameOne和NameTwo之间匹配时在第二个列表框中选择相应的项目。但是,它不会在第二个列表框中选择我的项目。那是为什么?

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>

代码:

/// <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 个答案:

答案 0 :(得分:2)

创建一个“容器”ViewModel,它实现INotifyPropertyChanged而不是使用Window本身作为容器。

不建议执行DataContext = this;

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");
        }
    }
}

然后,在UI中:

DataContext = new ViewModel();