Wpf – Disable a WPF button, but still swallow the click events

wpf

I have a button in my application which is bound to a command. This button sits inside another control which also reacts to mouseclicks. When the button is enabled I get the behaviour that I expect – click on the button and the command is triggered, click outside the button but inside the container control and that is triggered instead.

Unfortunately when the button is disabled (through the CanExecute method of the command) the clicks on the button are bubbled up to the container control. I don't want this, I want the clicks to be swallowed – neither trigger the command nor bubble up.

I tried to overcome this by created a new class inheriting from Button but none of the following methods even seem to get called on a disabled button:

  • OnPreviewMouseDown
  • OnPreviewMouseUp
  • OnPreviewMouseLeftButtonDown
  • OnPreviewMouseLeftButtonUp
  • OnMouseDown
  • OnMouseUp
  • OnMouseLeftButtonDown
  • OnMouseLeftButtonUp
  • OnClick

Is a disabled control completely ignored by the WPF routed event system? And if so is there anyway that I can get the behaviour that I'm looking for?

Best Answer

RCGoforth's answer got me 90% of the way there, but the solution isn't to put a rectangle behind the button, because the bubbling event goes up the tree not across to siblings. In the end I surrounded the button with a ContentControl (since rectangle's can't have children) which swallowed the event before it could go up any further:

<ContentControl MouseDown="ContentControl_MouseDown">
    <Button Content="Click Test"
            Padding="2"
            Command="{Binding TestCommand}"/>
</ContentControl>

In the code behind:

private void ContentControl_MouseDown(object sender, MouseButtonEventArgs e)
{
    e.Handled = true;
}

Or to do this entirely in XAML (and to increase the hack level of the code...)

<Button>
    <Button.Template>
        <ControlTemplate>
            <Button Content="Click Test"
                    Command="{Binding TestCommand}"/>
        </ControlTemplate>
    </Button.Template>
</Button>