0

The idea is almost the same as in How to hide items of a combobox in WPF.

In my ComboBox, I am showing multiple items, and I need to be able to hide irrelevant/incompatible items from the ComboBox when an external flag is set (in my case it is a boolean Checkbox with name ShowAllItems).

My ComboBox is bound to a list of items of a type which is "aware" of their compatibility status (a field named IsSupported). I just need to hide/show these items depending on whether the Checkbox is ticked or not.

A naïve approach would probably be adding/removing items from the list each time a Checkbox's status is changed.
Another (also probably naïve approach) would be to add a new field to the items of the list IsVisible, and then update this field each time a Checkbox's status is changed.

To summarize, my filter would depend on an item's IsSupported field and on the Checkbox's ShowAllItems field.

The ComboBox:

<ComboBox ItemsSource="{Binding MyItemsList, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" SelectedItem="{Binding MySelectedItem, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
    <ComboBox.ItemContainerStyle>
        <Style TargetType="ComboBoxItem" BasedOn="{StaticResource {x:Type ComboBoxItem}}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding IsSupported}" Value="False">
                    <Setter Property="Visibility" Value="Collapsed"></Setter>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </ComboBox.ItemContainerStyle>
</ComboBox>

and the Checkbox:

<CheckBox IsChecked="{Binding ShowAllItems, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Content="Show all items"/>
Semi
  • 93
  • 7
  • 1
    use `MultiDataTrigger` – ASh Jan 04 '22 at 14:02
  • But how can I bind the boolean property of the Checkbox "ShowAllItems" to the DataTrigger of the Combobox? They live in different scopes? I would need something like Binding="{Binding PARENT.ShowAllItems}"? – Semi Jan 04 '22 at 14:06
  • 1
    https://stackoverflow.com/questions/17186985/wpf-binding-to-parent-itemscontrol-from-inside-of-child-itemscontrol-data-templa. use RelativeSource: `{RelativeSource AncestorType=ComboBox}` (and note DataContext in binding path) – ASh Jan 04 '22 at 14:13
  • It works, perfect! Would also be interested in reason behind why both `AncestorType=ComboBox` and `AncestorType={x:Type ItemsControl}` work. It seems ambiguous but it still works fine. – Semi Jan 04 '22 at 14:55
  • 1
    very simple reason: ComboBox class inherits ItemsControl, so both types can be used in this situation – ASh Jan 04 '22 at 15:09

1 Answers1

0
<ComboBox IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding MyItemsList, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" SelectedItem="{Binding MySelectedItem, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
    <ComboBox.ItemContainerStyle>
        <Style TargetType="ComboBoxItem" BasedOn="{StaticResource {x:Type ComboBoxItem}}">
            <Style.Triggers>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition Binding="{Binding IsSupported}" Value="False" />
                        <Condition Binding="{Binding Path=DataContext.ShowAllItems, RelativeSource={RelativeSource AncestorType=ComboBox}}" Value="False" />
                    </MultiDataTrigger.Conditions>
                    <MultiDataTrigger.Setters>
                        <Setter Property="Visibility" Value="Collapsed" />
                        <Setter Property="IsEnabled" Value="False" />
                    </MultiDataTrigger.Setters>
                </MultiDataTrigger>
            </Style.Triggers>
        </Style>
    </ComboBox.ItemContainerStyle>
</ComboBox>

Thanks to @ASh for pointing out that I need to use MultiDataTrigger, and how to bind the Checkbox's ShowAllItems property (which lives in a different scope).

Also note that IsEnabled setter needs to be used to prevent user from selecting the item through usage of keyboard arrows up/down as well as mouse scroll wheel.

Semi
  • 93
  • 7