question

AA-5973 avatar image
0 Votes"
AA-5973 asked DaisyTian-1203 commented

c# keyboard input in WPF DataGrid

Hey,

I am doing a simple calculator as an exercise and I am quite new in c#.

How to input keyboard?
maybe I need just numbers and =-+ and ENTER
if its letter I would like it to be "Error"

Code XALM:

 <Window x:Class="Calculator.MainWindow"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
         xmlns:local="clr-namespace:Calculator"
         mc:Ignorable="d"
         Title="MainWindow" Height="500" Width="300">
     <Grid Margin="8">
         <Grid.ColumnDefinitions>
             <ColumnDefinition/>
             <ColumnDefinition/>
             <ColumnDefinition/>
             <ColumnDefinition/>
         </Grid.ColumnDefinitions>
         <Grid.RowDefinitions>
             <RowDefinition Height="1.5*"/>
             <RowDefinition/>
             <RowDefinition/>
             <RowDefinition/>
             <RowDefinition/>
             <RowDefinition/>
         </Grid.RowDefinitions>
         <Label x:Name="result" Content="0" Grid.ColumnSpan="4" HorizontalAlignment="Right" 
                VerticalAlignment="Bottom" FontSize="50"/>
         <Button Content="AC" Margin="2" Grid.Column="0" Grid.Row="1"
                 FontWeight="bold" Click="OperationButton_Click"/>
         <Button Content="+/-" Margin="2" Grid.Column="1" Grid.Row="1"
                 FontWeight="bold" Click="OperationButton_Click"/>
         <Button Content="%" Margin="2" Grid.Column="2" Grid.Row="1"
                 FontWeight="bold" Click="OperationButton_Click"/>
         <Button Content="÷" Margin="2" Grid.Column="3" Grid.Row="1"
                 FontWeight="bold" Click="OperationButton_Click"/>
    
         <Button Content="7" Margin="2" Grid.Column="0" Grid.Row="2"
                 FontSize="20" Click="NumberButton_Click"/>
         <Button Content="8" Margin="2" Grid.Column="1" Grid.Row="2"
                 FontSize="20" Click="NumberButton_Click"/>
         <Button Content="9" Margin="2" Grid.Column="2" Grid.Row="2"
                 FontSize="20" Click="NumberButton_Click"/>
         <Button Content="×" Margin="2" Grid.Column="3" Grid.Row="2"
                 FontWeight="bold" Click="OperationButton_Click"/>
    
         <Button Content="4" Margin="2" Grid.Column="0" Grid.Row="3"
                 FontSize="20" Click="NumberButton_Click"/>
         <Button Content="5" Margin="2" Grid.Column="1" Grid.Row="3"
                 FontSize="20" Click="NumberButton_Click"/>
         <Button Content="6" Margin="2" Grid.Column="2" Grid.Row="3"
                 FontSize="20" Click="NumberButton_Click"/>
         <Button Content="-" Margin="2" Grid.Column="3" Grid.Row="3"
                 FontWeight="bold" Click="OperationButton_Click"/>
    
         <Button Content="1" Margin="2" Grid.Column="0" Grid.Row="4"
                 FontSize="20" Click="NumberButton_Click"/>
         <Button Content="2" Margin="2" Grid.Column="1" Grid.Row="4"
                 FontSize="20" Click="NumberButton_Click"/>
         <Button Content="3" Margin="2" Grid.Column="2" Grid.Row="4"
                 FontSize="20" Click="NumberButton_Click"/>
         <Button Content="+" Margin="2" Grid.Column="3" Grid.Row="4"
                 FontWeight="bold" Click="OperationButton_Click"/>
    
         <Button Content="0" Margin="2" Grid.Column="0" Grid.Row="5" 
                 FontSize="20" Grid.ColumnSpan="2" Click="NumberButton_Click"/>
         <Button x:Name="dec" Content="" Margin="2" Grid.Column="2" Grid.Row="5"
                 FontWeight="bold" Click="OperationButton_Click"/>
         <Button Content="=" Margin="2" Grid.Column="3" Grid.Row="5"
                 FontWeight="bold" Click="OperationButton_Click"/>
     </Grid>
 </Window>

code c#:

 using System;
 using System.Globalization;
 using System.Windows;
 using System.Windows.Controls;
    
 namespace Calculator
 {
     /// <summary>
     /// Interaction logic for MainWindow.xaml
     /// </summary>
     public partial class MainWindow : Window
     {
         double firstNumber, secondNumber, resultNumber = 0;
         bool calcDone = false;
         Operations operation = Operations.None;
         string separator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;
    
         public MainWindow()
         {
             InitializeComponent();
    
             //Assign to the decimal button the separator from the current culture
             dec.Content = separator;
         }
    
         //List the possible numeric operations
         private enum Operations
         {
             None,
             Division,
             Multiplication,
             Subtraction,
             Sum
         }
    
         //Manage number buttons input
         private void NumberButton_Click(object sender, RoutedEventArgs e)
         {
             Button button = (Button)sender;
    
             if (calcDone) //calculation already done
             {
                 result.Content = $"{button.Content}";
                 calcDone = false;
             }
             else //calculation not yet done
             {
                 if (result.Content.ToString() == "0")
                 {
                     result.Content = $"{button.Content}";
                 }
                 else
                 {
                     result.Content = $"{result.Content}{button.Content}";
                 }
             }
    
         }
    
         //Manage operation buttons input
         private void OperationButton_Click(object sender, RoutedEventArgs e)
         {
             Button button = (Button)sender;
    
             //Evaluate button pressed
             switch (button.Content.ToString())
             {
                 case "AC":
                     result.Content = "0";
                     break;
                 case "+/-":
                     if (!(result.Content.ToString() == "0"))
                     {
                         result.Content = Convert.ToDouble(result.Content) * -1;
                     }
                     break;
                 case "%":
                     if (!(result.Content.ToString() == "0"))
                     {
                         result.Content = Convert.ToDouble(result.Content) / 100;
                     }
                     break;
                 case "÷":
                     firstNumber = Convert.ToDouble(result.Content);
                     operation = Operations.Division;
                     result.Content = "0";
                     break;
                 case "×":
                     firstNumber = Convert.ToDouble(result.Content);
                     operation = Operations.Multiplication;
                     result.Content = "0";
                     break;
                 case "-":
                     firstNumber = Convert.ToDouble(result.Content);
                     operation = Operations.Subtraction;
                     result.Content = "0";
                     break;
                 case "+":
                     firstNumber = Convert.ToDouble(result.Content);
                     operation = Operations.Sum;
                     result.Content = "0";
                     break;
                 case "=":
                     switch (operation)
                     {
                         case Operations.Division:
                             if (calcDone)
                             {
                                 if (!(result.Content.ToString() == "ERROR"))
                                 {
                                     result.Content = Convert.ToDouble(result.Content) / secondNumber;
                                 }
                             }
                             else
                             {
                                 //Check if division by 0
                                 if (result.Content.ToString() == "0")
                                 {
                                     result.Content = "ERROR";
                                     calcDone = true;
                                 }
                                 else
                                 {
                                     secondNumber = Convert.ToDouble(result.Content);
                                     resultNumber = firstNumber / secondNumber;
                                     result.Content = resultNumber;
                                     calcDone = true;
                                 }
                             }
                             break;
                         case Operations.Multiplication:
                             if (calcDone)
                             {
                                 result.Content = Convert.ToDouble(result.Content) * secondNumber;
                             }
                             else
                             {
                                 secondNumber = Convert.ToDouble(result.Content);
                                 resultNumber = firstNumber * secondNumber;
                                 result.Content = resultNumber;
                                 calcDone = true;
                             }
                             break;
                         case Operations.Subtraction:
                             if (calcDone)
                             {
                                 result.Content = Convert.ToDouble(result.Content) - secondNumber;
                             }
                             else
                             {
                                 secondNumber = Convert.ToDouble(result.Content);
                                 resultNumber = firstNumber - secondNumber;
                                 result.Content = resultNumber;
                                 calcDone = true;
                             }
                             break;
                         case Operations.Sum:
                             if (calcDone)
                             {
                                 result.Content = Convert.ToDouble(result.Content) + secondNumber;
                             }
                             else
                             {
                                 secondNumber = Convert.ToDouble(result.Content);
                                 MessageBox.Show($"{firstNumber} + {secondNumber}");
                                 resultNumber = firstNumber + secondNumber;
                                 result.Content = resultNumber;
                                 calcDone = true;
                             }
                             break;
                     }
                     break;
                 default:
                     if (!result.Content.ToString().Contains(separator))
                     {
                         result.Content = $"{result.Content}{button.Content}";
                     }
                     break;
             }
         }
     }
 }

So what should I do?

Thanks!

Best regards,
AA



dotnet-csharpwindows-wpf
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

SimpleSamples avatar image
0 Votes"
SimpleSamples answered AA-5973 edited

It is not clear to me what you mean by input keyboard. There are two possible meanings.

You can choose one character within the Content attribute to be used as the AccessKey, as described in #838 – Using a Label’s Access Key to Give Focus to Another Control. So in other words if you change (for the relevant button) Content="1" to Content="_1" then when the "1" key is pressed then that will work the exact same way as if the "1" button is pressed.

If you do that then you normally would have a separate event handler for each button. For your form here you have NumberButton_Click as the event handler for every number. You could create a separate event handler for each number but if you want you can modify NumberButton_Click so that it can determine which number was pressed, as in the following:

 private void NumberButton_Click(object sender, RoutedEventArgs e)
 {
     Button button = (Button)sender;

     string s = button.Content.ToString();
     if (s.Length != 2)
         {
             System.Diagnostics.Debug.WriteLine($"NumberButton content is not valid");
             return;
         }

     if (calcDone) //calculation already done
     {
         result.Content = s[1];
         calcDone = false;
     }
     else //calculation not yet done
     {
         if (result.Content.ToString() == "0")
         {
             result.Content = s[1];
         }
         else
         {
             result.Content = result.Content.ToString() + s[1];
         }
     }

 }

That is if the Content is in the format "_n" where n is a number. You can use the similar code for OperationButton_Click. For the AC button you need to choose one character, either A or C, to be used as the access key. I am not sure what the "+/-" button is for but you will need to choose one character to be used as the access key for it. If it is for toggling the number between positive and negative then I am not sure what to do; the Windows Calculator accessory has such a button and as best as I can tell it cannot be used from the keyboard.

Another possibility requires the understanding of focus. Unless a key is specified for use as an accelerator or (as in the preceding) an access key, Windows normally sends keyboard input to the control with focus. So you need a text box that has the focus to get keyboard input. I am sure there have been times when you type something into an application and nothing happens until you click something like a text box. When you do you are setting the text box as the control with the focus. You might not need to use a text box for that if everything can be done using access keys but note that the Windows Calculator accessory has such a text box.











· 8
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Thank you very much for your answer!

But I tried to do "if you change (for the relevant button) Content="1" to Content="_1"".
When I type e.g. 5, I get 5. When I type further it will be smth like this: 5_-_3_= .

  1. I do not know how to delete that extra "_" before and after each number or symbol.

  2. I do not know how to do buttons "enter", "AC" and comma.

It would be great If you can help me a little bit more :)

Sincerely,
AA



0 Votes 0 ·

I was not sure what the question was so I did not provide all details. Now that you have clarified what you want I have provided more in my response. Note that you must put the underscore before the relevant character (key), as in Content="_1". And you seem to be processing the keyboard in a manner that is unnecessary for the solution I posted.

0 Votes 0 ·

My question is: How to add the keyboard to the calculator program?
So if you click on your keyboard "1" you will have clicked it in the program.
The same way I am typing right now. I click on the letters and have them in the textbox. Yeah?

I put the underscore before the relevant character as in Content="_1". But it gave me 5_-_3_=

0 Votes 0 ·

Great you are here to help me! I am really such a noob.

Firstly I have changed my code this way:
Step 1. I added public string AccessKey { get; set; } after /// <summary> /// Interaction logic for MainWindow.xaml /// </summary>
Step 2. I have changed for relevant buttoms e.g. Content="1" to Content="_1".

What should I change/add now?

Should I undo step 2? And then modify private void NumberButton_Click(object sender, RoutedEventArgs e) by adding those lines of code you have provided? Where exactly?

Thank you for your time and consideration!

Best regards,
AA





0 Votes 0 ·

First let me say that I mistakenly thought you are using VB.Net. I do not know why; I will change the code to C#.

0 Votes 0 ·

OMG
Thank you!!

One more stupid question: How to use a similar code for OperationButton_Click? I mean what should I add and what keep?

Best regards,
AA



0 Votes 0 ·
Show more comments
DaisyTian-1203 avatar image
0 Votes"
DaisyTian-1203 answered DaisyTian-1203 commented

I update your Xaml like below to implement what you want:

 <Window x:Class="Calculator.MainWindow"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
         xmlns:local="clr-namespace:Calculator"
         mc:Ignorable="d"
         Title="MainWindow" Height="450" Width="800" PreviewKeyDown="Window_KeyDownPreview">
     <Grid Margin="8">
         <Grid.ColumnDefinitions>
             <ColumnDefinition/>
             <ColumnDefinition/>
             <ColumnDefinition/>
             <ColumnDefinition/>
         </Grid.ColumnDefinitions>
         <Grid.RowDefinitions>
             <RowDefinition Height="1.5*"/>
             <RowDefinition/>
             <RowDefinition/>
             <RowDefinition/>
             <RowDefinition/>
             <RowDefinition/>
         </Grid.RowDefinitions>
         <Label x:Name="result" Content="0" Grid.ColumnSpan="4" HorizontalAlignment="Right"   VerticalAlignment="Bottom" FontSize="50"/>
         <Button x:Name="Clear" Content="AC" Margin="2" Grid.Column="0" Grid.Row="1" FontWeight="bold" Click="OperationButton_Click"/>
         <Button x:Name="Plus_Minus" Content="+/-" Margin="2" Grid.Column="1" Grid.Row="1" FontWeight="bold" Click="OperationButton_Click"/>
         <Button x:Name="Percent" Content="%" Margin="2" Grid.Column="2" Grid.Row="1" FontWeight="bold" Click="OperationButton_Click"/>
         <Button x:Name="Divide" Content="÷" Margin="2" Grid.Column="3" Grid.Row="1" FontWeight="bold" Click="OperationButton_Click"/>
                    
         <Button x:Name="Seven" Content="7" Margin="2" Grid.Column="0" Grid.Row="2" FontSize="20" Click="NumberButton_Click"/>
         <Button x:Name="Eight" Content="8" Margin="2" Grid.Column="1" Grid.Row="2" FontSize="20" Click="NumberButton_Click"/>
         <Button x:Name="Nine" Content="9" Margin="2" Grid.Column="2" Grid.Row="2" FontSize="20" Click="NumberButton_Click"/>
         <Button x:Name="Multiply" Content="×" Margin="2" Grid.Column="3" Grid.Row="2" FontWeight="bold" Click="OperationButton_Click"/>
                     
         <Button x:Name="Four" Content="4" Margin="2" Grid.Column="0" Grid.Row="3" FontSize="20" Click="NumberButton_Click"/>
         <Button x:Name="Five" Content="5" Margin="2" Grid.Column="1" Grid.Row="3" FontSize="20" Click="NumberButton_Click"/>
         <Button x:Name="Six" Content="6" Margin="2" Grid.Column="2" Grid.Row="3" FontSize="20" Click="NumberButton_Click"/>
         <Button x:Name="Minus" Content="-" Margin="2" Grid.Column="3" Grid.Row="3" FontWeight="bold" Click="OperationButton_Click"/>
    
         <Button x:Name="One"  Content="1" Margin="2" Grid.Column="0" Grid.Row="4" FontSize="20" Click="NumberButton_Click"/>
         <Button x:Name="Two" Content="2" Margin="2" Grid.Column="1" Grid.Row="4" FontSize="20" Click="NumberButton_Click"/>
         <Button x:Name="Three" Content="3" Margin="2" Grid.Column="2" Grid.Row="4" FontSize="20" Click="NumberButton_Click"/>
         <Button x:Name="Plus" Content="+" Margin="2" Grid.Column="3" Grid.Row="4" FontWeight="bold" Click="OperationButton_Click"/>
    
         <Button x:Name="Zero" Content="0" Margin="2" Grid.Column="0" Grid.Row="5" FontSize="20" Grid.ColumnSpan="2" Click="NumberButton_Click"/>
         <Button x:Name="dec" Content="" Margin="2" Grid.Column="2" Grid.Row="5" FontWeight="bold" Click="OperationButton_Click"/>
         <Button x:Name="Equals" Content="=" Margin="2" Grid.Column="3" Grid.Row="5" FontWeight="bold" Click="OperationButton_Click"/>
     </Grid>
 </Window>

And add Window_KeyDownPreview to your c# code:

   private void Window_KeyDownPreview(object sender, KeyEventArgs e)
         {
             switch (e.Key)
             {
                 case Key.NumPad0:
                     Zero.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
                     break;
                 case Key.NumPad1:
                     One.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
                     break;
                 case Key.NumPad2:
                     Two.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
                     break;
                 case Key.NumPad3:
                     Three.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
                     break;
                 case Key.NumPad4:
                     Four.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
                     break;
                 case Key.NumPad5:
                     Five.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
                     break;
                 case Key.NumPad6:
                     Six.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
                     break;
                 case Key.NumPad7:
                     Seven.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
                     break;
                 case Key.NumPad8:
                     Eight.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
                     break;
                 case Key.NumPad9:
                     Nine.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
                     break;
                 case Key.Decimal:
                     dec.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
                     break;
                 case Key.Add:
                     Plus.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
                     break;
                 case Key.Subtract:
                     Minus.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
                     break;
                 case Key.Multiply:
                     Multiply.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
                     break;
                 case Key.Divide:
                     Divide.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
                     break;
                 case Key.Enter:
                     Equals.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
                     break;
             }
         }

If the response is helpful, please click "Accept Answer" and upvote it.
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

· 12
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Hey,

Thank you for your time.

Right now I have this code (see below) but it is not working.
Maybe I wrote smth wrong.

XALM same as you wrote, added nothing extra.

C# is the same as initially. Plus added your code Window_KeyDownPreview after public MainWindow()
Maybe Window_KeyDownPreview should be not there.

Best regards,
AA





0 Votes 0 ·

Note that that is not an object-oriented solution and that is why I did not suggest such a thing.

0 Votes 0 ·

So what should i do?

0 Votes 0 ·

@AA-5973
Did you add PreviewKeyDown="Window_KeyDownPreview" to your xaml code like the line 8 in my first part code?

0 Votes 0 ·

Yes, i did it

0 Votes 0 ·
Show more comments
karenpayneoregon avatar image
0 Votes"
karenpayneoregon answered AA-5973 edited

There are tons of code samples for this on GitHub, use the following with Google WPF-calculator GitHub which will produce several pages to choice from. And dependent on your skill level will dictate which one will assist you.

Some are very simple to advance e.g. using MVVM pattern for advance.

I picked a random from GitHub here which is simple and works. For keyboard, it recognizes operators on the numeric keypad, for = press Enter.

81614-f1.png



f1.png (6.6 KiB)
· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Hey

Thank you. I will try to find a good example. // update I didn't find better example.

In this example which you picked For keyboard, it recognizes operators on the numeric keypad
I do not have the numeric keypad, just that which is under F1,2,3...-buttons
How to update code?

0 Votes 0 ·