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

后端 未结 2 623
旧巷少年郎
旧巷少年郎 2021-02-14 06:50

I have a list of AvailableItems that I want to display as a list of checkboxes, so that users can pick which items to generate, which are then stored in another lis

相关标签:
2条回答
  • 2021-02-14 07:16

    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.

    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):

    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:

    <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.

    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.

    0 讨论(0)
  • 2021-02-14 07:30

    I've found a solution to my problem.

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

    <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 ListBoxItem to a checkbox and binding each Checkbox.IsChecked to ListBoxItem.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.

    0 讨论(0)
提交回复
热议问题