2009-07-31 63 views
3

我幾天來一直在四處尋找我的問題的答案,但無法找到解決方案。帶有ListBox和Combobox的WPF Master-Details視圖綁定

問題是,組合框更新了用戶類中的測試對象與先前選擇的用戶。

即您選擇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綁定到「{綁定路徑= userTest,模式= OneWay}「,那麼它的工作原理,但我不能手動改變它。

這裏是一個踢球者以爲,如果我面向.NET 4.0(VS2010),那麼它工作正常...

誰能幫我找到一個解決的辦法?

回答

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的測試。

更新:好的,我認爲我得到了這個工作。我認爲你缺少的部分代碼在你發佈什麼(例如什麼DataContextWindow是),但這裏是我得到的工作:

我創建了一個名爲ViewModel類,它被設置爲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)); 
     } 
    } 
} 

我將兩個列表的創建移動到代碼。我在示例中注意到的一件事是ListOfTests的一個實例用作ComboBoxItemsSource,而另一個實例用於構建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> 

到工作把事情的關鍵是CurrentUser財產。它綁定到ListBox.SelectedItem,而ComboBox.SelectedItem綁定到CurrentUser.UserTest。這將更改ComboBox中的選擇,以表示在ListBox中選擇的用戶的測試。

我得到了所有使用Visual Studio 2008 SP1的工作,所以希望它也能爲你工作。如果您在解決問題時遇到任何問題,請告訴我,我會看看我能做些什麼。

+0

安迪嗨, 我已經實現INotifyPropertyChanged的如你所說的,但不幸的是,我仍然得到了同樣的問題。 我已在http://cid-eddcda42d46afe81.skydrive.live.com/self.aspx/Public%20Dev/ComboboxTest.zip發佈解決方案文件 請注意用戶數量和測試數量應該相同。隨機點擊幾個用戶,然後檢查您點擊的用戶和測試是否仍然排隊。 – 2009-08-03 20:07:48

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