简体   繁体   English

在WPF中将控件绑定到集合/数组中的单个值

[英]Bind a control to a single value in a collection/array in WPF

In WPF I have a collection of bool? 在WPF中,我有一个bool集合吗? values and I want to bind each of these to a separate checkbox programmatically. 值,我想以编程方式将这些值绑定到单独的复选框。 I want the bindings to be TwoWay so that changing the value of the individual item in the collection in code updates the check box and vice versa. 我希望绑定是TwoWay,以便在代码中更改集合中单个项目的值会更新复选框,反之亦然。

I have spent ages trying to figure out how to do this and I am completely stuck. 我花了很长时间试图弄清楚该如何做,但我完全陷于困境。 With the following code the checkbox only gets the right value when the window is loaded and that's it. 使用以下代码,仅在加载窗口时复选框才获得正确的值,仅此而已。 Changing the check box doesn't even update the value in the collection. 更改复选框甚至不会更新集合中的值。 (UPDATE: this appears to be a bug in .NET4 as the collection does get updated in an identical .NET3.5 project. UPDATE: Microsoft have confirmed the bug and that it will be fixed in the .NET4 release.) (更新:这似乎是.NET4中的错误,因为该集合确实在相同的.NET3.5项目中得到了更新。更新:Microsoft已经确认该错误,并将在.NET4版本中修复。)

Many thanks in advance for your help! 在此先感谢您的帮助!

C#: 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: XAML:

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

There are a few things that need changing here to get this to work. 为了使此功能正常工作,需要在此处进行一些更改。 Firstly you'll need to wrap your boolean value in an object that implements the INotifyPropertyChanged interface in order to get the change notification that you are looking for. 首先,您需要将布尔值包装在实现INotifyPropertyChanged接口的对象中,以便获取您要查找的更改通知。 Currently you are binding to boolean values in your collection which do not implement the interface. 当前,您正在绑定到不实现该接口的集合中的布尔值。 To do this you could create a wrapper class like so : 为此,您可以创建一个包装器类,如下所示:

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

    }

You'll then want to create these objects in your form instead of a list of booleans. 然后,您将要在表单中创建这些对象,而不是布尔列表。 You may also want to use an observable collection instead of a list so that notification of items being added and removed are sent. 您可能还希望使用可观察的集合而不是列表,以便发送有关添加和删除的项目的通知。 This is shown below: 如下所示:

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

The next thing to do is to display a list of check boxes in your ui. 下一步是在用户界面中显示复选框列表。 To do this WPF provides itemscontrols. 为此,WPF提供了项控件。 ListBox is an itemscontrol so we can use this as a starting point. ListBox是一个项控件,因此我们可以以此为起点。 Set the itemssource of a listbox to be MyCollection. 将列表框的itemssource设置为MyCollection。 We then need to define how each Wrapper object is going to be displayed in the list box and this can be done with a datatemplate which is created in the windows resources. 然后,我们需要定义如何在列表框中显示每个包装器对象,这可以通过在Windows资源中创建的数据模板来完成。 This is shown below : 如下所示:

<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>

This should get you up and running with a simple demo of checkboxes that have values bound to a list of booleans. 这将使您启动并运行一个复选框的简单演示,该复选框具有绑定到布尔值列表的值。

What makes you think it's not working? 是什么让您认为它不起作用? It's working for me :) 它为我工作:)

Here's my test XAML: 这是我的测试XAML:

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

Here's my code behind: 这是我的代码背后:

private void Button_Click(object sender, RoutedEventArgs e)
{

}

(the rest is the same as yours) (其余与您相同)

I placed a breakpoint on Button_Click and checked MyCollection[0] it was updated according to the IsChecked value of the CheckBox . 我在Button_Click上放置了一个断点,并检查了MyCollection[0]它已根据CheckBoxIsChecked值进行了更新。

Try changing your collection type from List<bool?> to ObservableCollection<bool?> perhaps that is the reason you think it's not working for you (the fact that changes to the collection are not reflected anywhere else in your view). 尝试将集合类型从List<bool?>更改为ObservableCollection<bool?>也许这就是您认为它对您不起作用的原因(对集合所做的更改未在视图中的其他任何地方反映出来)。

Change your List<bool?> to an ObservableCollection<bool?> . 将您的List<bool?>更改为ObservableCollection<bool?> A List does not raise the change notifications that WPF needs to update the UI. 列表不会引发WPF更新UI所需的更改通知。 An ObservableCollection does. 一个ObservableCollection做。 This handles the case where the list entry is changed and the CheckBox needs to update accordingly. 这可以处理更改列表条目并且CheckBox需要相应更新的情况。

In the other direction, it works for me even with a List<bool?> -- ie toggling the checkbox modifies the value in the collection. 另一方面,即使使用List<bool?> ,它也对我List<bool?> -即,切换复选框会修改集合中的值。 Your binding syntax is certainly correct. 您的绑定语法肯定是正确的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM