Data Binding

Data binding concepts.

General

In Wisej.NET, data binding refers to the process of connecting UI elements on a Wisej.NET UI container (i.e., Form, Page, UserControl, Desktop, ...) with data sources, such as databases or data objects. This allows the UI to display data from the data source, and to automatically update the data source when the user modifies the data in the UI.

There are two types of data binding in Wisej.NET: simple binding and complex binding.

Simple binding involves binding a single UI element, such as a text box, to a single data field, such as a customer name. When the data source is updated, the value of the text box will automatically be updated to reflect the new value of the customer name field.

Complex binding involves binding a container control, such as a grid, to a data source. Each row in the grid is bound to a record in the data source, and each cell in the grid is bound to a field in the record. When the data source is updated, the grid will automatically be updated to reflect the changes.

Wisej.NET provides several tools and methods for creating and managing data bindings, including the DataBindings editor and the BindingSource component.

Designer

When you are building controls that interact with data, you sometimes need to bind a control to a type, rather than an object. You typically need to bind a control to a type at design time, when data may not be available, but you still want your data-bound controls to display data from a type's public interface.

Bind BindingSource to Type

  1. Create a Windows Forms project (File > New > Project > Visual C# or Visual Basic > Web > Wisej.NET Web Page Application).

  2. In Design view, drag a BindingSource component onto the form.

  3. In the Properties window, click the arrow for the DataSource property.

  4. In the DataSource UI Type Editor, click Add Project Data Source.

  5. On the Choose a Data Source Type page, select Object and click Next.

  6. Select the type to bind to:

    • If the type you want to bind to is in the current project, or the assembly that contains the type is already added as a reference, expand the nodes to find the type you want, and then select it.

      -or-

    • If the type you want to bind to is in another assembly, not currently in the list of references, click Add Reference, and then click the Projects tab. Select the project that contains the business object you want and click OK. This project will appear in the list of assemblies, so you can expand the nodes to find the type you want, and then select it.

  7. Click Next, and then click Finish.

Bind Control to BindingSource

  1. Add a TextBox to the form.

  2. In the Properties window, expand the (DataBindings) node.

  3. Click the arrow next to the Text property.

  4. In the DataSource UI Type Editor, expand the node for the BindingSource added previously, and select the property of the bound type you want to bind to the Text property of the TextBox.

Data Sources

Lists

Developers can bind to a strongly-typed generic list (List<T>) or create a new BindingList<T> implementation to bind data to.

List<T>

The List<T> class is the generic equivalent of the ArrayList class. It implements the** IList<T>** generic interface by using an array whose size is dynamically increased as required.

You can add items to a** List<T> **by using the Add or AddRange methods.

BindingList<T>

The BindingList<T> class can be used as a base class to create a two-way data-binding mechanism. BindingList<T> provides a concrete, generic implementation of the IBindingList interface. This is an alternative to implementing the complete IBindingList interface, which can be difficult because of the subtle interaction between IBindingList, IEditableObject, and the associated CurrencyManager. However, the typical solutions programmer will use a class that provides data binding functionality, such as BindingSource, instead of directly using BindingList<T>.

BindingList<T> supports factory-created instances through the extensible AddNew method. (This same type of extensibility is also found in other classes, such as BindingSource) In addition, since this class implements the ICancelAddNew interface, it enables transactional commits or rollbacks of the new item through the EndNew and CancelNew methods.

var data = new List<dynamic>
{
	new { id = 1, name = "John" },
	new { id = 2, name = "Jane" },
	new { id = 3, name = "Jared" }
};

this.dataRepeater1.DataSource = data;

this.textBoxID.DataBindings.Add(new Binding("Text", data, "id"));
this.textBoxName.DataBindings.Add(new Binding("Text", data, "name"));

ADO.NET

ADO.NET provides consistent access to data sources such as SQL Server and XML, and to data sources exposed through OLE DB and ODBC. Data-sharing consumer applications can use ADO.NET to connect to these data sources and retrieve, handle, and update the data that they contain.

Entity Framework

Entity Framework Core is a modern object-database mapper for .NET. It supports LINQ queries, change tracking, updates, and schema migrations. EF Core works with many databases, including SQL Database (on-premises and Azure), SQLite, MySQL, PostgreSQL, and Azure Cosmos DB.

LINQ

Language-Integrated Query (LINQ) is the name for a set of technologies based on the integration of query capabilities directly into the C# language. Traditionally, queries against data are expressed as simple strings without type checking at compile time or IntelliSense support. Furthermore, you have to learn a different query language for each type of data source: SQL databases, XML documents, various Web services, and so on. With LINQ, a query is a first-class language construct, just like classes, methods, events.

Example:

var data = new List<dynamic>
{
	new { id = 1, name = "John" },
	new { id = 2, name = "Jane" },
	new { id = 3, name = "Jared" }
};

var filter = data.Where(record => 
record.name.StartsWith("Ja")).ToList();

this.dataRepeater1.DataSource = filter;

this.textBoxID.DataBindings.Add(new Binding("Text", filter, "id"));
this.textBoxName.DataBindings.Add(new Binding("Text", filter, "name"));

Result:

Currency Manager

The CurrencyManager in Wisej.NET manages a list of Binding objects.

BindingContext

Each Wisej.NET Form has at least one BindingContext object that manages the BindingManagerBase objects for the form. Because the BindingManagerBase class is abstract, the return type of the Item[] property is either a CurrencyManager or a PropertyManager. If the data source is an object that can return only a single property (instead of a list of objects), the Type is a PropertyManager. For example, if you specify a TextBox as the data source, a PropertyManager is returned. On the other hand, if the data source is an object that implements IList or IBindingList, a CurrencyManager is returned.

For each data source on a Wisej.NET Form, there is a single CurrencyManager or PropertyManager. Because there may be multiple data sources associated with a Wisej.NET Form, the BindingContext enables you to retrieve any particular CurrencyManager associated with a data source.

Formatting

The Format event is raised when data is pushed from the data source into the control. You can handle the Format event to convert unformatted data from the data source into formatted data for display. When data is pulled from the control into the data source, the Parse event is raised to unformat the displayed value, then the Format event occurs to reformat the data for display. This ensures that the bound control displays correctly formatted data regardless of whether the user enters formatted or unformatted data in the control.

private void DecimalToCurrencyString(object sender, ConvertEventArgs e)
{
   if(e.DesiredType != typeof(string)) 
      return;
   
   e.Value = ((decimal) e.Value).ToString("c");
}

private void CurrencyStringToDecimal(object sender, ConvertEventArgs e)
{
   if(cevent.DesiredType != typeof(decimal)) 
      return;

   e.Value = Decimal.Parse(e.Value.ToString(), NumberStyles.Currency, null);
}

private void BindControl()
{
   var binding = new Binding("Text", data, "value");
   
   binding.Format += new ConvertEventHandler(DecimalToCurrencyString);
   binding.Parse += new ConvertEventHandler(CurrencyStringToDecimal);
   
   this.textBox1.DataBindings.Add(b);
}

Events

The Format event is raised when data is pushed from the data source into the control. You can handle the Format event to convert unformatted data from the data source into formatted data for display. When data is pulled from the control into the data source, the Parse event is raised to unformat the displayed value, then the Format event occurs to reformat the data for display. This ensures that the bound control displays correctly formatted data regardless of whether the user enters formatted or unformatted data in the control.

The Format and Parse events allow you to create custom formats for displaying data. For example, if the data in a table is of type Decimal, you can display the data in the local currency format by setting the Value property of the ConvertEventArgs to the formatted value in the Format event. You must consequently unformat the displayed value in the Parse event.

INotifyPropertyChanged

The INotifyPropertyChanged interface is used to notify clients, typically binding clients, that a property value has changed.

For example, consider a Person object with a property called FirstName. To provide generic property-change notification, the Person type implements the INotifyPropertyChanged interface and raises a PropertyChanged event when FirstName is changed.

For change notification to occur in a binding between a bound client and a data source, your bound type should either:

  • Implement the INotifyPropertyChanged interface (preferred).

  • Provide a change event for each property of the bound type.

Do not do both.

Last updated