Silverlight: Simulate RadioButton Click event using UI Automation? - c#

In Silverlight, both the Button and the RadioButton controls have a Click event, since they inherit from System.Windows.Controls.Primitives.ButtonBase.
If we want to simulate this Click event for a Button, we can use the ButtonAutomationPeer class, like so (given a button called myButton):
ButtonAutomationPeer peer = new ButtonAutomationPeer(myButton);
IInvokeProvider ip = (IInvokeProvider)peer;
ip.Invoke();
However, when we try to do the same thing for a RadioButton, we discover that the RadioButtonAutomationPeer class does not implement IInvokeProvider (so we can't call Invoke()). Is there some other way we can cause the Click event for a RadioButton to be fired?

Try this:
RadioButtonAutomationPeer peer = new RadioButtonAutomationPeer(myRadioButton);
IToggleProvider tp = (IToggleProvider) peer;
while (tp.ToggleState != targetToggleState)
{
tp.Toggle();
}
You'll need to know your desired toggle state (On, Off, or Indeterminate). Or if you just want to toggle to a different state, strike the while loop just call Toggle.
Obviously this isn't the exact same thing as a click. If you've bound the radio button to a command, you might be forced to be a little more explicit and do something like this to get your automation to work:
<RadioButton ... (don't set the Command property)>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Checked">
<i:InvokeCommandAction Command="{Binding MyCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</RadioButton>
Using the Blend SDK (that's the "i:" xmlns), you're invoking a command when the RadioButton is checked. Personally I'd do that approach even without automation over just binding a command to a RadioButton: it's not clear when the command executes with a binding, but the triggers add some clarity and remove the need for me to think the next time I look at the code.

Related

Is it possible to close a window without firing the activated event?

I'm quit looking for a while and can't find a solution for this supposed easy task. I am using two events via event triggers, the 'Activated' and the 'Closed' event.
I'm using the 'Activated' event to update my Window, but I don't want it be fired when I close the application from the taskbar. Any ideas?
My program contains the following eventtrigger in the XAML-Code:
<i:Interaction.Triggers>
<i:EventTrigger EventName="Activated" >
<i:InvokeCommandAction Command="{Binding WindowActivated}" />
</i:EventTrigger>
<i:EventTrigger EventName="Closing">
<i:InvokeCommandAction Command="{Binding ClosingCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
To my knowledge this isn't possible. And it's got nothing to do with WPF or MVVM, it's how Windows handles this itself. When you right-click on the taskbar you force the focus away from your application, so you'll get a deactivate event. Selecting close from the pop-up menu causes windows to send a WM_SYSCOMMAND/SC_CLOSE but it has to activate your window first, and there's no way at the application level to know the future intention of the system thread that's initiating this action.
As I see it you have 2 choices. The first is to use a DispatcherTimer to add a small delay between the Activate and the update of your window, long enough for the subsequent close message to arrive.
The second is to do your update in a CompositionTarget.Rendering event handler. This event is triggered even when the application doesn't have focus (seomthing you may want to track yourself if you don't want background updates), but the SC_CLOSE event that follows the WM_ACTIVATE event should occur fast enough for it to arrive before the next CompositionTarget.Rendering event, at which point you know your application is closing and can therefore ignore all subsequent updates.

WPF MVVM event to command - invoke command based on event args

I have a WPF app which uses DevExpress controls and MVVM with PRISM.
I'm using DockLayoutManager's 'DockOperationCompleted' event to invoke a command on my view model like this:
<dxd:DockLayoutManager x:Name="dockContainer">
<i:Interaction.Triggers>
<i:EventTrigger EventName="DockOperationCompleted">
<i:InvokeCommandAction Command="{Binding DataContext.SaveLayoutCommand, ElementName=dockContainer}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<dxd:LayoutGroup/>
</dxd:DockLayoutManager>
The purpose of the 'SaveLayoutCommand' command is to save the layout so it can be restored later in time.
The 'DockOperationCompleted' event is raised after a DockItem gets docked or closed (there are other cases but they are irrelevant).
The problem is that when I close the main window, the dock items in my DockLayoutManager are getting closed one by one and thus 'SaveLayoutCommand' gets invoked for every closed dock item and I don't want this to happen.
The 'DockOperationCompletedEventArgs' with which the event gets raised has a 'DockOperation' property which I can check agains, but I'm not sure where exactly should this code fit in.
What I am trying to achieve is that the command should be invoked only in one case - when the item is docked
My question is : is there a way to 'filter' when the command gets invoked based on the event's event args?
Thanks :)
In addition to aKzenTs answer I want to point out that with DevExpress its rather easy to pass the event args to a command.
You should use EventToCommand from their MVVM library (PassEventArgsToCommand-Property). If you want to keep your viewmodel clean of DevExpress you can additionally use a Converter to transform the event args to an arbitrary object.
<dxmvvm:Interaction.Triggers>
<dxmvvm:EventToCommand Command="{Binding YOURCOMMAND}"
EventName="THEEVENT"
EventArgsConverter="{StaticResource YOUREVENTARGSCONVERTER}"
PassEventArgsToCommand="true" />
</dxmvvm:Interaction.Triggers>
There is no builtin way to filter the events that are raised before invoking an action. You can however implement your own custom trigger action that does the filtering.
Unfortunately it's also not easy to access the event args and passing them to the command. See this question as a reference:
MVVM Passing EventArgs As Command Parameter

XAML - InputBindings prevent MouseLeftButtonDown-Events being fired

I have a class derived from ItemsControl in which I implement my own selection-algorithm which uses the MouseLeftButtonDown to change the selection.
Now I needed a specific control to handle Mouseclicks in the ViewModel, so I wrote the following:
<controls:DraggableItemsContainer bla="blub">
<controls:DraggableItemsContainer.InputBindings>
<MouseBinding Gesture="LeftClick" Command="{Binding DeselectSubGroupsCommand}" />
</controls:DraggableItemsContainer.InputBindings>
</controls:DraggableItemsContainer>
What happens now is, that I don't get the MouseLeftButtonDown-event anymore - which is comprehensable because the command "e.handles" the click.
But in this case, that's not what I want. Is there a way to fire the event anyway?
PS: Yes I need to do the selection in the MouseLeftButtonDown-event and not in any Preview-event
Two options:
You can have your custom ItemsControl hook PreviewMouseDown instead of MouseDown.
You can continue to hook MouseDown, but do it by calling AddHandler, and pass true for the handledEventsToo parameter.
If it's important that you get notified after the MouseBinding has done its work, then you need to use AddHandler. If you're okay with getting the message first, PreviewMouseDown is simpler.
I think your issue is that you try to catch the same event, on the same control, using two different approaches.
Try this:
<Grid>
<Grid.InputBindings>
<MouseBinding Gesture="LeftClick" Command="{Binding DeselectSubGroupsCommand}" />
</Grid.InputBindings>
<controls:DraggableItemsContainer bla="blub">
.....
</controls:DraggableItemsContainer>
</Grid>
Make sure that in your control you have e.Handled = false.
This should allow for your internal logic to run, and then execute the command. If you need it in the opposite order..... I don't know.

Handling keyboard press in WPF

I am only beginning to learn MVVM and its use in WPF.
I am using it to build a very simple Calculator application (like the Windows built in calculator).
One thing i've noticed, is that binding my view (XAML) to commands does not let me configure WHEN these actual commands are fired.
For example, a Button control fires the command bound to it when it is clicked.
I would like to achieve the same effect when the numpad buttons are presed ('1' will fire the Command of the "1" Button control, and so on).
I could not find 1 way to do this, all sites seem to show multiple other options which don't seem valid in this case.
Should this be set up in the Control's (Button) level or on the entire window? How can i do this ?
Try to set input bindings of your main window.
<Window.InputBindings>
<KeyBinding Key="D1" Command="{Binding Command1}" />
<KeyBinding Key="NumPad1" Command="{Binding Command1}" />
</Window.InputBindings>

Attach command with parameter to KeyUp event

I am currently transforming a medium size WPF project to MVVM and I ran into a problem that I wasn't able to solve, yet. Maybe you could help me out?
The target framework is .NET 3.5.1.
I have a list view that gets its items from the underlying view model. That view model is exposing a command to remove the selected items from the list view. Therefore the command parameter is bound to the SelectedItems property of the list view.
<ListView ItemsSource="{Binding MyItems}"
x:Name="MyListView"
SelectionMode="Extended">
</ListView>
<Button x:Name="MyRemoveButton"
Content="Remove item"
Command="{Binding RemoveItemCommand}"
CommandParameter="{Binding ElementName=MyListView, Path=SelectedItems}">
My intention is to execute this command not only when pressing a button, but also when the KeyUp event is fired on the list view and the pressed key is "delete".
I was close to finding the solution when I stumbled upon interaction triggers in this example:
http://joyfulwpf.blogspot.com/2009/05/mvvm-invoking-command-on-attached-event.html?showComment=1250325648481#c3867495357686026904
Now the problem with this demo is that the command parameter is the pressed key, but in my case I need the command parameter to be the SelectedItems property and I need the command to execute only on a specific key.
Is there any way to do this without much overhead and in the MVVM way?
Something like this would be awesome:
<i:Interaction.Triggers>
<i:EventTrigger EventName="KeyUp">
<local:CommandAction Command="{Binding RemoveItemCommand}"
CommandParameter={Binding ElementName=MyListView, Path=SelectedItems}
EventArgument="Key.Delete"/>
</i:EventTrigger>
</i:Interaction.Triggers>
To do it in the MVVM way you need to bind "SelectedItems" property of the ListView to your ViewModel, so you could use it from your commands and wouldn't need to pass it via CommandParameter.
How strict is your separation requirement? If you don't have designers using Blend, then put a call to a ViewModel method into the KeyUp or PreviewKeyUp event handler in your code-behind.

Categories

Resources