Earn More by Sharing What You Love
Do you create content for developers working with .NET, C#, Java, Python, or Node.js? Turn your expertise into extra income!

Tim Corey
1h 11m 40s
In Lesson 22 of the C# App Start to Finish series, Tim Corey begins work on the Tournament Viewer form, focusing heavily on WinForms data binding. Tim explains that this lesson is not about saving data to databases or text files - that will come later. Instead, the entire purpose of this video is to wire up the UI, populate controls, and understand how data moves between models and WinForms controls using data binding.
Tim makes it clear that WinForms data binding can feel clunky, confusing, and sometimes frustrating. Because of that, this lesson becomes a deep, practical walkthrough of how data binding actually behaves, what breaks it, and how to fix it. By following Tim's debugging journey, we get a realistic and valuable understanding of WinForms binding mechanics.
Tim starts by describing what the Tournament Viewer form is supposed to do. The form displays:
Tim emphasizes that all of this information must stay in sync. When a round changes, the matchups must update. When a matchup changes, the team names and scores must update. This requirement drives the entire discussion around data binding. Controls bound to the same data source, also known as data-bound controls, stay in sync automatically. The BindingNavigator control handles the binding to the data by keeping the pointer to the item in the record list current. The CurrencyManager class manages a collection of bindings between list controls and a data source object, allowing for position tracking and change notifications. Each bound control, such as a TextBox or Label, is linked to the data source through these mechanisms to ensure automatic synchronization.
Tim explains that the Tournament Viewer form should not decide which tournament to load. That responsibility belongs to the dashboard. Therefore, the Tournament Viewer form must receive a TournamentModel through its constructor.
He shows how the passed-in tournament object is stored in a private field at the form level, making it accessible to every method in the form. This tournament object becomes the single source of truth for all data binding operations. In simple data binding, a control can be bound to a single data element, such as a value from a single data table, allowing you to display or edit individual data points. The BindingSource can be used in both simple and complex binding scenarios.
Tim introduces a private method called LoadFormData. This method pulls data from the tournament model and pushes it into UI controls.
For example:
Tim highlights that this is the simplest form of data binding - manually assigning values - and it's a good starting point before dealing with lists and collections. Simple binding connects a single property of a control to a single value in a data source and typically displays one record at a time.
Tim walks through modifying the dashboard so that when a user selects a tournament and clicks "Load Tournament," the Tournament Viewer form opens.
Here, Tim casts the selected dropdown item to a TournamentModel and passes it into the viewer form. He confirms the wiring works by running the application and seeing the tournament name appear correctly.
This confirms that basic object passing and UI updates are functioning before moving into list binding.
Now Tim moves into list binding, starting with tournament rounds.
He explains that rounds are best represented as a list of integers, not strings. Tim explicitly says this choice makes life easier because:
A ComboBox control can be bound to a given table or list, allowing you to display and select data efficiently. When binding a ComboBox control, you can use the DisplayMember property to specify which field is shown to the user, and the ValueMember property to determine which field is used as the underlying value. Similarly, you can bind the DataGridView control to the information contained in a data table.
Tim loops through the tournament's rounds, extracts unique round numbers, and stores them in a list.
Tim introduces the first important WinForms binding rule:
Always set the DataSource to null before resetting it.
He clears the dropdown's data source, then assigns the rounds list to it. When you bind a control to a data source, if the data source implements interfaces like INotifyCollectionChanged, the control will automatically refresh its UI when the data changes. This ensures real-time synchronization between the data and its visual representation. Additionally, changes in the UI control or the underlying data source automatically update the other end of the binding based on configuration (one-way or two-way). Because integers convert naturally to strings, he explains that no DisplayMember is required here.
Tim then demonstrates a common mistake - forgetting to call the load method - and shows how missing a single method call results in an empty dropdown.
Tim explains that WinForms relies heavily on events, especially SelectedIndexChanged.
He wires the round dropdown's SelectedIndexChanged event to a method that loads matchups for the selected round. In WinForms data binding, an event handler receives the object sender parameter, which identifies which control triggered the event. You can handle the following events, such as Format and Parse, to customize data formatting and validation; the Format and Parse events of the Binding class allow for special formatting and validation of data during the data binding process. Other controls can also be bound and synchronized through similar event handling.
Tim prefers extracting logic into private helper methods instead of placing code directly in event handlers. He explains this keeps the code reusable and clean.
Tim retrieves the selected round by casting the dropdown's selected item back to an integer.
He loops through the tournament's rounds again, but this time filters matchups where the matchup round equals the selected round. These matchups are placed into a selected matchups list, which becomes the data source for the matchup list box.
This introduces the challenge of binding lists of complex objects.
Tim explains that the matchup model doesn't have a natural string representation suitable for UI display.
Instead of forcing logic into the UI, Tim adds a read-only DisplayName property to the model. This property builds a string like:
Team A vs. Team B
If a team is missing (bye week or future round), Tim returns:
Matchup not yet determined
Complex bound controls, such as DataGridView, support complex bind scenarios where multiple data elements from a data table or other structures can be displayed and edited. Complex data binding allows you to bind more than one data element to a control, such as binding multiple columns or rows from the underlying record source. ADO.NET provides many data structures suitable for binding, including DataTable, DataView, and other structures, and Windows Forms supports binding to multiple data sources. The binding class manages the logical link between data source fields and control properties, and interfaces like IBindingList, IEditableObject, and INotifyPropertyChanged provide sorting, change notification, and rollback support. You can set default filters on data views to control how data is displayed, and the binding context and CurrencyManager ultimately determine how data-bound controls are synchronized. The BindingContext property of a Windows Form manages the CurrencyManager objects for the form, and each data source has a single CurrencyManager object, which keeps all controls bound to the same data source in sync. Custom controls can be created in Windows Forms that behave like standard data-bound controls by implementing the necessary data binding interfaces.
This is a key WinForms data binding principle Tim emphasizes:
The model should decide how it is displayed - not the UI.
Tim encounters multiple bugs:
Rather than hiding these issues, Tim walks through each debugging step. He explains how binding breaks when lists are replaced, even if the new list contains valid data.
This leads to a critical WinForms lesson.
The following code demonstrates how to handle the Format and Parse events of the Binding class to provide special formatting and validation during the data binding process. The format event and parse event can be used to customize how data is converted and validated between the UI and the data source.
Tim experiments with BindingSource, placing it between the UI control and the data. He explains how this used to be the recommended approach, but admits it introduces complexity and confusion. The BindingSource component acts as a proxy between a data source and Windows Forms controls, and it works with various data structures suitable for binding, such as DataTables, DataViews, BindingLists, and arrays.
He then introduces BindingList, explaining that it automatically updates bound controls when the list changes. If the data source implements the appropriate interfaces, such as INotifyCollectionChanged, data binding in Windows Forms supports automatic updates of controls when the underlying data changes.
However, Tim discovers a crucial rule:
You must NOT replace a BindingList with a new one.
Instead, you must:
Replacing the list breaks the binding connection.
Tim confirms the root cause of the binding issue:
BindingList<T>() disconnects the UIHe updates both rounds and matchups to use this pattern. Once applied consistently, the UI finally updates correctly.
Tim explains that WinForms does not automatically fire SelectedIndexChanged when items are loaded.
To fix this, he manually:
This ensures the UI initializes correctly without requiring user interaction.
By the end of the lesson, Tim confirms:
He emphasizes that this lesson was not about perfection, but about understanding how WinForms data binding really behaves - including its limitations.
Tim closes by explaining that scoring and filtering (like "unplayed only") will be handled in the next lesson, once there's real state change to work with.
Lesson 22 is a masterclass in practical WinForms data binding, not because everything works smoothly, but because Tim Corey walks through every failure, fix, and design decision in real time.
By following Tim's video, developers gain a realistic understanding of:
If you've ever struggled with WinForms data binding, this lesson - and Tim's explanations - make the "why" finally click.
Do you create content for developers working with .NET, C#, Java, Python, or Node.js? Turn your expertise into extra income!
Join our newsletter, you’ll get exclusive access on article updates. We value your privacy