KeyBinding not working when switching Windows - c#

My MainWindow has some KeyBindings:
<Window.InputBindings>
<KeyBinding Command="{Binding NewFileCommand}" Key="{Binding NewFileCommand.Key}" Modifiers="{Binding NewFileCommand.Modifiers}" />
</Window.InputBindings>
They´re working, as long as i clicked somewhere into the content of my Window. But if I use Alt+Tab to switch between Applications (let´s say MS Word and my App) the Shortcuts won´t work anymore until I click again somewhere into the View. Same when selecting the Application-Window via Mouse on the Border.
How can I make them working?

In my repro, I used the RelayCommand from MVVM Light which worked fine. I'm guessing that you are using something else. Try adding this code in your window:
private void Window_Activated(object sender, EventArgs e)
{
System.Windows.Input.CommandManager.InvalidateRequerySuggested();
}
That tells the command framework that something has changed and it should re-evaluate the CanExecute status of each command.

Related

How to do loose coupling of button pressed and released events in Xamarin.Forms with Prism?

For my current project I need to capture button pressed and release events in Xamarin.Forms. But I want to keep things loosely coupled using Prism.
At first I used the Command property of the , like so:
<Button x:Name="ButtonForward" Command="{Binding MoveUpCommand}" />
But the Command property only fires when the button is released. To make seperate pressed and released actions I used the events in XAML:
<Button x:Name="ButtonForward" Pressed="ButtonForward_Pressed" Released="ButtonMove_Released"/>
And called the Commands manually in the event handlers in code behind:
private void ButtonMove_Released(object sender, System.EventArgs e)
{
var vm = BindingContext as DirectControlViewModel;
if (vm.MoveStopCommand.CanExecute(null))
vm.MoveStopCommand.Execute(null);
}
private void ButtonForward_Pressed(object sender, System.EventArgs e)
{
var vm = BindingContext as DirectControlViewModel;
if (vm.MoveUpCommand.CanExecute(null))
vm.MoveUpCommand.Execute(null);
}
The problem is that it isn't loosely coupled anymore, since the View now has to know its ViewModel.
Is there a way to have a button that does have seperate commands for pressed and released events, keeping the View and ViewModel loosely coupled? Any help would be appreciated.
Use the EventToCommandBehavior on the Button. This will allow you take advantage of any Event on anything you're working with and Execute a Command when the event is fired.
<Button>
<Button.Behaviors>
<prism:EventToCommandBehavior EventName="Pressed"
Command="{Binding PressedCommand}" />
<prism:EventToCommandBehavior EventName="Released"
Command="{Binding ReleasedCommand}" />
</Button.Behaviors>
</Button>
Note there are additional properties that you can utilize if you have some sort of Parameter that you would like to pass the Command which may be a property in the EventArgs, or something else entirely that you'd like to bind to or specify.

Is using command binding or event handler a better approach to implement Close, Minimize and Maximize Buttons in WPF?

I am making the close, maximize and minimize buttons in WPF C#. I tried two different methods and both seemed to work with me but I just want to know which approach in general is considered a better practice for this kind of implementation.
Method one:
in XAML:
<Window.CommandBindings>
<CommandBinding Command="{x:Static SystemCommands.CloseWindowCommand}" CanExecute="CommandBinding_CanExecute_1" Executed="CommandBinding_Executed_1" />
<CommandBinding ... />
<CommandBinding ... />
</Window.CommandBindings>
<Button Command="{x:Static SystemCommands.CloseWindowCommand}" Content ="close"/>
<Button ... />
<Button .../>
in C#:
private void CommandBinding_Executed_1(object sender, ExecutedRoutedEventArgs e)
{
SystemCommands.CloseWindow(this);
}
...
Method two:
in XAML:
<Button Content="X" Click="CloseButton_Click" />
<Button .../>
<Button ... />
in C#:
private void CloseButton_Click(object sender, RoutedEventArgs e)
{
Close();
}
...
Since the close, maximize and minimize buttons are typically part of a control, or a template of a control, you could handle the Click event of the buttons directly. There is no need nor reason to introduce any command bindings just to be able to handle the click of a Button internally in a control.
You could either hook up the event handlers in XAML or, if the buttons are defined in a ControlTemplate of a custom control, you could override the OnApplyTemplate() method of the control and hook up the event handlers programmatically as suggested here: https://blog.magnusmontin.net/2013/03/16/how-to-create-a-custom-window-in-wpf/.
Button click handler is simple and fast (to implement). If you are sure you are going to use just this button to close your window - click handler is good enough. If however there is possibility you are going to need more than one place to close the window (for example - you are going to use "close" menu option) - then it's better to not spread the same logic over multiple places and use a command, because command has all handling logic in one place (CommandBinding_Executed_1 in your case). Also, command has CanExecute logic so you will be able to automatically disable your close button (and all other "close" controls) in case window cannot be closed right now (with click handler you will have to code this logic yourself). Also, with command you can close your window from any control down the tree, even if that control has no reference to your window at all. This applies to "command vs click handler" in general, not specifically to the case with closing window where some of the above might seem a bit contrieved.

Using Keyboard as input for XAML and C# Calculator

I am creating a calculator using Visual Studio (C# and XAML). I want to be able to type the numbers and operation to do the calculation. without having to click on the result screen (Just like the windows default calculator). How can I achieve that? I am creating the calculator with MVVM concepts just as exercise to learn MVVM.
You will want to use a KeyBinding in your XAML and bind a command to the key.
<Window.InputBindings>
<KeyBinding Key="D1"
Command="AddOneToEntryCommand" />
<KeyBinding Key="Add"
Command="AddCommand" />
<KeyBinding Key="Subtract"
Command="SubtractCommand" />
<!-- Add bindings for all the keys and handle the logic in your commands -->
</Window.InputBindings>
You could simply use the KeyUp event to capture the keys the user entered.
Add it to your xaml window:
KeyUp="Window_KeyUp"
private void Window_KeyUp(object sender, KeyEventArgs e)
{
string str= e.Key.ToString();
//do whateveer you want with that.
}
Goodluck.

How to track WPF commands?

In a WPF application, I want to have a User Tracking System to keep statistics on the way users are using the application. In other words, I'm looking for a way to track what commands are being executed and how they have been triggered by the user (by clicking on the toolbar button, by using keyboard shortcuts, etc). So far, I haven't found a nice way to do this while using the WPF command pattern...
Do you have ideas/suggestions on how to achieve/design something like this without overriding every control used in the application?
For discussion purposes, I created a very basic WPF application containing a toolbar with a single Save button, a TextBox and a ListBox. I also added a KeyBinding to trigger the Save command when pressing CTRL+S.
The first challenge is to determine which device (mouse or keyboard) was used to trigger the command.
The second challenge is to determine what is the control used to trigger the command (the command source). I'm not interested to know which control had keyboard focus when the command was triggered, I would like to know what control was used to trigger the command (usually it's a button, an hyperlink, a MenuItem from a ContextMenu, etc.)
MainWindow.xaml
<Window x:Class="TrackingCommands.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" x:Name="Me" Height="480" Width="600">
<Window.CommandBindings>
<CommandBinding Command="Save" Executed="OnSaveCommandExecuted" CanExecute="OnSaveCommandCanExecute" />
</Window.CommandBindings>
<Window.InputBindings>
<KeyBinding Command="Save" Gesture="CTRL+S"/>
</Window.InputBindings>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<ToolBarTray Grid.Row="0">
<ToolBar>
<Button Command="Save" Content="Save"/>
</ToolBar>
</ToolBarTray>
<TextBox Grid.Row="1" TextWrapping="Wrap" AcceptsReturn="True"/>
</Grid>
</Window>
MainWindow.xaml.cs
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
}
private void OnSaveCommandExecuted(object sender, ExecutedRoutedEventArgs e)
{
e.Handled = true;
}
private void OnSaveCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
e.Handled = true;
}
}
EDIT
I realized my original question was a bit vague, I apologize. I will try to give more information and ask a more precise question.
I know it is simple enough to store a list of commands that have been executed. The challenge here is to retrieve which device was used to trigger the command initially: mouse or keyboard?
By putting the tracking logic in the "executed" handler, there is no way at this point to determine if the user triggered the command by clicking a button with the mouse, by pressing Enter on the button or if he used a keyboard shortcut. In my example, the same command can be triggered by clicking the toolbar button or by pressing CTRL+S on keyboard. How can I track these separate actions that will all trigger the same command?
Can this be achieve in the ViewModel layer? When we reach the command handler, it's already too late: we have lost this information. The only place we really know the device used is in the View itself. How to pass this information to the Command handler? Is the only way to do this is to override the Button control to intercept Click and KeyDown events in order to provide additional context to the command handler?
If you use the MVVM pattern then the Command would be bound from the View to a Command instance in the View Model. You could use create an ICommand implementation that provided an event when it was executed with some details about itself. Maybe use a command provider/factory/whatever to create each command and wire it up to a logger/tracker.
Create a Singleton or static class that has a Stack<ICommand> property and pass a reference to this class to your Windows (or preferably view models). You should of course encapsulate the Stack object using some typical AddCommand and RemoveCommand methods. Then, whenever an ICommand is called, Push it into the Stack.
However, you'll either need to define your ICommands in separate classes, or preferably use a form of the RelayCommand found online. Here's an example:
private ActionCommand deleteCommand = new ActionCommand(action => DeleteCommand(AudioTrack),
canExecute => CanDelete(AudioTrack));
public override ICommand Delete
{
get { return deleteCommand; }
}
private void DeleteCommand(AudioTrack audioTrack)
{
// Do work then add to Stack in CommandManager
CommandManager.AddCommand(deleteCommand);
}
private bool CanDelete(AudioTrack audioTrack)
{
return audioTrack != null;
}
I'm not exactly sure what your second question means, because the ICommands are set as the value to the Command property of the relevant control, so you should already know what controls they are, eg.:
<MenuItem Header="Delete track" Command="{Binding Delete}"
CommandParameter="{Binding Release.ThinDiscs.CurrentItem}">
<MenuItem.Icon>
<Image Source="pack://application:,,,/App;component/Images/Delete.png" />
</MenuItem.Icon>
</MenuItem>

Having multiple Controls using the same CommandBinding in WPF?

In my Window, there are several controls which perform the same action.
For example I have a MenuItem
<MenuItem x:Name="_mnuNew" Command="New" Header="_New" InputGestureText="Ctrl+N"/>
and a Button
<Button x:Name="_btnNew" Command="New"/>
performing the "New" Command
<Window.CommandBindings>
<CommandBinding Command="New" CanExecute="IsNewExecuteable" Executed="NewExecute" />
</Window.CommandBindings>
The assignment works as desired for the MenuItem. Setting the Command for the Button results in a NullReferenceException
I've read here that Command Bindings do also work on Buttons, so what am I doing wrong.
EDIT:
private void IsNewExecuteable(object sender, System.Windows.Input.CanExecuteRoutedEventArgs e)
{
e.CanExecute = IsRunning; //IsRunning is a siple property that is tested and works
}
The whole CommandBinding Part was fine but there was a mistake inside of IsNewExecuteable, in which I trusted and which was obviously wrong.
Excuse me for Posting this question, everytime I am using a technique new to me I don't see obvious misstakes.
Anyway thanks a lot to those who helped

Categories