简体   繁体   English

如何绑定ObservableCollection <bool> 到WPF中的复选框列表框

[英]How to bind an ObservableCollection<bool> to a Listbox of Checkboxes in WPF

Let me prefix this question by stating that I'm very new to both C# and WPF. 让我用这个问题作为前缀,说明我对C#和WPF都很新。

I'm trying to connect a collection of Boolean values to a container containing 6 checkboxes, and have the state of these values stored when a button is pressed. 我正在尝试将一组Boolean值连接到一个包含6个复选框的容器,并在按下按钮时存储这些值的状态。 I'm assuming there is an easy way to do this, since binding checkboxes to a collection of seems a very natural thing to do, but all the solutions I have seen so far have seemed overly complicated (example: http://merill.net/2009/10/wpf-checked-listbox/ ). 我假设有一种简单的方法可以做到这一点,因为绑定到一个集合的复选框似乎是很自然的事情,但到目前为止我看到的所有解决方案似乎都过于复杂(例如: http:// merill。 net / 2009/10 / wpf-checked-listbox / )。

I create the checkboxes by modifying the data template of a ListBox and set the ItemsSource of the ListBox to the ObservableCollection , but my problem is that I don't know what to bind the IsChecked to, since I'm trying to bind it to the actual object in the collection and not a property of the object. 我通过修改数据模板创建的复选框, ListBox和设置ItemsSource中的ListBoxObservableCollection ,但我的问题是,我不知道该怎么绑定IsChecked来,因为我试图将其绑定到集合中的实际对象,而不是对象的属性。

Use IsChecked="{Binding}" to bind the item of the collection directly. 使用IsChecked="{Binding}"直接绑定集合的项目。

<ListBox ItemsSource="{Binding MyBooleanCollection}" >
    <ListBox.ItemTemplate>
        <DataTemplate>
            <CheckBox IsChecked="{Binding Mode=OneWay}"/>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

However it is not possible to do bind to source with this method. 但是,使用此方法无法绑定到源。 Because the binding on the IsChecked property of the CheckBox doesn't the index of the item of the binding. 因为CheckBoxIsChecked属性上的绑定不是绑定项的索引。 So, it can't change the collection but only the item of the collection. 因此,它不能更改集合,只能更改集合的项目。

Update 更新

To get around that limitation, you can create a wrapper to the Boolean value: 要绕过该限制,您可以创建布尔值的包装器:

public class Wrapper<T> : INotifyPropertyChanged
{
    private T value;
    public T Value
    {
        get { return value; }
        set
        {
            {
                this.value = value;
                OnPropertyChanged();
            }
        }
    }

    public static implicit operator Wrapper<T>(T value)
    {
        return new Wrapper<T> { value = value };
    }
    public static implicit operator T(Wrapper<T> wrapper)
    {
        return wrapper.value;
    }

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

Here is an exemple of usage: 这是一个例子:

public partial class MainWindow : Window
{
    public ObservableCollection<Wrapper<bool>> MyBooleanCollection { get; private set; }

    public MainWindow()
    {
        InitializeComponent();

        DataContext = this;
        MyBooleanCollection = new ObservableCollection<Wrapper<bool>>() { false, true, true, false, true };
    }
}

And in the XAML: 而在XAML中:

<CheckBox IsChecked="{Binding Value}"/>

In the ItemTemplate you may write ItemTemplate你可以写

<CheckBox IsChecked="{Binding Path=.}"/>

or 要么

<CheckBox IsChecked="{Binding Mode=OwnWay}"/>

which binds directly to the item object, ie the bool value from the collection. 它直接绑定到item对象,即集合中的bool值。


Note however that in either case the bound values in the collection will not be replaced when a CheckBox is checked or unchecked. 但请注意,在任何一种情况下,选中或取消选中CheckBox时,不会替换集合中的绑定值。 In order to immediately update the collection when a CheckBox is clicked, your collection would have to contain objects with a boolean property to which IsChecked is bound. 为了在单击CheckBox时立即更新集合,您的集合必须包含具有与IsChecked绑定的布尔属性的对象。

In your case this could be as simple as the following (as your question sounds like you don't need property change notifications): 在您的情况下,这可能就像下面一样简单(因为您的问题听起来像您不需要属性更改通知):

public class BooleanHelper
{
    public bool Value { get; set; }
}

The binding would now look like this: 绑定现在看起来像这样:

<CheckBox IsChecked="{Binding Path=Value}"/>

The collection would now be an ObservableCollection<BooleanHelper> and you would perhaps add items like this: 该集合现在将是一个ObservableCollection<BooleanHelper> ,您可能会添加如下项目:

Items.Add(new BooleanHelper { Value = true });

By the link that you provided, you could also use INotifyPropertyChanged extension to your CheckedListItem class, but thats if you dont want use ObservableCollection. 通过您提供的链接,您还可以对CheckedListItem类使用INotifyPropertyChanged扩展,但如果您不想使用ObservableCollection。 It would be something like this: 它会是这样的:

public class CheckedListItem : INotifyPropertyChanged
{
    private int _Id;
    public int Id 
    {
        get;
        set; NotifyIfAnythingChanged("Id");
    }

    private string _Name;
    public string Name
    {
        get;
        set; NotifyIfAnythingChanged("Name");
    }

    private bool _IsChecked;
    public bool IsChecked
    {
        get;
        set; NotifyIfAnythingChanged("IsChecked");
    }

    private void NotifyIfAnythingChanged(String propName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propName));
    }
    public event PropertyChangedEventHandler PropertyChanged;
}

Your listbox should be something like this: 你的列表框应该是这样的:

<ListBox x:Name="MyListBox">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <CheckBox Content={Binding Path=Name} IsChecked="{Binding Mode=TwoWay, Path=IsChecked}"/>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

In your code behind you should initialize the ObservableCollection just once, because every change made into it will result into an UI update. 在您的代码中,您应该只初始化ObservableCollection一次,因为对其进行的每个更改都将导致UI更新。

ObservableCollection<CheckedListItem> MyList = new ObservableCollection<CheckedListItem>();
MyListBox.ItemsSource = MyList;

Now every change made into MyList, such as Add(), Remove(), Etc. Will affect your UI. 现在,对MyList进行的每个更改,例如Add(),Remove()等都将影响您的UI。

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

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