将复选框列表绑定到已检查值列表的最简单方法是什么

时间:2009-04-23 18:36:44

标签: wpf binding

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

显示包含相应复选框的所有可用项目很简单:

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

但是现在我需要将每个Checkbox.IsChecked属性绑定到项目位于ItemsToGenerate列表中的事实。我想过像这样ListContainmentToBoolConverter

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

但这不起作用,因为我错过了ConverterParameter来传递每个项目的值,但我不能这样做,因为ConverterParameter不支持绑定。

有什么想法吗?

2 个答案:

答案 0 :(得分:13)

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

我已将ItemsControl更改为ListBox,并使用here描述的技术在SelectedItems与我的ItemsToGenerate集合之间添加了绑定。它基本上允许我使用简单的附加属性将任何自定义集合同步到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>

我仍然可以按照我最初的需要(复选框列表)显示此内容,方法是添加一个数据模板,将每个ListBoxItem更改为一个复选框,并将每个Checkbox.IsChecked绑定到{{1 }}

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

答案 1 :(得分:9)

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

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

最后会更简单,特别是如果你真的需要更新某些东西,如果允许用户选中/取消选中复选框。

== update ==

在回答评论时,我对此有所了解,因为我不确定我理解实际问题是什么:只要我们有完整列表(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();

然后,您可以通过将_Items公开为名为Items:

的属性来绑定您的列表
<ItemsControl ItemsSource="{Binding Path=Items}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <CheckBox Content="{Binding Name}" IsChecked="{Binding IsSelected}" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>    
</ItemsControl>

您可以稍后从_Items中选择IsSelected为true,以便在需要时获取所选项目。

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