0

Trying to set up a WPF ComboBox; some of its items should not be selectable, so I'm binding IsEnabled to some property of the underlying item.

At the same time, I need to define an ItemTemplate that contains e.g. a Button. This button needs to be clickable, even if the item is not selectable (worth nothing a click on the button should not select the item as such of course; it will trigger a command performing some background actions, which will eventually make the underlying item selectable)

However, when ComboBoxItem.IsEnabled = false, it seems even the button automatically gets disabled.

Brief example:

    <ComboBox ItemsSource="{Binding Items}">
        <ComboBox.ItemContainerStyle>
            <Style TargetType="{x:Type ComboBoxItem}">
                <Setter Property="IsEnabled" Value="{Binding CanSelectItem}"/>
            </Style>
        </ComboBox.ItemContainerStyle>

        <ComboBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding Name}"/>

                    <!-- This button isn't clickable when ComboBoxItem.IsEnabled = false .. but it should be! -->
                    <Button Content="Click me" Command="{Binding SomeCmd}"/>
                </StackPanel>
            </DataTemplate>
        </ComboBox.ItemTemplate>
    </ComboBox>

Is there any way to circumvent this? E.g., set some items as non-selectable, however define a button in the ItemTemplate that remains clickable regardless?

Thanks

Mighty Badaboom
  • 6,067
  • 5
  • 34
  • 51
Bogey
  • 4,926
  • 4
  • 32
  • 57
  • 3
    Setting the ComboBoxItem as disabled will disable _all_ of its content. Maybe instead of disabling just cancel the `SelectionChanged` event when suitable? – nondestructive Aug 23 '17 at 11:41

2 Answers2

1

When you remove the ComboBox.ItemContainerStyle you can set the IsEnabled property of each element in the DataTemplate

<ComboBox.ItemTemplate>
    <DataTemplate>
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="{Binding Name}"
                       IsEnabled="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.IsEnabled}"/>
            <Button Content="Click me" Command="{Binding SomeCmd}"/>
        </StackPanel>
    </DataTemplate>
</ComboBox.ItemTemplate>

The combobox item will still be enabled but the TextBlock will be disabled. The binding is just an example. Depends on where your IsEnabled property is. In my example the property is in the viewmodel which is DataContext of your Window.

Mighty Badaboom
  • 6,067
  • 5
  • 34
  • 51
  • 1
    Won't this allow for the item to be selected (regardless of the `TextBlock`'s status as disabled)? I can't test right now, thanks. – nondestructive Aug 23 '17 at 11:51
  • @nondestructive Damn, yes...good point. As far as I know there is no other way to enable the button; as you mentioned in the other comment. – Mighty Badaboom Aug 23 '17 at 11:53
  • Well, your answer could still be useful if that event suggestion is viable. You'd still want the text to be (or at least look) disabled. – nondestructive Aug 23 '17 at 11:57
  • @nondestructive Yes, that's why I did not deleted the answer. Maybe it still does what the questioneer wants. – Mighty Badaboom Aug 23 '17 at 11:59
  • Thanks to both of you! Have the (probably useless) habit of trying to avoid codebehind in the view where possible, but seeing this seems to be the best - or only - way in this case, will go for the ideas you suggested. Thanks – Bogey Aug 23 '17 at 12:06
  • @Bogey Glad to help. I'd argue that avoiding code-behind in views is a problem only when it becomes counter-productive (i.e. you end up spending more time/resources in figuring out how to avoid it than on _actually_ solving the problem). – nondestructive Aug 23 '17 at 12:46
  • True - probably just a bad habit on my end. Have played around with the solution a bit, it works well but does allow to "fake select" disabled items (e.g. clicking on them will close the combobox), also think the SelectedItem will actually change for a brief moment before canceling. Looking at a second way (posted below) by using a custom button with custom IsEnabled-behavior; not quite sure yet which one is going to be the better way – Bogey Aug 23 '17 at 14:39
0

For future reference, have found another way of doing this, based on this answer:

WPF override IsEnabled from Parent

So basically creating a class derived from button that overrides the default IsEnabled behavior.

Benefit is that this seems to do exactly what I was looking for, but it does change one of WPF's pretty.. default behaviors, so might need to be taken with a bit of care

Bogey
  • 4,926
  • 4
  • 32
  • 57