2010-01-17 60 views
4

在WPF中,我有一個bool集合?值,我想以編程方式將每個這些綁定到單獨的複選框。我希望綁定是TwoWay,以便更改代碼中集合中單個項目的值更新複選框,反之亦然。將控件綁定到WPF中的一個集合/數組中的單個值

我花了很多年試圖找出如何做到這一點,我完全卡住了。使用下面的代碼,當窗口加載時,複選框只會獲得正確的值,就是這樣。更改複選框甚至不更新集合中的值。 (更新:這似乎是.NET4中的一個錯誤,因爲集合在相同的.NET3.5項目中得到更新。更新:Microsoft已經確認該錯誤並且它將在.NET4版本中得到修復。)

非常感謝您的幫助!

C#:

namespace MyNamespace 
{ 
    public partial class MyWindow : Window, INotifyPropertyChanged 
    { 
     public MyWindow() 
     { 
      InitializeComponent(); 
      DataContext = this; 
     } 

     public event PropertyChangedEventHandler PropertyChanged; 
     protected void OnPropertyChanged(string propertyName) 
     { 
      if (PropertyChanged != null) 
      { 
       PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
      } 

     public List<bool?> myCollection = new List<bool?> 
      { true, false, true, false, true, false }; 

     public List<bool?> MyCollection 
     { 
      get { return myCollection; } 
      set { myCollection = value; } 
     } 
    } 
} 

XAML:

<CheckBox IsChecked="{Binding Path=MyCollection[0], Mode=TwoWay}"> 
+0

我還在努力通過前3個答案,但我很困惑,爲什麼我的代碼似乎適用於前兩個受訪者(至少在方向CheckBox - > MyCollection)。對我而言,這根本就沒有發生。如果相關,我使用VS2010 Beta 2和.NET4。 – 2010-01-17 23:14:11

+0

嗯,我肯定沒有想到這將是相關的:我將所有東西都複製到一個.NET 3.5項目,並嘿presto - 複選框更新MyCollection中的值。我想知道爲什麼它不能在.NET 4中工作? – 2010-01-17 23:41:29

+0

嗯,如果你有這樣的代碼在.NET 3.5中工作,但是相同的代碼在.NET 4中不起作用,那就暗示了.NET 4中的一個錯誤。可能值得發佈到Connect。 – itowlson 2010-01-17 23:59:18

回答

5

有幾件事情需要改變,讓這個工作。首先,您需要將您的布爾值封裝在實現INotifyPropertyChanged接口的對象中,以便獲取您正在查找的更改通知。目前,您正在綁定到您的集合中的布爾值,它們並未實現該接口。要做到這一點,你可以創建一個包裝類,像這樣:

public class Wrapper: INotifyPropertyChanged 
    { 
     public event PropertyChangedEventHandler PropertyChanged; 
     protected void OnPropertyChanged(string propertyName) 
     { 
      if (PropertyChanged != null) 
      { 
       PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
      } 
     } 

     private bool val = false; 

     public bool Val 
     { 
      get { return val; } 
      set 
      { 
       val = value; 
       this.OnPropertyChanged("Val"); 
      } 
     } 

     public Wrapper(bool val) 
     { 
      this.val = val; 
     } 

    } 

然後您就需要創建您的形式,而不是布爾值的列表,這些對象。您可能還想使用可觀察集合而不是列表,以便發送添加和刪除項目的通知。如下所示:

public Window1() 
    { 
     InitializeComponent(); 
     this.DataContext = this; 
    } 

    private ObservableCollection<Wrapper> myCollection = new ObservableCollection<Wrapper>() 
     {new Wrapper(true), new Wrapper(false), new Wrapper(true)}; 


    public ObservableCollection<Wrapper> MyCollection 
    { 
     get { return myCollection; } 
    } 

接下來要做的是在你的UI中顯示覆選框列表。爲此,WPF提供了itemscontrols。 ListBox是一個itemscontrol,所以我們可以用它作爲一個起點。將列表框的itemssource設置爲MyCollection。然後,我們需要定義每個Wrapper對象將如何顯示在列表框中,這可以使用在Windows資源中創建的數據模板來完成。這是如下圖所示:

<Window.Resources> 
    <DataTemplate x:Key="myCollectionItems"> 
     <CheckBox IsChecked="{Binding Path=Val, Mode=TwoWay}"></CheckBox> 
    </DataTemplate> 
</Window.Resources> 
<Grid> 
    <ListBox ItemsSource="{Binding Path=MyCollection}" ItemTemplate="{StaticResource myCollectionItems}"></ListBox> 
</Grid> 

這應該讓你和與綁定到布爾列表值複選框的一個簡單的演示運行。

+0

-1雖然你的建議可能是有效的,但只有一件事情需要原始海報的代碼工作,將集合類型從'List '到'ObservableCollection' - 你的答案可能是正確的,但不是問題的關鍵。 – 2010-01-17 20:46:25

+0

該問題指出需要綁定到複選框列表,使用itemcontrol比綁定到每個項目明顯更好。該問題還指出,代碼中的更改應該會導致複選框發生更改,這是通過在包裝器對象中實現更改通知來演示的。據我所知,更改不會傳遞到用戶界面沒有這樣做。 – mattythomas2000 2010-01-17 22:10:31

+0

非常感謝你這個馬特 - 這種方法一定會很有用,因爲我打算以編程方式創建複選框,你的答案爲此提供了一個優雅的解決方案。 – 2010-01-17 23:27:17

0

是什麼讓你覺得它不工作?它的工作對我來說:)

這裏是我的測試XAML:

<UniformGrid> 
    <CheckBox IsChecked="{Binding Path=MyCollection[0], Mode=TwoWay}"/> 
    <ListBox ItemsSource="{Binding MyCollection}"/> 
    <Button Content="Test" Click="Button_Click"/> 
</UniformGrid> 

這裏是我的代碼背後:

private void Button_Click(object sender, RoutedEventArgs e) 
{ 

} 

(剩下的就是你的一樣)

我放在斷點Button_Click和檢查MyCollection[0]它已根據CheckBoxIsChecked值更新。

嘗試將您的集合類型從List<bool?>更改爲ObservableCollection<bool?>也許這就是您認爲它不適用於您的原因(對集合的更改未反映到您視圖中的任何其他位置)。

+0

感謝您的迴應Aviad。我在一個新項目中再次嘗試了我的代碼,以確保但沒有運氣。不知道你是怎麼做到的!但是,當我將List <>更改爲ObservableCollection <>時,對代碼中值的更改立即反映在複選框上 - 但反之亦然。但這至少是一個開始。 – 2010-01-17 22:57:01

+0

看到我的評論上面,CheckBox-> MyCollection在.NET3.5,但不是.NET4 – 2010-01-17 23:47:12

1

將您的List<bool?>更改爲ObservableCollection<bool?>。 List不會引發WPF需要更新UI的更改通知。一個ObservableCollection可以。這將處理列表條目發生更改並且CheckBox需要相應更新的情況。

在另一個方向上,即使使用List<bool?>也適用於我 - 即切換複選框可修改集合中的值。你的綁定語法當然是正確的。

+0

感謝您的迴應。更改爲ObservableCollection確實會導致在代碼中更改值時更新UI。但奇怪的是,其他方向與剩下的我的代碼保持不變。 – 2010-01-17 23:20:11

+0

查看我的評論,上面的CheckBox-> MyCollection在.NET3.5中工作,但不在.NET4中 – 2010-01-17 23:43:52

相關問題