Press "Enter" to skip to content

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;
        }
    }
}

NEXT LESSON: Lesson 03.6: Update Player data with the PropertyChanged event

PREVIOUS LESSON: Lesson 03.4: Creating the GameSession (ViewModel) Class

10 Comments

  1. Leslie P
    Leslie P 2022-07-01

    I’m using Visual Studio 17.2.5 and it does not show the same nodes in the Solution Explorer as your video does; there’s no ‘references’ node at all. I right clicked on ‘dependencies’ and was able to add a reference, but even after doing that, I did not see all the nodes you did once you added the reference. There have been a few other differences, not sure if I installed something wrong or if VS has just been reorganized/designed since you made that video. If the latter, this particular section of your tutorial may need a re-work due to the vast differences in layout/organization of the new VS community ed.

    • SOSCSRPG
      SOSCSRPG 2022-07-05

      Hi Leslie,

      Thanks! I’ll look into updating this. It may take a while, since I’ll need to manually re-run through the lessons before it, to get code in the same condition (unless I can figure a simpler way).

      When Microsoft released .NET Core and .NET 5/6, they made lots of updates to Visual Studio.

  2. Frederico Volpini
    Frederico Volpini 2022-07-26

    Hey!

    I didn’t understand what you did inside MainWindos.xaml.cs
    Is there a place or keyword you can recommend I search about?

    • SOSCSRPG
      SOSCSRPG 2022-07-27

      Hello Frederico!

      I’ll give a general explanation, but please tell me if you have a specific question about something.

      MainWindow.xaml is used to display things in the screen. MainWindow.xaml.cs is used to create or change the objects of the program that are displayed in MainWindow.xaml. The xaml.cs file is sometimes called a “code behind” page for the xaml file, because it holds the logic (code) for the objects that are displayed in the xaml page.

      In this case, we are creating a GameSession object. In the GameSession object’s constructor (lines 14-23), we create (instantiate) a Player object and set its property values. We put that Player object into the GameSession object’s CurrentPlayer property. We put that GameSession object into the xaml.cs page’s DataContext. Every xaml page has a DataContext – the property where it holds the object being used in the xaml.

      If we created a xaml page to edit a Player, we could instantiate a Player object and set that xaml page’s DataContext to the Player object, because the Player object is what we are going to display, and edit, on the xaml page.

      In this code, we have the extra GameSession object because it is going to hold more that just the CurrentPlayer object. We’re going to add location and monster information (objects) into the GameSession class, so we can display that on the xaml page in the future.

      Please let me know if that was not clear, or if you still have questions.

      • Frederico Volpini
        Frederico Volpini 2022-07-29

        You did perfect now, thanks! For both explaining and answering fast.
        Finished the lesson and I both understand and all is working.

        I suppose I don’t need to dive deeper into what the line:

        “DataContext = _gameSession;”

        at MainWindow.xaml.cs does, do I?

        • SOSCSRPG
          SOSCSRPG 2022-07-30

          You’re welcome.

          If you understand that DataContext is a property on Window objects, and we are putting our GameSession into that property, that’s probably all you need to know for now. There are more-advanced things you can learn about DataContext in the future, if you want.

  3. Antonio V
    Antonio V 2022-11-06

    I’m using Visual Studio 2022 for Windows and when I try to bind the “Name”, I get an error that says “No DataContext found for Binding ‘CurrentPlayer.Name’. I made sure that I did include the DataContext line in the MainWindow.xaml.cs and it does not work.

    • SOSCSRPG
      SOSCSRPG 2022-11-06

      Hi Antonio,

      Can you check if the GameSession class, Player class, CurrentPlayer property (in GameSession), and Name property (in Player) all have a “public” in front of them? If those are missing, that could cause this error.

      If they are public, can you upload your solution (including the directories under it, and all the files in those directories) to GitHub, Dropbox, or some other file-sharing location so I can look at it?

      If you haven’t used GitHub before, here is some information (and a video) on how to upload your solution to GitHub and share it with me. https://codingwithscott.com/how-to-connect-visual-studio-community-edition-2022-to-github/

      • Antonio V
        Antonio V 2022-11-06

        I checked everything, and it is all public. It turns out that Visual Studio 2022 shows you what your page looks like live without you having to run it. When it was showing it to me like that, the binding was not working. But when I ran the program, the binding worked fine. I am assuming that it is a bug in Visual Studio. Is this correct?

        • SOSCSRPG
          SOSCSRPG 2022-11-07

          It sounds like you have the XAML Designer turned on for the WPF windows. If so, it doesn’t always show the binding correctly until you run the program. When the program isn’t running, there isn’t an instance of the object, so there isn’t anything to bind to – which can show an error in the Designer view.

Leave a Reply

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