2010-01-17 302 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

相关问题