C# Application Development: A Deep Dive Through Tim Corey’s “Create Team Form Part 2” (Lesson 13)
In this article, we’re going to take a deeper look at C# application development by following Tim Corey’s Lesson 13 from his “C# App Start to Finish” series. Tim walks us through the process of building a functional Windows Forms application, focusing on how to connect UI controls like combo boxes, list boxes, and buttons to data. This lesson demonstrates key concepts such as data binding, list management, database connectivity using Dapper, and basic validation and debugging, all essential skills for building real-world C# applications.
Continuing the Create Team Form
Tim begins by reminding us that Lesson 13 is a continuation of the previous video, where the “Add New Member” section was wired up. In this lesson, Tim explains that the main goal is to wire up the dropdown (combo box) and list box, and then connect the newly created person object so it appears in the list. Tim sets the plan clearly: this lesson will focus on UI wiring, data movement, and list synchronization—fundamental aspects of building a C# desktop application.
Understanding the Drop-down and List Box Data
Tim explains that behind the combo box and list box, there will be a list of Person objects. This is a classic example of data binding in Windows Forms, where UI elements are bound to collections of data models.
He creates two private lists at the class level:
availableTeamMembers – the people who can be added to the team
- selectedTeamMembers – the people already added to the team
Tim clarifies the expected behavior: when a person is selected from the dropdown and added, they should move from availableTeamMembers to selectedTeamMembers. This is a standard CRUD operation pattern in desktop app development, where the UI reflects the underlying data.
Why Tim Doesn’t Limit Team Members by Tournament
Tim addresses a common design question: “Why not restrict team members based on the tournament?” He explains that the Create Team form is not tied directly to a tournament, and multiple tournaments could run simultaneously.
Tim uses a practical example: if both a basketball tournament and a ping-pong tournament are running, a person could participate in both. Limiting the dropdown would require complex logic and could introduce bugs. Instead, Tim chooses a simpler approach:
- Only remove a person from the dropdown after they are added to a team.
This approach demonstrates a practical software design decision: avoid over-complication unless necessary.
Creating the WireUpLists Method
Tim creates a method called WireUpLists to connect the lists to UI controls. This method binds the availableTeamMembers list to the combo box and the selectedTeamMembers list to the list box.
Tim points out a key improvement: in modern Windows Forms, you can bind lists directly to controls without using a separate BindingSource. This is a helpful tip for developers working on Windows Forms data binding.
Adding DisplayMember with Full Name
Tim explains that the combo box must display a readable name. The DisplayMember property expects a string property from the Person model. Tim warns that using only FirstName or LastName can cause duplicates.
So Tim creates a read-only property called FullName:
public string FullName
{
get
{
return $"{FirstName} {LastName}";
}
}This demonstrates an important UI practice: always make sure your UI displays user-friendly information, not raw object data.
Creating Sample Data for Testing
Tim creates a method called CreateSampleData to test the lists and UI. He adds sample Person objects to both lists and calls WireUpLists in the constructor.
This is a useful technique for building and testing Windows Forms applications quickly before connecting to a real database.
Replacing Sample Data with Real Data
Tim comments out the sample data and prepares to load real data. He adds a method GetPerson_All to the IDataConnection interface. Tim explains his naming convention:
Create = insert
- Get = select
This is a standard naming strategy for data access layers in C# applications.
Implementing SQL Data Retrieval Using Dapper
Tim implements the SQL version of GetPerson_All using Dapper and a stored procedure:
connection.Query<PersonModel>("spPeople_GetAll").ToList();Tim intentionally uses an output variable instead of a direct return to make debugging easier. This demonstrates how debugging practices can affect code design.
Cleaning Up Repeated Code with Constants
Tim notices repeated connection string names and changes them to a constant. He explains that repetition is bad practice and can cause errors later.
This is an important software engineering principle: DRY (Don’t Repeat Yourself).
Loading Real Data into the Dropdown
Tim creates LoadListData() and populates availableTeamMembers using GetPerson_All(). The selectedTeamMembers list remains empty, which is correct since a new team starts empty.
This demonstrates how to connect the UI to real data sources, whether a database or text file.
Wiring the Add Member Button
Tim creates the Add Member button event handler. The logic is:
Get selected person from dropdown
Remove them from available list
Add them to selected list
- Refresh the UI
Tim explains that the selected item must be cast to PersonModel because the combo box stores objects as object. This highlights the importance of type casting and object handling in C#.
Debugging the Refresh Issue
Tim discovers the UI doesn’t refresh after moving items. After debugging, he finds the solution:
Set DataSource to null
- Then reassign the list
This forces the combo box and list box to refresh. Tim emphasizes that debugging skills are essential and often required to understand how data binding behaves.
Wiring the Remove Selected Button
Tim renames the button to Remove Selected and creates the event handler. This reverses the add operation:
Remove from selectedTeamMembers
Add back to availableTeamMembers
- Refresh UI
Tim discovers a bug: if no item is selected, a null value gets added. He adds validation:
if (p != null)
{
// proceed
}This demonstrates basic validation and error prevention.
The Importance of Testing
Tim emphasizes testing your application like a user who tries to break it. He advises having testers who intentionally try to break the app, because real users will do unexpected actions.
This is a key lesson for building reliable software.
Wiring the “Create Member” Button
Tim modifies the “Create Member” button to save a new person to the data store and immediately add them to the selected list. This demonstrates how to implement CRUD operations in a Windows Forms application.
Implementing GetPerson_All for Text File
Tim realizes the text file version of GetPerson_All is missing. He implements it using a simple line:
return PeopleFile.FullFilePath.LoadFile().ConvertToPersonModels();This shows that file-based storage can be implemented easily without complex logic.
Confirming Everything Works
Tim runs the app and confirms that the dropdown now loads people from the text file and database. He adds new people and sees them appear immediately, showing the full system works correctly.
What’s Next?
Tim concludes by stating that the next video will focus on creating the team itself. This involves saving multiple pieces of data into the database or text file, completing the feature.
Final Thoughts
Tim Corey’s Lesson 13 is a real-world example of C# Windows Forms application development. From wiring UI controls and data binding to debugging and validation, Tim teaches practical programming skills for building real desktop applications. This lesson is especially valuable for developers who want to learn data binding, Dapper, SQL CRUD operations, and UI-driven programming in C#.
If you want to continue learning, Tim’s next lesson will complete the team creation feature and tie everything together into a working application.

