sebhaub sebhaub - 1 month ago 16
C# Question

ToggleButtonAutomationPeer Toggle() does not execute command

I am trying to automate a ToggleButton. For this I am using the ToggleButtonAutomationPeer as you can see in the listing.
The Problem is, that the command of the button is not executed when using the

Toggle()
method of the AutomationPeer.

The ToggleButton in XAML

<ToggleButton Name="mToggle" Command="{Binding SomeCommand}"></ToggleButton>


The code used to automate the ToggleButton

var peer = new ToggleButtonAutomationPeer(mToggle);
var toggleProvider = peer.GetPattern(PatternInterface.Toggle) as IToggleProvider;
if (toggleProvider != null) toggleProvider.Toggle();


The only way i found to execute the command of the ToggleButton was using this line of code

mToggle.Command.Execute(null);


Does someone maybe know the reason or a better way of doing this?

Thanks in advance

Edit



Based on the answer of Vladimir Perevalov i derived the
ToggleButtonAutomationPeer
class and also implemented the
IInvokeProvider
.
Since the
OnClick()
method seems to be protected i am using Reflection to get the method and invoke it.
I am not really comfortable with using Reflection... am i missing a better way here?

class MyToggleButtonAutomationPeer : ToggleButtonAutomationPeer, IInvokeProvider
{
public MyToggleButtonAutomationPeer(ToggleButton owner)
: base(owner)
{}

public override object GetPattern(PatternInterface patternInterface)
{
return patternInterface == PatternInterface.Invoke ? this : base.GetPattern(patternInterface);
}

public void Invoke()
{
var dynMethod = Owner.GetType().GetMethod("OnClick", BindingFlags.NonPublic | BindingFlags.Instance);
dynMethod.Invoke(Owner, null);
}
}


Anyway a big thanks so far :)

Answer

This seems to be a bug in implementation. I looked through the sources of ToggleButton and its base - ButtonBase. It looks like when you call automation peer it is the same as to call ToggleButton.IsChecked (this also does not invoke the command). The command is only invoked when you do click the ToggleButton. Since it will

  1. Change the IsChecked property
  2. Call the base.OnClick. Which is the ButtonBase.OnClick and which will call the command.

I tried to use

peer.GetPattern(PatternInterface.Invoke) as IInvokeProvider

But this does not work also, since IInvokeProvider is implemented by ButtonAutomationPeer, not ButtonBaseAutomationPeer which is base for ToggleButtonAutomationPeer.

So in my opinion, you should implement your own automation peer for ToggleButton, which in its Toggle method should call OnClick instead of OnToggle and everything should work. Or you can subclass ToggleButtonAutomationPeer and additionally implement IInvokeProvider and call OnClick in its Invoke method.

Comments