Какой самый простой способ привязать список флажков к списку проверенных значений - PullRequest
11 голосов
/ 23 апреля 2009

У меня есть список 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 ]

13 голосов
/ 24 апреля 2009

Я нашел решение своей проблемы.

Я изменил свой 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.

У меня был такой шаблон во многих местах моего приложения, что это идеальное решение для меня, потому что теперь мне просто нужно указать одно прикрепленное свойство, а все остальное обрабатывается привязками данных, а я нет нужен дополнительный код.

9 голосов
/ 23 апреля 2009

Честно говоря, я бы создал список объектов, содержащих как строку, так и логическое значение, указывающее, отмечен ли он.

С помощью небольшого Linq вы можете сгенерировать свой список объектов и связать его с itemSource вместо привязки списка строк.

В конце будет проще, особенно если вам действительно нужно что-то обновить, если пользователю разрешено ставить / снимать флажки.

== обновление ==

в ответ на комментарий я расскажу об этом, потому что я не уверен, что понимаю, в чем будет проблема: при условии, что у нас есть полный список (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 значений и использовать его в запросе, который должен сделать его быстрее, если это необходимо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...