Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Binding any object data members at design time

0.00/5 (No votes)
8 Nov 2004 1  
Enables binding of any public data member of any object into a control at design time.

Introduction

The AgConfig class enables binding of any public data member of any object into a control at design time. It automatically handles synchronization between a data member of an object and the contents of a bound control.

It was primarily designed to simplify the work with settings data and creation of settings forms. With this utility class, it is easy to:

  • access data in public data members of an object
  • bind public data members of an object to controls at design time
  • serialize the data to/from an XML file

Background

I was always wondering to have a simple way for creating settings forms and store settings data in a file.

A Control.DataBinding can be used to bind a control's property to the property of any object. However, this can not be done at design time unless the object is a DataSet, DataTable, or a few other classes from System.Data namespace.

A DataSet can be easily constructed for any class using Microsoft's XSD utility which is part of VS.NET. This enables us to bind controls to a DataSet at design time. DataSet also provides a simple way for storing its contents to an XML file. But accessing DataSet contents programmatically is a bit more complicated than accessing object's members.

It would be nice to have a tool that automatically synchronizes object data members with the DataSet contents. So, we could programmatically access our settings through data members of an object and create settings forms easily just by binding the object data members to controls at design time.

Using the code

Usage of the AgConfig class can be divided into several categories:

  1. creating a settings class
  2. creating a DataSet from the settings class
  3. creating a settings form
  4. reading and writing XML data

1. Creating a settings class

Settings data is represented by public data members of our class, for example the AppData class, which demonstrates how to create embedded classes to divide settings into sections and also how to create arrays of objects. Note the syntax for creating arrays, the Array object must be created even empty.

The settings class must have a public default constructor (the one with no arguments) to make it serializable by XmlSelizer.

public class AppData
{
    public string Text = "Hello there";
    public int Number = 7;
    
    public class Section1Class
    {
        public string Text1 = "Hello there 1";
        public int Number1 = 77;
    }

    public Section1Class Section1 = new Section1Class();

    public class Item
    {
        public int ID;
        public string Name;
    }
    
    public Item[] Items = new Item[] {};
}

Maybe, it is a good idea to put the AppData class into a separate class library.

2. Creating a DataSet

To create a DataSet from a settings class, we can use the Microsoft's XSD command line utility which is part of VS.NET. This utility reads the type information from an assembly, so we need to rebuild our project first (ConfigTest).

The command line for the XSL utility looks like follows:

<KBD>xsd configtest.exe /type:AppData</KBD>

After running the above command, a schema0.xsd file containing the XSD schema for AppData type is created in the current directory. Add this file into the project by clicking the "Project/Add Existing Item..." menu item, and rename it to AppData.xsd for convenience.

Generating DataSet from this schema can be done by double clicking the AppData.xsd file in Solution Explorer and checking the "Schema/Generate Dataset" menu item.

Finally, the targetNamespace and id properties of the created DataSet must be set to match the way AgConfig class will handle them. Set the targetNamespace to "ConfigTest.AppData" (in the form "<application name>.<class name>") and id to "AppDataDataSet" (in the form "<class name>DataSet").

3. Creating a settings form

The example settings form contains a DataGrid control which is bound to a AppDataDataSet component on the form (created by dragging the DataSet component from the toolbox and selecting the typed AppDataDataSet). The following code in settings form makes things work together:

private AgConfig AppDataConfig = new AgConfig(Settings.AppData);
// settings form's AgConfig object

Following code is part of the settings form constructor. config1 is initialized so that it automatically reflects changes made in controls bound to appDataDataSet1 into data members of Settings.AppData (which is a static instance of AppData class).

AppDataConfig.DataSet = appDataDataSet1;

4. Reading and writing XML data

Settings object data (Settings.AppData) can be read or written from/to an XML format using several methods provided by AgCondig class. (See ReadFromXmlxxx() and WriteToXmlxxx() methods).

This is an example of serialized XML data:

<?xml version="1.0"?>
<AppDataDataSet xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <AppData>
    <Text>Hello there</Text>
    <Number>7</Number>
    <Section1>
      <Text1>Hello there 1</Text1>
      <Number1>77</Number1>
    </Section1>
    <Items>
      <Item>
        <ID>1</ID>
      </Item>
      <Item>
        <ID>2</ID>
      </Item>
    </Items>
  </AppData>
</AppDataDataSet>

Other properties and methods of AgConfig class are:

  • XmlExtraTypes

    Type array of additional object types to serialize (see XmlSerializer constructor for details).

  • FileName

    Fully qualified name of file for storing XML data. By default, this is a file in the application startup directory with the name of Data object and ".xml" extension.

  • XmlRootName

    Name of the root XML element for serialization. By default, this is the name of Data object.

  • XmlNamespace

    Target namespace for serialization. By default, this is dot separated application name and Data object name.

  • DataSet

    A DataSet associated with this instance. By default, this is an untyped DataSet with schema inferred from Data object's XML data.

  • Data

    Actual object that holds settings data.

  • WriteToXmlFile(string file)

    Serializes Data object data into an XML file.

  • ReadFromXmlFile(string file)

    Deserializes Data object data from an XML file.

  • ReadFromXmlStream(Stream s)

    Deserializes Data object data from a stream.

  • WriteToXmlStream(Stream s)

    Serializes Data object data into a stream.

  • WriteToDataSet(DataSet ds)

    Populates a DataSet with Data object data.

  • ReadFromDataSet(DataSet ds)

    Retrieves Data object data from a DataSet.

Remarks

Changes made in controls bound to AgConfig.DataSet are automatically reflected into corresponding AgConfig.Data object data members.

To reflect changes made directly to AgConfig.Data object data members into AgConfig.DataSet, the AgConfig.WriteToDataSet() method has to be called.

An XmlSerializer is used to serialize data. Because of this, only public data members are serialized. Some classes from .NET framework library can not be serialized this way. An example of such a class is Drawing.Color, which has no public data members and hence it can not be serialized using XmlSerializer. One way to workaround this problem is to create a wrapper class that publishes non-public properties. Another way is to add a new property to settings class that serializes Color as a string and uses XmlIgnore and XmlElemrnt attributes to disable serialization of original property and change the XML element name of the new property.

Points of Interest

The key point was to find out how to serialize an object using XmlSerializer that it can be deserialized using DataSet.ReadXml() method and vice versa.

History

This is the initial release.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here