February 1st, 2022

Databinding with the OOP Windows Forms Designer

Klaus Loeffelmann
Senior Software Engineer

The design-time support for databinding in the new Windows Forms (WinForms) .NET Out of Process (OOP) Designer is different from the Framework Designer. The WinForms OOP Designer has a new and easier approach for hooking up data sources, focusing on Object Data Sources to support .NET based object relational mapper technologies (like the latest version of Entity Framework Core – EF Core for short) which the WinForms team recommends as a successor for Typed DataSets. This new approach was due to the completely different architecture of the new WinForms OOP Designer, which we have discussed in the previous blog post. If you haven’t read it yet, you should do so first, as it is essential for a better understanding of this post.

Why is the Data Source Tool Window unavailable in .NET projects?

Essential to databinding in WinForms .NET Framework is the Data Source Provider Service. This service runs in Visual Studio, and its responsibilities are as follows:

  • It generates and maintains Typed DataSets by connecting to a database data source (for example Microsoft SQL Server or Oracle DB Server).

  • It detects types which are designed to act either as Typed DataSet Data Sources or Object Data Sources.

  • It identifies potential Object Data Sources and sets those up in the project.

  • It discovers legacy (for example SOAP-based) web services and sets them up in a way so they can act as data sources.

  • It provides the UI functionality for the Data Source Tool Window in .NET Framework for WPF and WinForms applications. It also provides the UI Wizard to add new or maintain existing SQL Server connected data sources.

As of today, the Data Source Provider Service only works in the context of Visual Studio, which means it can only type-resolve .NET Framework assemblies and types. For .NET in its current version, the Data Source Provider Service is not able to retrieve the necessary type information as it would need to operate on the .NET Server Side (the DesignToolsServer). This is the reason that the UI stacks which used to rely on the Data Source Provider Service (WinForms, WPF) need to come up with alternatives for setting up new data sources and at the same time support legacy scenarios as well as possible. Providing feasible migration options, so that data access and databinding technologies can be migrated Form by Form, with both data source binding approaches (Typed DataSets and new ORMs based on Object Data Sources) present over a period of time, was the main driver for the new databinding functionality.

Working with legacy Typed DataSets in the OOP Designer

To decouple WinForms from the dependency to the Data Source Provider Service, there is now a new and quicker way to hook up new Object Data Sources.

That said, existing Typed DataSets definitions copied from Framework projects can – with some limitations – be consumed by the OOP Designer even without that service present. This means, data-bound Forms or UserControls using Typed DataSets can be opened, and the Design Binding Picker (the drop-down editor in the Property Browser to pick data sources for binding) will continue to provide the necessary functionality to define the databinding of individual properties of controls. At this time, though, no new Typed DataSets can be generated in the context of a WinForms .NET application. It is also not possible, to interactively update the schema for a Typed DataSet by querying the schema of the assigned database. Necessary components (DataSet and for assigning the data at runtime tablenameTableAdapter) to add a new binding definition can, however, be added from the toolbox and hooked up manually – which means maintaining legacy data-bound forms based on Typed Data Sets in .NET WinForms projects is generally supported.

The following animated gif shows the process. Copy the Typed DataSet definition from your existing Framework project to your new .NET project and see that all necessary adapters and DataSets automatically appear in the toolbox on recompile. You see: Clicking the Typed DataSet based data source on the Picker does only set up the binding if the respective components are present in the Component Tray.

An animated gif showing how to prepare a Form for using Typed DataSets as a data source for binding

New Approaches when using Object Data Source Binding

Object Data Sources can, in contrast to Typed Data Sets, get their data through all different kind of means. One of the most popular alternatives, which is a great replacement for old-fashioned Typed DataSets, is Entity Framework Core (EF Core for short). Apart from the fact that it has greater performance and a bigger set of functionalities compared to Typed Data Sets, it also uses a different approach in dealing with the permanent task of updating and maintaining a database’s schema. While EF Core can principally be used in the same way as Typed Datasets, which are generated based on an already existing database, data objects based on EF Core can take a different more flexible and more maintenance-friendly approach, which is called Code first.

Code-first in this context means, the class definition defines the data structures/schemas, the relations between the entities (tables), and then the actual database schema is derived from this class definition: So-called migration-code updates the actual database definition on the fly. The advantage: The underlying database technologies is abstracted away: Code-first enables you to generate the schema for many different database systems: SQL Server, SQLite, Oracle Server, In-Memory databases, Cosmos, PostgreSQL, MySql – you name it!

A screenshot of a C# code file in Visual Studio showing a typical EF Core code-first data class

Let’s consider the following scenario: We build a .NET 6 Windows Forms application using EF Core code-first with data classes defined in a dedicated class library. This way, we can reuse the data layer code in other projects. But – in contrast what you would have done with Typed DataSets, we are not binding the EF Core data classes directly to the WinForms UI. The goal is to reduce the business logic code in the actual UI (Forms/UserControls) and get rid as much as possible of the WinForms typical “Code Behind” style. For that, we are introducing a set of properties to bind to yet another Object Data Source, which implements the business logic instead. We call this the business logic UI-controller class, or UI-controller for short. And those are the properties, we bind. A few examples:

  • Instead of setting the window title text of a Form directly in code-behind in the Form, we have a property in the UI-controller for the windows title. And that we bind.

  • A Save button should only be enabled when there actually is something to save. Instead of enabling or disabling the button in Code-Behind in the Form, we are introducing for example a `SaveButtonEnabled` property in the UI-controller, which we then bind against the `Enabled` property of the button.

  • We can even utilize a concept which originated from WPF and is called Command Binding. It’s suitable for elements like ToolStripItems (and the derived components ToolStripButton, ToolStripMenuItem and others) or Button controls and implemented via the ICommand interface: When the user clicks on such a button in the WinForms UI, and the command property of that button is bound to a respective property in the UI-controller class, the command executes the underlying business code in the business class logic rather than in some Click event code-behind.

A UI-controller class would look something like this:

A screenshot of a C# code file in Visual Studio showing a UI controller class implementing INotifyPropertyChanged base class

Using a combination of data classes (which represent the Database) and UI-controller(s) in this way as Object Data Sources has some advantages:

  • Business logic reuse: The business logic is defined by business object (data source) classes independently of the UI. This means they can be reused in other scenarios. The same business objects which are used in a WinForms application could also be used for example in a Maui .NET mobile application.

  • Unit tests: Since the business logic doesn’t include any specific UI-stack dependencies, it can be unit tested way more easily. That is a big advantage over the WinForms typical code-behind approach.

  • View model/UI Controller support: Object Data Source classes can – or rather should – implement the `INotifyPropertyChanged` Interface. This enables data sources to act as UI-Controller classes (or View Models), which make them suitable to be reused in other UI Stacks.

A diagram showing the relation between Data/Model class, UI-controller and a UI Form

Note: Although the binding infrastructure in WinForms is comparatively powerful, it doesn’t have the flexibility of XAML-based binding which you might know from WPF, UWP or Maui. For WinForms, you will most likely always be ending up with some Code-Behind code to support UI-Controller binding scenarios, which are otherwise difficult to implement just on the model/controller side. But that’s OK and expected. For a better reusability of code and the ability to write code, which is testable, it’s still worth the effort. And a migration to this way of binding can be easily done over time, Form by Form, so it is really feasible and can be planned for huge LOB apps. On top, we plan to further support and extend UI-controller centric scenarios in the .NET 7 time frame for WinForms projects.

The New Add Object Data Source Dialog

To use a certain class as your Object Data Source, start the binding process as you previously would:

  • Open the Design Binding Picker to add a new Object Data Source definition to your project.

  • Click on the link Add new Object Data Source to find the type you want to use as a data source in your project.

  • Use the Filter field to filter the selection by name. Note that types which implement the `INotifyPropertyChanged` interface (or derive from types which are based on that interface) are formatted in bold typeface.

  • Use the checkboxes in the dialog to include or exclude types, which are not part of your project, or to control how the types are organized in the list.

The example in the animated GIF below shows how a slightly modified ToolStripMenuItem component can be bound this way to a Command, and in addition a DataGridView’s DataSource to a property of a UI-controller representing a list of customers:

An animated gif showing how to use the Design Binding Picker to access the new Add Object Data Source Dialog

Here you see that adding MainUIController as an Object Data Source and then binding its Import command to the ImportExternalDataCommand property automatically led to the adding of the mainUiControllerBindingSource component: In the Design Binding Picker you can then pick that component as the actual data source.

History lesson: why BindingSources as mediators and no direct binding?

Adding a BindingSource component for an Object Data Source as a mediator between the data source and the target control/component is a concept which WinForms adapted from the early beginning (.NET 2.0 back in 2005). The BindingSource component acts as the so-called currency manager. Currency in this context means, the BindingSource component manages which data item in a list of items is the current one. This way of binding is also done for scenarios, for which the data source is or provides only one object instance – a UI-controller or a single data source item for a data entry form for example. This principle is being kept for backwards compatibility reasons, which means that any attempt to bind the first property to a newly added (object) data source will always add a respective BindingSource component to the component tray. The actual binding will then be hooked up to that BindingSource component rather than to the data source directly.

Note: It is important to know in this context, that WinForms doesn’t natively know the concept of type conversion based on the IValueConverter interface as it is used in WPF, UWP or WinUI. Rather, a conversion during binding can be done by handling the events, such as Format and Parse, which are provided by the actual binding instances generated by the designer for the binding in InitializeComponent. Like this:

public FormMain()
{
    InitializeComponent();

    // Current version of WinForms Databinding doesn't allow yet
    // IValueConverter, we do this instead:
    var totalRevenueBinding = _totalRevenueTextBox.DataBindings[0];

    // ConvertTo, here Decimal to String as an example:
    totalRevenueBinding.Format += (sender, eventArgs) =>
    {
        if (eventArgs.DesiredType != typeof(string))
        {
            return;
        }

        eventArgs.Value = ((decimal)eventArgs.Value!).ToString();
    };
    .
    .
    .

In this sample code we are assuming there is only one DataSource/Control binding for a TextBox named _totalRevenueTextBox. We’re getting its Binding definition and wire up to its Format event, where the actual conversion is then handled at runtime.

Improvements to Advanced Databinding

We also made improvements to the Advanced Databinding Editor. You use the Advanced Databinding Editor for all properties which are not listed directly under Data Binding in the Property Browser. This dialog now shows what component or control you are binding to. It also shows what exact type of that control or component you are editing. Also, rather than picking the binding trigger from a drop-down list, you can now directly set that by clicking radio buttons, which is quicker and more accessible.

Animated gif showing how to use the Advanced Databinding Editor to bind property paths in complex binding scenarios

The Advanced Databinding Dialog now allows to set up another binding scenario: Sometimes it’s necessary that you define a whole property path in complex binding scenarios – which are scenarios, where you are binding to a list rather than to a single object instance. In those cases, the correlating BindingPath and BindingField of the Binding’s instance BindingMemberInfo property can now easily be set in the Advanced Databinding Editor by entering the whole path in the Path entry field. If this field gets the focus, Path and Field are merged, and you can edit the property path as a whole. When that entry field later loses the focus again, Path and Field are separated in the same way as they would show up if you’d queried them at runtime through the Binding’s correlating BindingMemberInfo property:

A screenshot of a C# code file in VS showing a BindingMemberInfo instance in the Debugger

Summary and key takeaways

  • Databinding in WinForms .NET is focused on Object Data Binding. We encourage developers to explore modern ORM technologies like Entity Framework Core, which can be used in their latest versions in contrast to .NET Framework.

  • Databinding of legacy technologies (Typed DataSets) is still supported, albeit with some limitations. Typed DataSet definitions can be copied from Framework projects, but new Typed DataSets cannot be created in .NET projects, nor can their schemas interactively be changed.
    Tip: Old and new database mapping technologies can coexist in a WinForms project, so there is a feasible way to gradually migrate the underlying data layer technologies, one Form at a time.

  • Object Data Sources are defined for the project through the Design Binding Picker in the Property Browser by clicking on the Add New Object Data Source link. The Data Source Provider Service is at the time not available for .NET projects (neither WinForms nor WPF). That is also the case for the Data Sources tool window, which relies on the Data Source Provider Service.

  • Object Data Sources are a great tool migrating business “Code-behind” logic from Forms and UserControls into UI-stack-independent controller classes. This way, it becomes easier for WinForms apps to be unit tested or reuse business logic code in other contexts, and also have a clear migration path to introduce modern technologies in WinForms LOB Apps.

  • The Advanced Databinding Dialog is now easier to handle and more accessible. It now also allows the definition for entering property paths for complex binding scenarios.

As always, please tell us which features you would like to see in the Designer but also in the WinForms runtime around the databinding area.

Happy WinForms Coding!

Author

Klaus Loeffelmann
Senior Software Engineer

29 comments

Discussion is closed. Login to edit/delete existing comments.

  • our apks

    Thank you so much. Is this project available on Github? I want to check it further for:

    <code>

    Hopefully i will get it there and do my research further.

    Read more
  • Aivars Ikaunieks · Edited

    I would like to describe my first experience with data binding to EF Core entities. My goal was to make master/detail data entry form with two DataGridView controls. For all entities i implemented IPropertyChanged and IPropertyChanging (with Fody). Enabled ChangeTrackingStrategy ChangingAndChangedNotifications to address some performance considerations. Than i tried to change list type of navigation properties to BindingList, and i could not do it because BindingList does not implement INotifyCollectionChanged. I was really baffled when...

    Read more
  • ayman metwally

    Thanks for that …

    I feel happy when I see improvements to WinForms … It means it’s still alive .. still get updates .. I’m a big WF fan.

    But will it be for long?

  • Marvin Groß · Edited

    Is this project available on GitHub?

    • Michał Ciołek

      I can’t find this on GitHub. I’d love to see this source code too. @Klaus can you publish it?

      • Klaus LoeffelmannMicrosoft employee Author

        The "sample project" for this blog post doesn't have much more than already shown in the post. On top, this post was primarily targeted for showing the new Databinding UI in the new WinForms Designer. Now, I get also from the feedback which reaches me via email in addition, that more and more folks are interested in the Controller/ViewModel approach for WinForms, which this post only addresses partly. I think this is not the right...

        Read more
  • Mauro

    Hi, thank you for this post. I’m so happy WinForms will have long life, I think it’s the best tech for building data/office-automation oriented clients.
    Is this code example available in some repo which we can clone?

    • Kris Golko · Edited

      Office Automation oriented? I wonder if you’re using Microsoft.Office.Interop.Excel package. Had problems with it with Office 365 and ended up switching to OpenXml

    • Klaus LoeffelmannMicrosoft employee Author · Edited

      I’ll like to introduce some sample code in context of #4895 in the WinForms repo. Please also take part in the discussion, if you have additional ideas around that. Thomas already got engaged (thanks!) and had some pretty good ideas around that we should further discuss or consider.

  • Thomas · Edited

    Thanks for this post and sharing some news about the designer and the developer experience.

    I am sad the DataSource browser Treeview in the property grid still doesn't sort the class properties alphabetically. When you have an object with a lot of them it makes the experience really painful. But it's been this way since the beginning, so I must be the only one mumbling about that :D

    I just also discovered the issue #4895 about enhancing...

    Read more
    • Klaus LoeffelmannMicrosoft employee Author

      I am sad the DataSource browser Treeview in the property grid still doesn’t sort the class properties alphabetically.

      I did not have this on my radar, thanks for pointing this out. I’ll take a look, how we can improve this. Shouldn’t be too difficult!

  • Andi

    It's awesome how much time your teem invests to migrate the WinForms-Designer.

    At my actual work I have to use the WinForms-Designer with dotnet-framework 4.7.2. The designer is very buggy on that framework. It's a pain to work with it. For me it is no surprise that your team needs so much much time for migration because the old source is not well.

    I must say, I don't understand why Microsoft invests so much resources for WinForms....

    Read more
    • Thorsten Sommer

      Thank you for the detailed report. I would like to disagree with the comments of Andi and Martin. I too have worked with the WinForms designer in Visual Studio for many years. I cannot confirm that it is buggy. On the contrary, I never had any issues with it. I don't see an issue in the fact that Microsoft has several UI technologies, all of which are maintained. On the contrary, we, the developers, have...

      Read more
      • Andi · Edited

        @Thorsten Sommer
        I don’t see an issue in the fact that Microsoft has several UI technologies, all of which are maintained. On the contrary, we, the developers, have the choice and can select the best technology for each task.

        You are right. In a good world it sounds very nice that we can decide a matching framework. But why you need 4 frameworks which solve the same problem (show something fancy on Windows-plattform).
        What do you...

        Read more
      • Klaus LoeffelmannMicrosoft employee Author

        All these frameworks does the same thing. I cannot say which is the best. An official guide when to choose which one would be nice I think.

        I don't agree. I think that each of those UI-Frameworks have different areas where they shine most, and on top address different team requirements, like design skills, ramp-up-times, accessibility advantages and much more. I wouldn't personally design a LOB app which needs let's more than 400 data...

        Read more
    • Uros Berce

      I’ve been using WinForms on dotnet 3,4 extensively for 15 years, and nothing beats its productivity for UI-heavy apps, nothing! And I honestly do not remember when was the last time I encountered a bug or crash(and it’s a huge project). It just works!;) I am so happy MS decided to stick with, and modernise WinForms. Keep it up!

    • Klaus LoeffelmannMicrosoft employee Author

      At my actual work I have to use the WinForms-Designer with dotnet-framework 4.7.2. The designer is very buggy on that framework. It’s a pain to work with it.

      We should make what you say actionable! Please file a bug (or bugs) along with repros, so we can get that addressed - if it applies of course - in the WinForms Repo.

      I must say, I don’t understand why Microsoft invests so much resources...

      Read more
      • danial hughes

        We all love the investment in WinForms. I have such fond memories of working with it and the improvements to data binding will give it a new lease of life. Seriously long live WinForms!!
        However please, please, please, show some love to WPF. Even the open source repo is barely supported. What's the point of open sourcing it if you're not going to staff the repo to allow the community to make the required updates.Read more

      • Andi · Edited

        We should make what you say actionable! Please file a bug (or bugs) along with repros, so we can get that addressed – if it applies of course – in the WinForms Repo.

        Thanks for that info. I already created some issues for asp- and efcore on GitHub in the past. The GitHub plattform works realy good for contacting the MS-devs.
        But sharing my WinForms problems is not possible for me because of two (or three)...

        Read more
      • Klaus LoeffelmannMicrosoft employee Author

        Hey Andi,

        some thoughts:

        The problems are not in runtime but on designer.

        It's completely fine to report them in the WinForms repo, also because we need to assess if runtime or designer behavior are the root cause. Repros are important though. I know that bugs which only occur in big projects, which are using third party controls on top and probably custom Control Designers are hard to track down and the process can be frustrating...

        Read more
      • gambler4882@yahoo.com · Edited

        <code>

        I've seen viewModels with 10k+ code, just as abused as the code behind. If a developer can't make a difference in what belongs to UI code, and what doesn't, no binding class between View and Model would make his\hers code cleaner.

        We had the architecture where the business logic is abstracted in separate libs, UI should just make calls to the database/webservice and represent the data.

        <code>

        I don't see the problem, you do not have to bind...

        Read more
    • Martin Sedlmair

      I agree with Andi. I appreciate your work and efforts on the WinForms-Designer, but on the other hand there is not so much invest in WPF.
      We have switched a long time ago from WinForms to WPF. I understand that some people need to keep WinForms alive because they don't want to switch or the efforts to switch would be too high.

      The problem also is that don't know how long WPF will live. Nowadays, there's...

      Read more
      • Mauro

        I think the only real alternative to business application as a long term investment is WinForms, and is still maintained not because of the huge "legacy" application still around, but because is the best tool to implement data-entry intensive application in a sustainable timespan. It's just easy and powerfull.
        WPF is made to implement media applications, and the complexity of xaml in complex interfaces is not sustainable.
        All other framework just failed and are now...

        Read more
      • gambler4882@yahoo.com

        It depends, what do you need to do? If you need a simple GUI for a windows business app, Winforms are still the best tool to use. Chose your tool, use the hammer appropriate for the nail.

      • Martin Sedlmair

        As I said, I agree that for simple tools WinForms is pretty suitable, I have used it for a long time. Nowadays I always go with WPF even for smaller tools. But as you said hammer -> nail 😉 The only thing I’m “complaining” is the wide variety of frameworks do do not match and I hope they will merge back again in the future.

      • gambler4882@yahoo.com

        Yup, to many different hammers 😉 I actually agree. And I’m sad that Microsoft did not make something like Uno with a good designer. UI code should be UI code, wherever it runs.