Lesson 03.5: Displaying the Player Object

In this lesson, we will connect the View (MainWindow.xaml) to the ViewModel (GameSession.cs), and display properties from the model (Player.cs).

 

 

Summary

In this lesson:

  • To let the “WPFUI” project see classes in the “Engine” project, we need to “add a reference” to the “Engine” project.
    • In the WPFUI project, right-click on the “References” and select “Add Reference…”
    • We want to add a reference to the “Engine” project, inside the solution, so we highlight “Projects” -> “Solution” and see a list of the available projects in the solution.
    • Check the “Engine” project, and the “OK” button.
    • Now, the WPFUI project has a reference to (can see the classes in) the Engine project.
  • We defined the layout of the screen in MainWindow.xaml.
    • The XAML file has a related file, where we can put C# code.
      • This is sometimes called the “code-behind” page.
      • xaml.cs is the code-behind page for MainWindow.xaml.
    • xaml.cs is another “class” – just like Player.cs, but it is for creating a screen, not a Player.
      • It has a “constructor”. This is what runs when you create a MainWindow object.
      • The constructor in MainWindow.xaml.cs runs the function “InitializeComponent()”. We will talk about functions later, but this is what draws the screen, and the objects on it (the grid, and labels).
      • We will create our Player object inside the MainWindow constructor.
    • Inside the constructor’s curly braces {}, we will instantiate a GameSession object.
      • This object will be the “DataContext” for the view – the object that will be used in the UI.

 

Source Code

GameSession.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Engine.Models;

namespace Engine.ViewModels
{
    public class GameSession
    {
        public Player CurrentPlayer { get; set; }

        public GameSession()
        {
            CurrentPlayer = new Player();
            CurrentPlayer.Name = "Scott";
            CurrentPlayer.CharacterClass = "Fighter";
            CurrentPlayer.HitPoints = 10;
            CurrentPlayer.Gold = 1000000;
            CurrentPlayer.ExperiencePoints = 0;
            CurrentPlayer.Level = 1;
        }
    }
}

 

MainWindow.xaml

<Window x:Class="WPFUI.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:WPFUI"
        mc:Ignorable="d"
        Title="Scott's Awesome Game" Height="768" Width="1024">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="225"/>
        </Grid.RowDefinitions>

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="250"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>

        <Label Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Content="Menu" Background="AliceBlue"/>

        <Grid Grid.Row="1" Grid.Column="0" Background="Aquamarine">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
            
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>
            
            <Label Grid.Row="0" Grid.Column="0" Content="Name:"/>
            <Label Grid.Row="0" Grid.Column="1" Content="{Binding CurrentPlayer.Name}"/>
            <Label Grid.Row="1" Grid.Column="0" Content="Class:"/>
            <Label Grid.Row="1" Grid.Column="1" Content="{Binding CurrentPlayer.CharacterClass}"/>
            <Label Grid.Row="2" Grid.Column="0" Content="Hit points:"/>
            <Label Grid.Row="2" Grid.Column="1" Content="{Binding CurrentPlayer.HitPoints}"/>
            <Label Grid.Row="3" Grid.Column="0" Content="Gold:"/>
            <Label Grid.Row="3" Grid.Column="1" Content="{Binding CurrentPlayer.Gold}"/>
            <Label Grid.Row="4" Grid.Column="0" Content="XP:"/>
            <Label Grid.Row="4" Grid.Column="1" Content="{Binding CurrentPlayer.ExperiencePoints}"/>
            <Label Grid.Row="5" Grid.Column="0" Content="Level:"/>
            <Label Grid.Row="5" Grid.Column="1" Content="{Binding CurrentPlayer.Level}"/>
        </Grid>

        <Label Grid.Row="1" Grid.Column="1" Content="Game Data" Background="Beige"/>
        <Label Grid.Row="2" Grid.Column="0" Content="Inventory/Quests" Background="BurlyWood"/>
        <Label Grid.Row="2" Grid.Column="1" Content="Combat/Movement Controls" Background="Lavender"/>

    </Grid>
</Window>

 

MainWindow.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Engine.ViewModels;

namespace WPFUI
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private GameSession _gameSession;

        public MainWindow()
        {
            InitializeComponent();

            _gameSession = new GameSession();

            DataContext = _gameSession;
        }
    }
}

 

Return to main page

 

29 thoughts on “Lesson 03.5: Displaying the Player Object

  1. Hey, Scott. I really love all the free, helpful information you’ve provided on your site! I’m looking forward to your next lessons. I’m extremely interested in programming, enjoying C# a lot so far. I want to learn more. Do you have any tips, resources (like books), or anything else that might be useful for me? I want to focus on game programming because that’s what I want to do as a career but anything you think is good in general is highly appreciated! Thanks so much.

    1. Hello,

      I’m glad to hear you’re enjoying the lessons.

      If you want to build games, especially with better graphics, you’ll probably want to look at Unity 3D. It’s like a version of Visual Studio, and the C# framework, with additional features to make it easier to create games. Some people even use it to create professional games. I don’t know any good books for it. You might want to look at the Quill18Creates channel on YouTube. He uses Unity and has at least one game on GitHub, so you can view the source code.

      For general C# programming, the three most-recommended books are “The C# Programming Yellow Book” by Rob Miles (for general learning), “Essential C# 6.0” by Eric Lippert and Mark Michaelis, and “C# in Depth, 3rd Edition” by Jon Skeet. I’d say the first one is more of a “guidebook”, and the last two are more like “reference” books.

      1. Thanks! I’ll definitely look at those books. I’ve actually been reading the C# Yellow Book but I just felt like I wasn’t getting enough programming practice and have been going to other outlets and have ended up not reading the book much and in very short bursts.

  2. Visual studio said that the CurrentPlayer = new Player() with all is call like CurrentPlayer.Name = “Blah”; , etc… could be simplified like this:

    CurrentPlayer = new Player()
    {
    Name = “Trevis”,
    CharacterClass = “Fighter”,
    HitPoints = 10,
    Gold = 1000000,
    ExperiencePoints = 0,
    Level = 1
    };

    Are you going to use this format later? or should I keep it the how you have it for now and worry about simplification later?

  3. Hi Scott,

    I am using VS2017 and even though I have everything same as you (I even copied your source code just to be sure) and the values are not showing even though I am not getting any errors so the binding should be done properly and I was even getting the placeholder values

  4. Isn’t it a bit redundant to have a property for player level? Player level is determined by experience anyway, right? It seems like something that could get out of sync somehow and display the wrong values, but maybe I’m wrong.

  5. For anyone having the issue where the player data is not being displayed on the screen, and the program is not hitting an error.

    The cause for me was that I missed the step of making the player object public in the Gamesession Class.

    I had to change:

    Player CurrentPlayer { get; set; }

    in GameSession.cs to:

    public Player CurrentPlayer { get; set; }

    This allowed access to the player information so it could be displayed.

     

    1. You definitely need to pay attention to the scope (public, internal, and private). This is especially true when creating classes. By default, Visual Studio creates them without an explicit scope. So, they default to “internal” (only visible to other classes in the same project). For many of our classes, they need to be set to “public”.

  6. Great video and lesson. I have XAML with values from code! I have resisted WPF for a while but your lessons are really great!

  7. Hi all,
    I have a problem with using Engine.ViewModels in MainWindow.xaml.cs i am getting error Namespace is not recognized, but reference is there. I copied your code and error is still there. I have Visual Studio 2017 and NET 3.5
    where can be problem please?
    Thank you

    1. Hello Michal,

      When you created the Engine project, did it have a different name, and did you rename it? If that happened, you might need to fix the namespace for the project. Here is a link to the Windows Form version of the project that shows how to fix that: http://scottlilly.com/learn-c-by-building-a-simple-rpg-index/lesson-02-2b-fixing-the-namespace/.

      If that is not the problem, can you upload your solution (including the directories under it, and all the files in those directories) to GitHub or Dropbox, so I can look at it?

      1. Hi Scott,
        Thanks for reply, i already solved it, it was my bad i somehow forget set that reference in project properties. Thank you again 🙂 And when will be next lesson? Im looking forward to save/load chapter and complex combat system, btw good job with this tutorial, i like it, keep it up.

        1. You’re welcome. I was working on the next lesson this morning. It should be up Thursday or Friday. It’s a small one, with more keyboard input. I’m trying to figure out what to work on after that. I think it will be converting the factories to read from XML files, so everyone can create their own custom game.

  8. I’ve run into the same problem with DataContext not working. I’ve set Player CurrentPlayer in GameSession.cs to public and the Player class and its properties are all public, and MainWindow.xaml still won’t recognize it. I’m using VS 2017 with .NET 4.6.1 on Windows 10.

  9. Ignore my previous comment (no edit button so replying again). I’ve been observing changes to the UI through the preview mode and didn’t think to actually run the program to see the data. Ran it and everything shows up fine.

  10. Hi Scott,
    I’m running into an error when adding the Engine as a reference. I see the Engine in the reference manager, however, after I select it and hit OK i get an error pop-up that says “Unable to add a reference to project ‘Engine’.

    a small difference i had was my class library has (universal windows) next to it. Is this the issue? Do you know if there is a way to connect these two?

    1. Hi Andrew,

      The class library type is probably the problem. Instead of “Universal Windows”, the project needs to be a “Class Library (.NET Framework)”. I don’t know of an easy way to convert it. You’ll probably need to delete the Engine project from the solution, delete the Engine directory from your disk, and add a .NET Framework Class Library “Engine” project into the solution.

  11. Thank you Scott for giving us this awesome info for free. Have you thought about making one of these rpg games but in unity, I would pay for something like that.

    1. You’re welcome! I’ve thought about doing something with Unity, but I’ve also been looking at genetic algorithms as the next thing for me to learn. There are so many things to learn, it’s difficult to decide. 🙂

  12. Hi Scott,

    I’m coming from Python and JavaScript and having a hard time getting my head around C# and WPF in particular.

    I’m really enjoying your tutorial, but I have what I think is rather a dumb question. I’m not able to phrase the right question to search the internet so I’m just going to ask here.

    In xaml.cs, what does this line do:

    private GameSession _gameSession;

    I can’t follow the logic of this line followed by the remaining code. Could you break it down for me, or point me towards a resource to understand this better?

    Thanks
    Jon

    1. Hi Jon,

      This line is declaring a variable named “_gameSession”. The variable is going to hold an object whose datatype is “GameSession” – one of our classes we created. If you’re new to OOP (Object-Oriented Programming), we can make our own datatypes, and not just use the built-in ones like string, int, boolean, etc. C# is a strongly-typed language, which means we can define what type of data is going to go into the variable (or property, or parameter). This helps eliminate problems like you might have seen in JavaScript, where JavaScript might think 1 + 1 equals 11, since it did string concatenation instead of arithmetic.

      The “private” at the start of the line is an access modifier. That defines what other parts of the program will be able to see the _gameSession variable. Because it’s private, and is inside the MainWindow class, but outside any functions, that means it can be used (read from, or written to) by anything in the class.

      Let me know if that wasn’t clear.

      Scott

  13. Hi Scott,

    Thanks for taking the time to reply.

    Yes, that explanation was really clear. I did not realize you could declare a variable as a class without further assignment (i.e private Foo _foo = new Foo();). Understanding that part makes the rest of the code much easier to follow.

    However, one thing I’m still unsure of is: Why is the variable declared outside of the class, but the object instantiated inside? Why not put these together inside? I wonder if that is just customary or if it’s actually required?

    I also appreciate the explanation on what strongly typed means and the further reading.

    Cheers
    Jon

    1. You’re welcome.

      The variable is declared outside the functions because we’re going to use it in several functions. That’s why it’s “class-level”, so it can be used by anything inside the class. You could possibly pass the variable from function to function, but many of our functions will eventually be triggered by an event like a button click.

      For example, when the user clicks on one of the movement buttons we’ll add, we’re going to have individual functions to move North/South/East/West. Each of those functions will need to use the GameSession variable, to update its properties about the player’s current location, create a monster for the player to fight, meet a trader, etc.

      It might be clearer after you get to the lessons where we add more functions to MainWindow.xaml.cs.

  14. Hey Scott, when i compile the Binding shows not to work, i’m using the visual studio 2019, and i just copy your code, but don’t work,ex : Just show the Player Name , but no the name.
    Thanks a lot.

Leave a Reply

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