|
|||||||||||||||||||||
|
|||||||||||||||||||||
|
Announcements
Want a new Job?
Chapters
Services
Feature Zones
|
IntroductionIn the first two articles in this series, we looked at the ADO.NET operations an object-oriented programmer would use to load data from a database to an object model, and the operations used to save the data back to the database. We also explored how to use the data binding capabilities of .NET 2.0 to bind an object model to UI controls in the presentation layer. We will continue our discussion of both subjects in this, the third and last article in the series. First, we will see how to use ADO.NET to serialize an object model. It turns out that ADO.NET can be very helpful in situations where our model does not fit neatly into a single object graph. Once we have finished with serialization, we will look at how to bind our object model to user controls. It’s not difficult, but it’s not terribly well documented, either. With these two techniques in hand, an object-oriented programmer should be ready for most day-to-day challenges encountered in developing .NET applications.
The Demo ApplicationThe demo application for this article illustrates these two techniques. It is based on the Authors/Books database from Part Two:
But this time, we aren’t going to load the object model from a database—we’re going to load it from an XML file. And instead of editing in the grid, as we did in Part Two, we provide a separate Edit Author Info panel to update author information. Serializing and Deserializing Object ModelsAs you are probably aware, .NET classes can be serialized and deserialized by simply marking them as The technique works well for simple object models that fit neatly into a single object graph. There are more advanced serialization techniques available for more complex object models, and even models with multiple object graphs can be handled with basic serialization by containing the various root objects within a master root object. But as serialization users know all too well, serialization can be temperamental, and it isn’t always easy to get working correctly. ADO.NET provides the opportunity for a different strategy—transfer the object model data to an ADO.NET data set, then serialize the data set. This approach can be far easier than fiddling with direct serialization, and it can handle very complex object models without breaking a sweat. An ADO.NET data set has a built in serializer. We don’t have to instantiate formatters or file streams—we can save a data set to an XML file with a simple command: // Save the data set to an XML file
dataSet.WriteXml(filePath);
We can load an XML file into a data set just as easily: // Load the data file into a new dataset
DataSet dataSet = new DataSet();
dataSet.ReadXml(filePath);
What makes this approach particularly attractive is the fact that an ADO.NET data set can have as many tables as one needs to capture a complex object model. Each root class can have its own table, and each class contained within that root can have its own table, as well. Root class tables are related to the tables that correspond to their contained classes using We will discuss serialization and deserialization more fully in our walkthrough of the demo application. For now, let’s turn our attention to the subject of data binding to user controls. Data Binding to User ControlsWhen you look at the Presentation layer of the demo application, you will probably notice that the Edit Author Info group is contained in a separate user control. Wouldn’t it have been easier to dispense with the user control and place the group directly on the form? In the demo app, it certainly would be easier, and you would probably never use a user control in an app as simple as this one. However, consider the following: I am currently working on an application that uses six different types of transactions. Each type of transaction derives from a To make matters more challenging, the properties aren’t all simple strings or Booleans. There is a fair amount of presentation logic associated with each transaction type, and the logic is somewhat different for each type. It’s the sort of situation that cries out for a user control. In the real-world application, my data entry form is laid out much the same as in the demo app. The grid is a detail view in a Customers-Transactions pair. It shows the transaction date and description; the edit form shows complete details for the transaction. When the user selects an item in the grid, the app traps the The demo app is much simpler—it has only one user control, whose data bindings are set in the Designer, rather than code. However, the real-world app uses the same techniques as the demo app. The only difference is in the run-time activation and deactivation of multiple user controls. Data binding to a user control: Data binding is simple when we can bind to .NET controls. As we saw in Part Two, we simply create and configure a But things get more interesting when we data bind to user controls. We need to add some infrastructure to our user controls before they will support data binding. The first bit of infrastructure to add is a
The
The attribute enables design-time specification of data bindings, but without more, the bindings won’t work. To make them functional, we need a way to notify the A data binding listens for an event called #region Declarations
// Property change events
public event System.EventHandler FirstNameChanged;
public event System.EventHandler LastNameChanged;
public event System.EventHandler SocSecNoChanged;
#endregion
When a property changes, we need to fire the appropriate private void textBoxFirstName_TextChanged(object sender, EventArgs e)
{
if (this.FirstNameChanged != null)
{
this.FirstNameChanged(this, new System.EventArgs());
}
}
So, with these two pieces of infrastructure in place, our object model can be bound to our user control. Timing of the PropertyChanged event: By default, the firing of a This approach causes all kinds of problems. The most obvious occurs when the I prefer to force the data binding to read the changed value as soon as the void DataBindings_CollectionChanged(object sender,
CollectionChangeEventArgs e)
{
// Set data bindings to update on property change
foreach (Binding binding in this.DataBindings)
{
binding.DataSourceUpdateMode =
DataSourceUpdateMode.OnPropertyChanged;
}
}
This approach avoids the “lost data” problem, and it creates a better experience for the end user. Notice in the demo app that information appears in the grid as each character is typed in the text boxes of the user control. This feature gives the user immediate confirmation that their entry is being recorded by the application. Communicating Changes to the Object ModelIn .NET 2.0, Microsoft introduced a new interface to handle communications from an object model to a data binding. The Note that the demo app doesn’t use the That point may be valid. On the other side, I would argue that the Nonetheless, if you are a strict constructionist on such matters, you may prefer to take the Command object route to the object model. In that case, your collections and their members should implement the Demo Application WalkthroughAnd that brings us back to the demo application. It is organized in much the same manner as the demo app in the Part Two of this series. The major differences between the two are:
The application deliberately simplifies things to the point of over-simplification. For example, the edit panel shows the same information as the grid. In a real-life application, the edit panel would show far more detail than the grid. The User Interface: The UI consists of a The Main form has four buttons; Open, Save, Add, and Delete. The Open button invokes a standard File Open dialog to open the XML data file. The file is located in the top level of the solution folder (the same folder as the .sln file). The Save button saves the file to the same location from which it was opened—no Save As functionality is provided. The Add and Delete buttons invoke add and delete operations on the Architecture: The architecture of the application is basically the same as the demo app in Part Two of this series. The application is organized according to the Model-View-Controller pattern, and Command objects are used to encapsulate the functionality of the Controller. The use of an XML file, rather than a database, simplifies the control aspects of the application, resulting in fewer Command objects than in Part Two. Data Access: The DAO object in this application differs from that in Part Two, in that we don’t need a lower-level The DAO loads both the Authors and Books lists into the object model, even though the Presentation layer only uses the The Object Model: The object model is virtually unchanged from Part Two. The only changes made involves removing the methods that linked business objects to their corresponding DAO objects. These methods were replaced by two methods in the The UserControl: For example, a user control might contain a property representing a business rule, and three radio buttons representing options for that rule. When the user selects a radio button, user control code would set the property to the appropriate option. Thus, the contained controls would be connected to the user control property only indirectly, through code.
As we discussed above, note the ConclusionWell, hopefully, that should do it. As I mentioned at the outset of this series, I began it as a learning exercise, and continued it as I encountered issues during development of real-world applications. So where are we now? At this point, you should be able to move data from a database or an XML file to and from an object model. You should be able to work with that model using MVC architecture, and you should be able to use .NET 2.0 data binding to move information between the object model and the UI of your application. Moreover, you should be able to create UIs that range from simple master-detail patterns to very complex summary-detail patterns involving multiple, alternating data-entry forms. For the life of me, I can’t think of anything else that needs to be covered. Of course, that’s what I said after Part Two. If you read Part One, you may remember I said that the point of ADO.NET for object programmers is to be able to spend more time with one’s spouse and children. I began this series just after Christmas—as I finish it, it’s nearly Valentine’s Day. If I stop now and rush out to the mall, I should have just enough time to buy my wife a Valentine’s Day present and card. See you later! | ||||||||||||||||||||