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

Cor*_*ger 3 data-binding wpf 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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

而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>
Run Code Online (Sandbox Code Playgroud)

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

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

有人可以帮我找到解决方案吗?

And*_*ndy 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));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

您也应该为您的test班级做同样的事情.

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

更新:好的,我想我有这个工作.我认为你缺少的部分代码在你发布的内容(像什么DataContextWindow啦),但这里是我得到的工作:

我创建了一个名为的类ViewModel,它被设置为DataContextmain 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));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我将两个列表的创建移动到代码中.有一件事我你的样品中注意到的是,一个实例ListOfTests被用作ItemsSourceComboBox,而另一个实例是用来建造ListOfUsers.我不确定这是否是问题的一部分,但最好只有一个测试列表.

主要的XAML 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>
Run Code Online (Sandbox Code Playgroud)

让事情发挥作用的关键是CurrentUser财产.这势必会ListBox.SelectedItem,并ComboBox.SelectedItem势必CurrentUser.UserTest.这将改变选择,ComboBox以表示在中选择的用户的测试ListBox.

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