Design-Time Data Sources






Design-Time Data Sources

You use VS05's Data Sources window to identify and create data sources for a project. You open the Data Sources window, shown in Figure, by choosing Data | Show Data Sources from the VS05 main menu.

15. Data Sources Window in VS05


When a project has no data sources, the Data Sources window displays a comment to make sure you know about it, and it gives you two mechanisms for adding a new one: the Add New Data Source link label or its tool strip button counterpart.[8] Either way opens the Data Source Configuration Wizard, shown in Figure.

[8] You can also add a data source to your project by clicking Data | Add New Data.

16. Data Source Configuration Wizard


Here, you create a data source to encapsulate data stored in a database, a web service, or a .NET type.

Databases

Arguably the most common location of data is within a database and, therefore, is the most common data to expose as a data source for data binding. Visual Studio has always provided the means to encapsulate data located in databases using typed data sets. A typed data set is a class that contains one or more database tables, views, stored procedures, and functions, each of which is exposed as a strongly typed .NET class. Each of these needs to be loaded with data from the database and, in some cases, needs to update the database with any changes. This work is performed by a typed table adapter. VS05 automatically creates one for each database object exposed from a typed data set.

To use the Data Source Configuration Wizard to facilitate the creation of typed data sets and table adapters, you choose the Database option, as shown in Figure. This process revolves around selecting one or more tables, stored procedures, or views that will supply the data you require. The next step is to identify the desired database by choosing a database connection, shown in Figure.

17. Choosing a Data Connection


Although supplying a connection string at design time helps our data binding configuration, we'll need the same connection string at run time. Consequently, the Data Source Configuration Wizard next asks you whether you want the database connection to be stored as an application setting, as shown in Figure.[9]

[9] By splitting out the connection string as an application setting, you can easily change it so that applications can use different database servers as dictated by deployment. See Chapter 15: Settings for more information on application settings and how they're used.

18. Persisting a Data Connection as an Application Setting


If you choose yes, the setting shown in Figure is added to your application-wide settings.

19. Storing the Database Connection String as an Application Setting


With your database connection string in hand, the Data Source Configuration Wizard can interrogate the desired database for all database objects that expose data. If the database is SQL Server, this includes tables, views, stored procedures, and functions, as shown in Figure.

20. Choosing Database Objects


After you choose the desired database objects and specify the name of the generated typed data set, you click the Finish button to complete the process. This creates the typed data set with the name you specified as an .xsd file added to your VS05 project root, as shown in Figure.[10]

[10] Typed data sets are a world unto themselves, and further exploration is beyond the scope of this book.

21. A Generated Typed Data Set with a Single Table and Corresponding Typed Table Adapter


Any typed data set (.xsd) is automatically detected by VS05whether it was produced via the Data Source Configuration Wizard or added manuallyand is listed in the Data Sources window, as shown in Figure.

22. The Generated Typed Data Set as a Data Source


In Figure, you can see the new Northwind typed data set, which includes the Employees table. Each field in the table is displayed with an icon that hints at the type of data it represents. Additionally, the middle two tool strip buttons are enabled (they weren't in Figure). With these two new buttons, the Data Sources window tool strip allows you to edit and reconfigure the typed data set.[11]

[11] When reconfiguring your database data source, the Data Source Configuration Wizard isn't comprehensive: It highlights column name changes for you, but it doesn't highlight columns whose data types, default values, and nullability have been changed.

Web Services

As you know, data sources are simply instances of item or list types. In the case of a database, each table is a list data source. On the other hand, to bind to data exposed via a web service means binding to a type exposed by that service.[12] The purpose of the Data Source Configuration Wizard, with respect to web services, is to turn types exposed from a web service into .NET-specific data sources against which you can bind.

[12] Typically, web services that expose types you'd like to bind to expose the necessary web methods to retrieve instances of those types and to update the state of those instances.

To create a data source for a web service-exposed type, you begin by selecting the Web Service option when you open the Data Source Configuration Wizard, which then opens the Add Web Reference dialog to allow you to locate the desired web service, as shown in Figure. [13]

[13] The Add Web Reference dialog is also displayed when you add a web reference to your project.

23. Choosing a Web Service That Exposes the Type You Want to Turn into a Data Source


You need to choose a web service that implements web methods that return item or list data source objects. To complete the process, you select the web service's service description, shown in Figure. This indicates the Web Services Description Language (WSDL) document that enables VS05 to generate a .NET class that maps to the web service.[14]

[14] WSDL is an XML format for describing web service end points. See http://www.w3.org/TR/wsdl (http://tinysells.com/37).

24. Selecting the WSDL Web Service Description


Clicking the Add Reference button finalizes your choice. The wizard navigates to the final summary page, which lets you know what you've gotten yourself into, as shown in Figure.

25. Confirming the Addition of the Specified Web Service to Your Project


When you click Finish, the web reference is added to your project, and all types from the web service that expose public properties are automatically listed in the Data Sources window, as shown in Figure.[15]

[15] See Chapter 18: Multithreaded User Interfaces for further discussion of VS05's web service support.

26. Web Service Data Sources Available from the Data Sources Window


As with typed data sets, web references added using either the Data Source Configuration Wizard or manually are listed automatically in the Data Sources window.

The example in Figure shows that the Employees web service we referenced operates over a typed data set for the Northwind database and, consequently, has re-created a familiar-looking data source. However, you can import any type exposed from any web service described with WSDL anywhere in the world.

Objects

Any typed data sets and public types exposed from referenced web services are automatically turned into data sources, but not all other types visible to your project are. The reason is that any object with public properties can conceivably become a data source, so automatically turning them into data sources would become quite unwieldy. To avoid this problem, VS05 supports a model that requires you to opt-in local and referenced .NET types as data sources.[16]

[16] It is possible to opt-in COM components as data sources, although it is not as robust an option as using native .NET types. Be sure to test this choice rigorously.

To turn one of these types into a data source, choose Object when you open the Data Source Configuration Wizard. The wizard navigates to a page from which you can choose the desired type, as shown in Figure.

27. Object Data Sources Available from the Current Project


The Data Source Configuration Wizard scans the entire project for possible types, including forms, typed data sets, and web services, all grouped by namespace. With a click of the check box, you can show or hide any types in referenced assemblies that begin with "Microsoft" or "System." Notice in Figure that the text box beneath the object list displays a description of the selected object. This description is derived from the XML summary comment at the top of the class:

/// <summary>
/// RaceCarDriver stores information about a Formula 1 race car driver.
/// </summary>
class RaceCarDriver : INotifyPropertyChanged {...}

When you've picked the desired type, click Finish to turn it into a data source. As with data sources for databases and web services, an object data source appears in the Data Sources window, as shown in Figure.

28. Object Data Source Added to the Data Sources Window


If the desired type is not located in your project, you reference it by clicking the Add Reference button in the Data Source Configuration Wizard (Figure). This opens VS05's standard Add Reference dialog, shown in Figure.

29. Referencing a .NET Assembly


Here, you can reference .NET assemblies located in the assembly cache, a project, the file system, or the list of most recently referenced assemblies. When you make your choice and click OK, the Data Source Configuration Wizard assembly list is updated with your selection, allowing you to then find the type from which you want a data source to be composed. An example is the Employee type, located in the EmployeesAssembly, as shown in Figure.

30. Selecting the Employee .NET Type to Be Turned into a Data Source


When you select your type and click Finish, the new data source is available in the Data Sources window, as shown in Figure.

31. Data Source Based on a .NET Type Located in a Different Assembly


Notice that data sources based on types located in referenced .NET assemblies are categorized by namespace.

Configuring the BindingSource

After you've designated a type as a data source and you've dropped a BindingSource component onto your form, you reference the former from the latter to enable data binding against the BindingSource. This involves setting the BindingSource component's DataSource property with the desired data source, as shown in Figure.

32. Configuring the BindingSource with a Data Source


All currently identified data sources are listed in the DataSource property's drop-down, under Other Data Sources | Project Data Sources. Note that you also have the option to add a new data source to your project, if you haven't already, using the Data Source Configuration Wizard.

In this example, the selected data source is represented in the Properties window, as shown in Figure.

33. BindingSource with a Configured Data Source


The following code is generated by the Windows Forms Designer when a data source is hooked up to a BindingSource from the Properties window (it should seem familiar):

// IDEDataBindingForm.Designer.cs
partial class IDEDataBindingForm {
  ...
  BindingSource bindingSource;
  ...
  void InitializeComponent() {
    ...
    this.bindingSource = new BindingSource(this.components);
    ...
    // bindingSource
    this.bindingSource.DataSource =
      typeof(DataBindingFundamentalsSample.RaceCarDriver);
    ...
  }
}

For data sources that aren't containers for other data sources (such as typed data sets), you need only set the DataSource property. However, for those that are containers, you also need to identify the contained data source you'd like to bind to. Contained data sources are known as data members and are referenced from the BindingSource component's aptly named DataMember property. Use the Properties window, as shown in Figure.

34. BindingSource with a Configured Data Source and Data Member


The Properties window is smart enough to inspect the data source for all possible data members and, as you can see in Figure, list them for your selection. The Windows Forms Designer-generated code to reflect your selection is shown here:

// IDEDataBindingForm.Designer.cs
partial class IDEDataBindingForm {
  ...
  void InitializeComponent() {
    this.components = new System.ComponentModel.Container();
    this.bindingSource = new BindingSource(this.components);
    this.northwindDataSet = new NorthwindDataSet();
    this.employeesTableAdapter = new EmployeesTableAdapter();
    ...
    // bindingSource
    this.bindingSource.DataMember = "Employees";
    this.bindingSource.DataSource = this.northwindDataSet;
    ...
    // northwindDataSet
    this.northwindDataSet.DataSetName = "NorthwindDataSet";
    ...
    // employeesTableAdapter
    this.employeesTableAdapter.ClearBeforeFill = true;
    ...
  }
  ...
  IContainer components = null;
  BindingSource bindingSource;
  NorthwindDataSet northwindDataSet;
  EmployeesTableAdapter employeesTableAdapter;
}

As you can see, the BindingSource component's DataSource and DataMember properties are set as expected. Perhaps unexpectedly, however, the Windows Forms Designer has taken the liberty of adding the NorthwindDataSet component to the form, referencing it directly from the DataSource property and eschewing the special typeof syntax. This special behavior is covered in Chapter 17.

An EmployeesTableAdapter component has also been added to the form. When a data member is selected for a data source that's a typed data set, the Windows Forms Designer is smart enough to find a corresponding typed table adapter, if one exists, and drop it onto the form. Typed table adapters are also components, and their primary role is to facilitate data persistence for the database object that's represented by the data member.

Data Source Persistence

In most cases, data sources need to be filled, at least initially, with data from a data store. For typed data sets, the role of managing persistence is delegated to typed table adapters, one of which is created for each data member in a typed data set. When you use the Properties window to configure a BindingSource component's DataSource and DataMember properties, the Windows Forms Designer not only adds both typed data sets and typed table adapters to a form, but it also generates the following code to load the typed data set with data from the database:

// IDEDataBindingForm.cs
partial class IDEDataBindingForm : Form {
  ...
  void IDEDataBindingForm_Load(object sender, EventArgs e) {
    // TODO: This line of code loads data into the
    // 'northwindDataSet.Employees' table. You can move
    // or remove it, as needed.
    this.employeesTableAdapter.Fill(this.northwindDataSet.Employees);
  }
}

In this code, the typed table adapter loads data into the Northwind typed data set's Employees table by invoking the former's Fill method. Details of the database connections and commands are handled internally by both the typed data set and the table adapter. In fact, if you saved the database connection string as an application setting, the typed table adapter interrogates the setting directly.

Although the code to load a typed data set is generated for you, you're on your own if you need to update the data store with any changes. The typed table adapter exposes the Update method for just this purpose:

// IDEDataBindingForm.cs
public partial class IDEDataBindingForm : Form {
  ...
  void IDEDataBindingForm_Load(object sender, EventArgs e) {
    // TODO: This line of code loads data into the
    // 'northwindDataSet.Employees' table. You can move
    // or remove it, as needed.
    this.employeesTableAdapter.Fill(this.northwindDataSet.Employees);
  }

  void IDEDataBindingForm_FormClosing(
    object sender, FormClosingEventArgs e) {
    // Save updates back to the Northwind database's Employees table
    this.employeesTableAdapter.Update(this.northwindDataSet.Employees);
  }
}

It's easy for the Windows Forms Designer, typed data sets, and table adapters to provide a persistence framework because they all leverage ADO.NET, which provides a consistent, reliable model for doing so. Unfortunately, the same is not true for data sources created from types located in web services or assemblies. In these situations, you need to manually write the code to load and save data.

Whether you can load data into or save data from a data source, however, the simple act of specifying a BindingSource component's DataSource (and, if required, DataMember) properties does allow you to declaratively bind your UI.



 Python   SQL   Java   php   Perl 
 game development   web development   internet   *nix   graphics   hardware 
 telecommunications   C++ 
 Flash   Active Directory   Windows