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.
Related
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.
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>
When i press Tab or shift+tab key the message show, But I to want show this message only when I press tab key not shift+tab key.
How to define this event only when i press Tab key using previewkeydown event in Wpf C# ?
private void txtH_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Tab)
{
MessageBox.Show("Tab");
}
}
You could perform a check like
if ((!e.KeyboardDevice.IsKeyDown(Key.LeftShift))
&& (!e.KeyboardDevice.IsKeyDown(Key.RightShift))
&& e.KeyboardDevice.IsKeyDown(Key.Tab))
Or you can do a check like
if (!(e.KeyboardDevice.Modifiers == ModifierKeys.Shift)
&& e.KeyboardDevice.IsKeyDown(Key.Tab))
WPF is not best used in an event-driven fashion like Winforms. It's best when you use the MVVM pattern in conjunction with Commands to separate out presentation and business logic concerns - this is where WPF is most powerful.
When doing so you can then define InputBinding derived XAML elements in your XAML files for your View and specify a Command to run using the Command attribute which is in your ViewModel.
e.g.
<KeyBinding Command="{Binding ShowMessageCommand}" Key="Tab" />
<KeyBinding Command="{Binding ShowMessageCommand}" Modifiers="Shift" Key="Tab" />
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.
I currently have a listbox in wpf c# and added some keybindings to the keydown event handler of my main window. It's event handlers for the spacebar and the up/down keys. However, when my listbox has focus, these bindings are not initiated. How can I disable these default keybindings (without entering a e.handle = true so the entire keystroke is disabled) for this control and run my own code?
The default keybindings do not use events directly but commands. What you can do is to define commands and attach events to them.
<Window.Resources>
<CommandBinding x:Key="NewBinding" Command="ApplicationCommands.New"
Executed="NewCommand" CanExecute="CanExecuteNew">
</CommandBinding>
</Window.Resources>
<ListBox.CommandBindings>
<StaticResource ResourceKey="NewBinding"></StaticResource>
</ListBox.CommandBindings>
To override default keybindings the syntax is :
<Window.InputBindings>
<KeyBinding Key="" Modifiers="" Command="" />
</Window.InputBindings>
If you are new to this try to get some overview WPF Commanding Overview and Advanced WPF you are going to have hard time to do so with events.