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

Wpf 将复选框列表绑定到选中值列表的最简单方法是什么,wpf,binding,Wpf,Binding,我有一个可用项列表,我想将其显示为复选框列表,以便用户可以选择要生成的项,然后这些项存储在另一个名为ItemsToGenerate的列表中。我的列表实际上只是字符串列表 使用相应的复选框显示所有可用项目很容易: <ItemsControl ItemsSource="{Binding Path=AvailableItems}"> <ItemsControl.ItemTemplate> <DataTemplate>

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

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

<ItemsControl ItemsSource="{Binding Path=AvailableItems}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <CheckBox Content="{Binding}" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>    
</ItemsControl>
但这不起作用,因为我缺少一个ConverterParameter来传递每个项的值,但我不能这样做,因为ConverterParameter不支持绑定


有什么想法吗?

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

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

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

==更新==

作为对评论的回答,我对此的看法是因为我不确定我是否理解实际问题是什么:如果我们有完整的可用项目列表和要生成的选定项目列表:

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

然后,通过将_Items作为名为Items的属性公开,可以像这样绑定列表:

<ItemsControl ItemsSource="{Binding Path=Items}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <CheckBox Content="{Binding Name}" IsChecked="{Binding IsSelected}" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>    
</ItemsControl>
如果需要,您可以稍后从IsSelected为true的_Items中选择以获取所选项目


另外,若ItemsToGenerate可以变大,那个么您应该创建一个值的HashSet并在查询中使用它,若需要的话,这会使查询速度更快。

我已经找到了解决问题的方法

我已将ItemsControl更改为ListBox,并使用所述技术在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绑定到ListBoxItem.IsSelected,我仍然能够显示这一点,因为我最初需要一个复选框列表


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

我不想这样做的原因是因为我的数据被保存为xml,有时还需要手工编辑。因此,如果有300个项目可用,并且他们只想生成2个项目,我希望他们只编写Item1Item2。我想到了另一种方法:使用一个列表框,其中项目模板将checkbox.IsChecked绑定到ListItem.IsSelected。那么,这将只是一个将ItemsSource绑定到AvailableItems并将SelectedItems绑定到ItemsToGenerate的问题。不过,您使用linq的方法似乎可以满足我的要求,所以我将尝试一下。但是如果我知道它不是绑定,我就必须使用Linq手动更新ItemsToGenerate。我希望它尽可能简单的原因是,我有很多地方可以使用这种模式:选择要编译的目标、要使用的语言、要生成的世界、要运行的任务等等。我希望最小化数据格式,但是在UI中显示所有可用的选项。如果你想实现你最初的想法,你可以使用带有多值转换器的多绑定。它将不接受任何参数并绑定到item和ItemsToGenerate集合。我尝试创建一个多值转换器,将第一个值绑定到item,将第二个值绑定到list ItemsToGenerate,如果item在not列表中,我将正确返回true或false。但是我怎样才能转换回来呢?convert-back方法只接收一个bool。我缺少列表和项目值,因此我可以将项目添加/删除到列表中。我想查看附加属性的实现。不幸的是,这仅在重用列表框中的选择时有效,但如果在模板中使用带有复选框的ItemsControl会怎么样?我尝试了这一点,最终结果看起来有点怪怪的。我个人将坚持使用一个普通的列表框。
<ItemsControl ItemsSource="{Binding Path=Items}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <CheckBox Content="{Binding Name}" IsChecked="{Binding IsSelected}" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>    
</ItemsControl>
<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>