代码之家  ›  专栏  ›  技术社区  ›  Anthony Brien

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

  •  11
  • Anthony Brien  · 技术社区  · 15 年前

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

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

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

    但现在,我需要将每个checkbox.ischecked属性绑定到项在 产生世代的 名单。我想做一个 ListContainmentToBoolConverter 这样地:

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

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

    有什么想法吗?

    2 回复  |  直到 15 年前
        1
  •  13
  •   Anthony Brien    15 年前

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

    我改变了自己 ItemsControl 到A ListBox ,并在selecteditems与我的 ItemsToGenerate 使用所述技术收集 here . 它基本上允许我将任何自定义集合同步到 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 ListBoxItem.IsSelected .

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

        2
  •  9
  •   Denis Troller    15 年前

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

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

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

    =更新=

    作为对评论的回答,我之所以接受这一点,是因为我不确定我是否理解实际的问题是什么:如果我们有完整的列表(可用项)和选定项的列表(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的属性:

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

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

    另外,如果itemstogenerate可以变大,您应该创建一个值的哈希集并在查询中使用它,如果需要的话,这会使它更快。