wpf 将复选框列表绑定到选中值列表的最简单方法是什么

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/782980/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 20:16:46  来源:igfitidea点击:

What's the simplest way to bind a list of checkboxes to a list of checked values

wpfbinding

提问by Anthony Brien

I have a list of AvailableItemsthat I want to display as a list of checkboxes, so that users can pick which items to generate, which are then stored in another list called ItemsToGenerate(my lists are actually just lists of strings).

我有一个AvailableItems我想显示为复选框列表的列表,以便用户可以选择要生成的项目,然后将其存储在另一个名为的ItemsToGenerate列表中(我的列表实际上只是字符串列表)。

Showing all available items with corresponding checkboxes is easy:

显示带有相应复选框的所有可用项目很容易:

<ItemsControl ItemsSource="{Binding Path=AvailableItems}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <CheckBox Content="{Binding}" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>    
</ItemsControl>

But now I need to bind each Checkbox.IsChecked property, to the fact that the item is in the ItemsToGeneratelist. I thought of making a ListContainmentToBoolConverterlike this:

但是现在我需要将每个 Checkbox.IsChecked 属性绑定到该项目在ItemsToGenerate列表中的事实。我想制作一个ListContainmentToBoolConverter这样的:

IsChecked="{Binding Path=ItemsToGenerate, 
            Converter={StaticResource ListContainmentToBoolConverter}}"

But that doesn't work because I'm missing a ConverterParameterto pass the value of each item, but I can't do that, because ConverterParameterdoes not support binding.

但这不起作用,因为我缺少ConverterParameter传递每个项目的值的一个,但我不能这样做,因为ConverterParameter不支持绑定。

Any ideas?

有任何想法吗?

回答by Anthony Brien

I've found a solution to my problem.

我找到了解决我的问题的方法。

I've changed my ItemsControlto a ListBox, and added a binding between the SelectedItems with my ItemsToGeneratecollection using the technique described here. It basically allows me to synchronize any custom collection to ListBox.SelectedItemsusing a simple attached property.

我已将 my 更改ItemsControl为 a ListBox,并ItemsToGenerate使用此处描述的技术在 SelectedItems 与我的集合之间添加了一个绑定。它基本上允许我ListBox.SelectedItems使用简单的附加属性来同步任何自定义集合。

<ListBox ItemsSource="{Binding AvailableItems}"
         Behaviors:MultiSelectorBehaviours.SynchronizedSelectedItems=
             "{Binding ItemsToGenerate}"
         SelectionMode="Multiple"
         Background="{x:Null}">  
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <WrapPanel />                    
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <CheckBox Content="{Binding}"
                      Margin="3"
                      IsChecked="{Binding RelativeSource=
                           {RelativeSource Mode=FindAncestor,
                            AncestorType={x:Type ListBoxItem}},
                           Path=IsSelected}" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ListBox>

I'm still able to display this as I initially wanted (a list of checkboxes), by adding a data template to change each ListBoxItemto a checkbox and binding each Checkbox.IsCheckedto ListBoxItem.IsSelected.

通过添加数据模板以将每个更改ListBoxItem为一个复选框并将每个绑定Checkbox.IsCheckedListBoxItem.IsSelected.

I had this pattern in so many places in my application that this is the ideal solution for me, because now I just need to specify one attached property, and the rest is all handled by the data bindings, and I don't need any additional code.

我在应用程序的很多地方都有这种模式,这对我来说是理想的解决方案,因为现在我只需要指定一个附加属性,其余的都由数据绑定处理,我不需要任何额外的代码。

回答by Denis Troller

I honestly would create a list of objects containing both the string and a boolean indicating if it is checked.

老实说,我会创建一个包含字符串和布尔值的对象列表,指示它是否被选中。

With a little Linq you can generate your list of objects and bind it to itemSource instead of binding the list of strings.

使用一点 Linq,您可以生成对象列表并将其绑定到 itemSource 而不是绑定字符串列表。

It will be simpler in the end, especially if you actually need to update something if the user is allowed to check/uncheck the checkboxes.

最后它会更简单,特别是如果允许用户选中/取消选中复选框,您实际上需要更新某些内容。

== update ==

== 更新 ==

in answer to the comment, my take on this because I'm not sure I understand what the actual problem would be: provided we have the full list (AvailableItems) and the list of selected items (ItemsToGenerate):

在回答评论时,我对此的看法是因为我不确定我理解实际问题是什么:前提是我们有完整列表 (AvailableItems) 和选定项目列表 (ItemsToGenerate):

public class ItemEntry
{
  public string Name { get; set; }
  public bool IsSelected {get; set; }
}

...

...

_Items = from item in AvailableItems
            select new ItemEntry() { 
                    Name = item, 
                    IsSelected = ItemsToGenerate.contains(item)
                  }).ToList();

You can then bind your list like so, by exposing _Items as a property named Items:

然后,您可以像这样绑定您的列表,方法是将 _Items 公开为名为 Items 的属性:

<ItemsControl ItemsSource="{Binding Path=Items}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <CheckBox Content="{Binding Name}" IsChecked="{Binding IsSelected}" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>    
</ItemsControl>

You can at a later time select from _Items where IsSelected is true to get the selected items if you need to.

如果需要,您可以稍后从 _Items 中选择,其中 IsSelected 为 true 以获取所选项目。

Also, if ItemsToGenerate can get big, you should create a HashSet of the values and use it in the query, that should make it faster if need be.

此外,如果 ItemsToGenerate 可以变大,您应该创建一个值的 HashSet 并在查询中使用它,如果需要,这应该使它更快。