Lesson 13.2: More keyboard actions (and fixes)

I’m back from taking time off for my birthday, so this lesson will be a simple one. We’ll add the ability to change the displayed tab to Inventory, Quests, or Recipes. Plus, we’ll fix a potential crash if the user clicks on the datagrid and tries to use the keyboard actions.



Lesson Steps


Step 1: Modify WPFUI\MainWindow.xaml

There was a problem with the last change.

If the user clicks on one of the rows in the Inventory, Quests, or Recipes datagrid, that row has “focus” – the program thinks that is what we want to work with. Then, if the user presses the “W” key (to move North), the program will think they want to enter data into the datagrid cell that has focus.

Since some of the bound properties are readonly (they don’t have setters), this causes the program to crash.


To fix this problem, we’ll update the XAML Bindings with “Mode=OneWay”. Then, the UI will know that is should only read values from the properties, and not try to change the property’s values from the UI.


The code for this change in MainWindow.xaml is shown in step 2, because we’re making some other changes to the same part of the code. Look at lines 175, 180, 182, 195, 198, and 211 of the new code, to see where we add the OneWay mode to the binding.



Step 2: Modify WPFUI\MainWindow.xaml.cs

I also had a request to show how to use keyboard input to change the focus of the Inventory, Quests, and Recipes tabs. I also added the ability to use a keypress to show the trade screen – if the player is at a location with a trader.


To set focus on a TabItem, we need a way to distinguish the three different TabItems in the TabControl and set the focus to (display) the desired TabItem.

The TabControl object holds a collection of its TabItems. We could reference them by using an index: Inventory is at index 0, Quests is at index 1, and Recipes is at index 2.

But, if we ever add a new tab, or change the existing tabs’ order, we would need to remember to change the code to use the new index values.

To prevent that future problem, we’ll give each TabItem a Name value and use that name to set the focus. This is done in MainWindow.xaml, on lines 169, 189, and 205.

We also needed to give a name to the TabControl, so we can reference it in the code-behind page. On line 167, add the new attribute: x:Name=”PlayerDataTabControl”.


In MainWindow.xaml.cs, on lines 94-96, I added three new keys to watch for “I” (for inventory), “Q” (for quests), and “R” (for recipes). When the user presses one of those keys, we call a new SetTabFocusTo() function, passing in the name of the TabItem we went to set the focus on.


Add the new SetTabFocusTo function to lines 108-121.

We loop through the PlayerDataTabControl’s Items property (its collection of TabItems) and checks if the TabItem’s Name matches the value of the passed-in parameter. If it matches, it sets that TabItem’s IsSelected property to “true”, making is the displayed TabItem, and stops looking at the other TabItems for one with a matching name.

Notice line 112 “if(item is TabItem tabItem)”. It might look a little strange. This assigns the current item to the “tabItem” variable, whose expected datatype is TabItem. If the item is a TabItem, the “if” statement will evaluate to “true”, and the program will run the code inside. The code is functionally the same as the code below, but combine the first two lines into one:


To display the trade screen, I added line 97, which adds a new value to _userInputActions that looks for a “T” keypress and calls the function that displays the trade screen – the same function we use for the “Trade” button.

Because the user can press “T” when they’re at a location without a trader, we need to add a “guard clause” around the code that displays the trade screen. This is the new “if” statement on lines 71-77.


MainWindow.xaml.cs (lines 163-226, the “Inventory, Quests, and Recipes” section)




Step 3: Test the game.

Be sure to click on the different datagrids (especially the text values in the rows) and press some keys.


NOTE: The next thing I’ll probably work on is moving the data in the factories to XML files, so you can modify those files to add more locations, monster, items, etc. to the game – without needing to recompile the program. But, if there are features you want to see done first, please leave a comment and let me know.


Return to main page

4 thoughts on “Lesson 13.2: More keyboard actions (and fixes)

  1. hello Scott and all

    if clicked on the game message window then used the shortcut keys it would enter that key char into the game message window.. it would still perform the action(move/fight)

    nothing major but thought ill point it

    i think can be fixed by making it  read only and un-selected AcceptsReturn  via the properties


    or via code if change line 84

    82. <RichTextBox x:Name=”GameMessages”
    83.  Background=”Beige”
    84. VerticalScrollBarVisibility=”Auto” IsReadOnly=”True” AcceptsReturn=”False”>

    using that cant type there but still can select and copy the game messages if for some reason need to


    thanks for the lessons

    1. Ah, yes. The RichTextBox is another control we’re using only to display a value, but can be used to input values. Thanks for catching that and sharing your change. I’ll update the post to include that code tomorrow (hopefully – I’ve been busy on a project lately).

  2. Hi Scott,
    im looking forward for the xml part but is there a possibility that we can display the requierments for crafting or the quest requierements as a tooltip or sth cause it is hard to keep track af all ur quests and recipes


Leave a Reply

Your email address will not be published. Required fields are marked *