Самый простой способ привязать список флажков к списку отмеченных значений
У меня есть список 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
не поддерживает привязку.
Любые идеи?
Ответы
Ответ 1
Я нашел решение моей проблемы.
Я изменил свой 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
.
У меня был такой шаблон во многих местах моего приложения, что это идеальное решение для меня, потому что теперь мне просто нужно указать одно прикрепленное свойство, а остальное все обрабатывается привязками данных, и я не нужен какой-либо дополнительный код.
Ответ 2
Я честно создаю список объектов, содержащих как строку, так и логическое значение, указывающее, проверено ли оно.
С небольшим 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 является истинным, чтобы получить выбранные элементы, если вам нужно.
Кроме того, если ItemsToGenerate может стать большим, вы должны создать HashSet значений и использовать его в запросе, который должен сделать его быстрее, если потребуется.