2009-07-31 16 views
3

私の質問に対する答えは数日前から探していますが、解決策を見つけることができません。リストボックスとバインドされたコンボボックスを使用したWPFマスター - 詳細ビュー

問題は、コンボボックスは、以前選択したユーザーとユーザー・クラスのテストオブジェクトを更新していることです。

はつまり、あなたはuser2の選択とUser2は、あなたがしてTEST5を持っているユーザ5を選択TEST2を持っています。今度はuser2を再度選択すると、test5があることが示されます。

ここにいくつかのコードがあります。私は2つのクラスのユーザーとテストを持っています。そしてそれぞれのObservableCollectionsは2つです。これは私がそれらをセットアップ持っているかである:

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> 

は、今私が変更された場合、「{バインディングパス= userTestへのSelectedItemにバインド、モード= OneWay} "それは動作しますが、手動で変更することはできません。思ったここ

がキッカーである...私は.NET 4.0(VS2010)を標的とした場合、それは正常に動作します...

は、誰も私がこれに対する解決策を見つける助けてくださいことはできますか?

答えて

5

私はあなたの質問を理解していた場合ときに、プロパティの値が変更されているWPFが通知されないように、それが鳴ります。これを回避するには、INotifyPropertyChangedインターフェイスを実装します。例えば、Userクラスは次のようになります:あなたはおそらく同様に、あなたのtestクラスに同じことを行う必要があります

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

WPFはPropertyChangedイベントが発生したときのために監視し、必要に応じて任意の影響を受けるバインディングを更新します。これにより、ComboBoxの選択項目がuser2のテストに戻されます。

更新:OK、私はこの作業を得たと思います。私はあなたが(WindowためDataContextが何であるかのように)掲載するもので、コードの一部が欠けていると思いますが、ここで私が働いて得たものです:

私はDataContextに設定されているViewModelというクラスを作成しましたメイン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)); 
     } 
    } 
} 

2つのリストの作成をコードに移動しました。私はあなたのサンプルに気づいたことの一つは、別のインスタンスがListOfUsersを構築するために使用している間にListOfTestsの1つのインスタンスは、ComboBoxItemsSourceとして使用されたということです。それが問題の一部であるかどうかはわかりませんが、テストのリストを1つだけ持つ方がよいでしょう。

メインWindowためのXAMLは以下の通りです:

<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.SelectedItemCurrentUser.UserTestに結合される。これにより、ComboBoxの選択がListBoxで選択されたユーザーのテストを表すように変更されます。

これはVisual Studio 2008 SP1を使用しているので、うまくいけばそれもうまくいくはずです。この問題を解決するのに問題がある場合は、私に知らせてください。

+0

こんにちはアンディ、 あなたが示唆したように、私はINotifyPropertyChangedのを実装しているが、残念ながら私はまだ同じ問題を取得しています。 http://cid-eddcda42d46afe81.skydrive.live.com/self.aspx/Public%20Dev/ComboboxTest.zipにソリューションファイルを掲載しました ユーザー番号とテスト番号が同じである必要があることに注意してください。いくつかのユーザーをランダムにクリックし、ユーザーとテストがまだ整列していれば、クリックしたユーザーをチェックしてください。 –

+0

あなたのzipファイルを開くことができませんでした - 無効であることを示すエラーが表示されました。とにかく、あなたのDataContextであり、userTestプロパティを持つオブジェクトもINotifyPropertyChangedを実装していますか? – Andy

+0

こんにちはアンディ、 はい、それは... は、私のようにそれを持っているん: パブリッククラスユーザー: { プライベート文字列名をINotifyPropertyChangedの。 公開ストリング名 ... ... プライベートテストuserTest; 公開テストUserTest { get { return userTest; } セット { userTest = value; OnPropertyChanged( "UserTest"); } } –

0

Andy、

これは私が現在持っているコードからより読みやすいものです。

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

関連する問題