带有Listbox和带有绑定的Combobox的WPF主 - 详细信息视图

时间:2009-07-31 20:56:37

标签: wpf data-binding combobox listbox

我几天来一直在寻找我的问题的答案,但我找不到解决方案。

问题是组合框用以前选择的用户更新了User类中的Test对象。

即。如果选择user2而user2有test2,则选择具有test5的user5。现在,如果再次选择user2,它将显示它有test5。

这是一些代码。我有两个类用户和测试。每个都有两个ObservableCollections。这就是我设置它们的方式:

public class User
{
    public string Name { get; set; }
    public int test { get; set; }
    public test userTest { get; set; }
}

public class test
{
    public int ID { get; set; }
    public String Name { get; set; }
}

public class ListOfTests:ObservableCollection<test>
{
    public ListOfTests()
    {
        for (int i = 0; i < 4; i++)
        {
            test newTest = new test();
            newTest.ID = i;
            newTest.Name = "Test " + i;
            Add(newTest);
        }
    }
}

public class ListOfUsers: ObservableCollection<User>
{
    public ListOfUsers()
    {
        ListOfTests testlist = new ListOfTests();
        for (int i = 0; i < 10; i++)
        {
            User newUser = new User();
            newUser.Name = "User " + i;
            newUser.ID = i;
            newUser.userTest = testlist[i];
            Add(newUser);
        }
    }
}

XAML是:

<Window x:Class="ComboboxTest.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ComboboxTest"
Title="Window1" Height="300" Width="300">
<StackPanel x:Name="SP1">
    <StackPanel.Resources>
        <local:ListOfTests x:Key="ListOfTests" />
    </StackPanel.Resources>
    <ListBox ItemsSource="{Binding}" DisplayMemberPath="Name" IsSynchronizedWithCurrentItem="True"/>
    <TextBox Text="{Binding Path=Name}" Foreground="Black"  />
    <TextBox Text="{Binding Path=userTest}" />  
    <ComboBox SelectedItem="{Binding Path=userTest}" 
              SelectedValue="{Binding Path=userTest.ID}"
              ItemsSource="{Binding Source={StaticResource ListOfTests}}" 
              DisplayMemberPath="Name" 
              SelectedValuePath="ID"

              Foreground="Black" />
</StackPanel>

现在,如果我将SelectedItem上的Binding更改为“{Binding Path = userTest,Mode = OneWay}”,那么它可以正常工作,但我无法手动更改它。

这是一个踢球者的想法......如果我的目标是.Net 4.0(VS2010),那么它的工作正常......

任何人都可以帮我找到解决方案吗?

2 个答案:

答案 0 :(得分:5)

如果我理解你的问题,听起来好像WPF在属性值发生变化时没有收到通知。您可以通过实现INotifyPropertyChanged接口来解决这个问题。例如,User类看起来像这样:

public class User : INotifyPropertyChanged
{
    private string name = string.Empty;
    public string Name
    {
        get { return this.name; }
        set
        {
            this.name = value;
            this.OnPropertyChanged("Name");
        }
    }

    private int test = 0;
    public int Test
    {
        get { return this.test; }
        set
        {
            this.test = value;
            this.OnPropertyChanged("Test");
        }
    }

    private test userTest = null;
    public test UserTest
    {
        get { return this.userTest; }
        set
        {
            this.userTest = value;
            this.OnPropertyChanged("UserTest");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string propName)
    {
        PropertyChangedEventHandler eh = this.PropertyChangd;
        if(null != eh)
        {
            eh(this, new PropertyChangedEventArgs(propName));
        }
    }
}

您也应该为test课程做同样的事情。

WPF将监视PropertyChanged事件何时被触发,并根据需要更新任何受影响的绑定。这应该会导致ComboBox中的所选项目更改回用户2的测试。

更新:好的,我认为我的工作正常。我认为你在发布的内容中缺少部分代码(比如DataContext的{​​{1}}),但这就是我的工作:

我创建了一个名为Window的类,该类设置为主ViewModel的{​​{1}}。这是它的代码:

DataContext

我将两个列表的创建移到了代码中。我在您的示例中注意到的一件事是Window的一个实例用作class ViewModel : INotifyPropertyChanged { public ViewModel() { for(int i = 0; i < 4; i++) { this.tests.Add(new Test() { ID = i, Name = "Test " + i.ToString(), }); } for(int i = 0; i < 4; i++) { this.users.Add(new User() { Name = "User " + i.ToString(), ID = i, UserTest = this.tests[i], }); } } private ObservableCollection<User> users = new ObservableCollection<User>(); public IEnumerable<User> Users { get { return this.users; } } private ObservableCollection<Test> tests = new ObservableCollection<Test>(); public IEnumerable<Test> Tests { get { return this.tests; } } private User currentUser = null; public User CurrentUser { get { return this.currentUser; } set { this.currentUser = value; this.OnPropertyChanged("CurrentUser"); } } public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged(string propName) { var eh = this.PropertyChanged; if(null != eh) { eh(this, new PropertyChangedEventArgs(propName)); } } } 的{​​{1}},而另一个实例用于构建ListOfTests。我不确定这是否是问题的一部分,但最好只有一个测试列表。

主要ItemsSource的XAML如下:

ComboBox

让事情有效的关键是ListOfUsers属性。它绑定到Window<Window x:Class="WpfApplication1.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WpfApplication1" Title="Window1" Height="300" Width="300"> <StackPanel> <ListBox ItemsSource="{Binding Path=Users}" SelectedItem="{Binding Path=CurrentUser}" DisplayMemberPath="Name" IsSynchronizedWithCurrentItem="True"> </ListBox> <TextBox Text="{Binding Path=CurrentUser.Name}" /> <TextBox Text="{Binding Path=CurrentUser.UserTest.Name}" /> <ComboBox ItemsSource="{Binding Path=Tests}" SelectedItem="{Binding Path=CurrentUser.UserTest}" DisplayMemberPath="Name" /> </StackPanel> </Window> 绑定到CurrentUser。这将更改ListBox.SelectedItem中的选择,以表示在ComboBox.SelectedItem中选择的用户的测试。

我使用Visual Studio 2008 SP1完成了所有工作,所以希望它也能为您工作。如果您在使用此工作时遇到任何问题,请告诉我,我会看到我能做些什么。

答案 1 :(得分:0)

安迪,

这是我现在的代码中更易读的摘录。

public class User : INotifyPropertyChanged
{
    private string name;
    public string Name 
    {
        get
        {
            return name;
        }
        set
        {
            name = value;
            OnPropertyChanged("Name");
        }
    }

    private int iD;
    public int ID 
    {
        get
        {
            return iD;
        }
        set
        {
            iD = value;
            OnPropertyChanged("ID");
        }
    }

    private test userTest;
    public test UserTest 
    {
        get
        {
            return userTest;
        }
        set
        {
            userTest = value;
            OnPropertyChanged("UserTest");
        }
    }


    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string propName)
    {
        PropertyChangedEventHandler eh = this.PropertyChanged;
        if (null != eh)
        {
            eh(this, new PropertyChangedEventArgs(propName));
        }
    }
}

看起来比评论更好。

此致 Corne