Lesson 20.3 – Binding list properties to datagridviews

Lesson Objectives

At the end of this lesson, you will know…

  • How to bind list properties of custom classes, to automatically update in datagridviews in the UI

 

Databinding list properties to the UI

In the last lesson we used databinding to connect the integer properties of the Player object to label controls in the UI (CurrentHitPoints, Level, etc.). In this lesson, we’ll bind the list properties for the player’s inventory and quests.

The basic principles are the same as binding an integer property; however, we need to do a few things differently.

 

Step 1: Open the InventoryItem class, in the Engine project.

Just like with the Player class, we need to say that this class implements the INotifyPropertyChanged interface. So, change this:

to this:

While adding this “using” statement, at the top of the file:

Then, add the PropertyChanged event and OnPropertyChanged() function.

Next, change the Details and Quantity auto-properties to use backing variables and call the OnPropertyChanged () function.

 

Step 2: We want the datagridview to display a property of InventoryItem’s Details property. So, we need to do one final thing to the InventoryItem class.

Add this new read-only property, that gets the item’s name from the Item object.

This way, the InventoryItem object has a Description property we can bind to in the datagrid. We can’t databind to a property of a property, without doing a lot of extra work. So, we’ll use this technique.

 

Step 3: Open the Player.cs class.

To bind a List property, you need to change its datatype to either “BindingList” or “ObservableCollection”. BindingList gives more options than ObservableCollection – like searching and sorting. So, we’ll use it.

Add this to the “using” statements, at the top of the file:

Then change the Inventory property from this:

To this:

And change the Player.cs constructor to this, to match the change to the Inventory property’s datatype:

One thing I don’t like in the .NET framework is that the different list/collection datatypes have different ways of working with them. Because we switched from a List datatype, to a BindingList, we need to make a couple other changes.

In some of the functions of the Player class, we check if an item exists in the player’s inventory – for example, to see if they have all the items needed to complete a quest. We used the .Exists() method on the List properties to do this check. However, .Exists is not available with BindlingLists.

So, in the Player class, use Ctrl-F to search for “Inventory.Exists” and change them to “Inventory.Any”. “Any” will return a “true”, if any of the items in the BindingList match the criteria we are looking for, just like “Exists” does for a List property or variable.

You should find this in two places: the HasRequiredItemToEnterThisLocation() function and the HasAllQuestCompletionItems() function.

 

Step 4: Now that the business objects are ready, we can bind them to the UI.

Open SuperAdventure.cs.

We currently call UpdateInventoryListInUI(), to update the inventory. Just like with the databinding for the integer properties, we’re going to perform the databinding in SuperAdenture’s constructor method, delete the old function, and delete any lines where we call the old function.

In SuperAdventure’s constructor, add these lines after the databinding for the hit points, gold, etc.:

These lines configure the dgvInventory datagrid view.

We say that we don’t want to show row headers – the blank squares to the left of each row.

We also don’t want the binding to automatically generate the data grid’s columns. If this value was set to “true”, the datagrid would create a column for each property of InventoryItem. We want to manually configure the columns, so we set AutoGenerateColumns to “false”.

Next, we say that the DataSource for the datagridview is going to be the player’s Inventory property. This is where the data “binds” to the UI.

The next two parts are where we configure the columns of the datagridview.

We add new DataGridViewTextBoxColumns, since we want to display text in them. There are different column types you can use if you want to display buttons – for example.

The DataPropertyName value is the property of InventoryItem that we want to display in the column. This is why we created the Description property in InventoryItem. We couldn’t use “Details.Name” here. We needed a property of InventoryItem for the databinding.

 

Step 5: Now we have the databinding in place, and we can get rid of the old code we used to refresh the Inventory datagridview.

Delete the UpdateInventoryListInUI() function from SuperAdventure.cs. It should be around line 223.

Use Ctrl-F to search for the places in SuperAdventure.cs where we call UpdateInventoryListInUI() and delete those lines. They should be at lines 209, 379, and 463.

 

Step 6: Run the program to make sure everything works.

 

Step 7: We need to repeat these steps to bind the player’s Quests list property to the UI.

Change PlayerQuest.cs to this:

 

Step 8: Modify Player.cs

Change the Quests property to a BindingList:

In the Player constructor, change the Quests to be a BindingList also:

Find the HasThisQuest() function, and change “Quests.Exists” to “Quests.Any”.

 

Step 9: Modify SuperAdventure.cs

Add this code in the constructor, to configure the datagridview and bind the player’s quest list to the UI.

 

Then, delete the UpdateQuestListInUI() function and delete where it was called in the MoveTo() function – around line 227.

 

Step 10: Run your program, and make sure there aren’t any errors.

 

Summary

This may not seem like the most exciting work – making all these changes, without adding any new features to the program. However, refactoring will make it much easier for you to expand the program later.

Plus, now that you know how to do databinding to the UI, you can start out using it the next time – instead of doing it the way we originally did, then making the change to this better method.

 

Source code for this lesson

Get it from GitHub: https://gist.github.com/ScottLilly/3ddd0df5d6a6d373a091

Or DropBox: https://www.dropbox.com/sh/qnl5bbc4rnhpuhd/AABhHIZKW1v3wduQxbqEv7L3a?dl=0

 

Next lesson: Lesson 20.4 – Binding child list properties to a combobox

Previous lesson: Lesson 20.2 – Binding a custom object’s properties to UI controls

All lessons: Learn C# by Building a Simple RPG Index

Leave a Reply

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