Wednesday, April 16, 2008
Data Load Controllers
We have recently introduced a fully-automatic way of creating external data loading mechanisms. This is achieved by means of so-called "data load controllers". So what is the basic idea behind these? Well, I am glad you asked! :-)
Milos provides great ways to load data in all kinds of data edit forms, from Windows to the Web, in all kinds of variation. For instance, one can simply use the SetEntityType<>() method to automatically load an entity of a certain type in a window or a web form. It is also possible to override LoadContents() and LoadSecondary() data methods to load additional data, or load it in slightly different ways.
This makes for easy ways of loading data. However, in some scenarios, we want to go even further. (We will always continue to support this approach as it provides the basis for all operations, but we want to provide more options). There are a few scenarios we want to simplify. Here are those considerations:
- This approach generally relies on inheritance. That is OK in many scenarios, but in some scenarios (such as ASP.NET web forms or WPF/Silverlight XAML), there are scenarios where one just wants to use an object instance for data loading. For instance, one might want to put a data panel into a web form without explicitly subclassing it. Those scenarios are currently supported by means of an event model. That is not a bad approach, but it is slightly different from the inheritance model, and the written code is not IL-compatible, since method signatures are differently, and so forth.
- Different interfaces may have a need to load the same data. For instance, 10 different forms of a windows application may need to load certain lookup tables. Or, an ASP.NET web form may need to load the same exact data as the WinForms or WPF equivalent. Neither the inheritance, nor the event model allows for simple code reuse in these scenarios.
- It is very hard to unit test data loading for UIs if the code is embedded in, or attached to the user interface classes.
We now provide an additional abstract option: All the data loading (and data handling) code can be put in an abstract class. Here is an example of such a class:
public class NameEditLoader : DataLoadController
If you are familiar with current Milos loading code, then you will recognize all of this, because the code is identical to code that would go into a Windows Forms class as well as other types of UI classes. The main difference is that this code now sits in an external class. This class can now be used in an interface class. For instance, it could be used in a Windows Form or a WPF window like so:
public MyWindow() // Constructor
public override void Configure()
public override object LoadSecondaryData()
NameBusinessObject names = NameBusinessObject.NewInstance();
DataSet dsNames = names.GetList();
The same exact object can also be used on a web form:
protected void Page_Load(object sender, EventArgs e)
The same object could also be used in XAML, or in a mobile app, and so forth. Also, the object can now be used stand-alone in unit test scenarios, which is extremely important in test driven development (TDD) and other scenarios where unit tests are needed. (And most applications need unit tests these days).
So we think this is a cool change. It is completely optional and everything that was there before is still available. But going forward, this is clearly the recommended approach.
Posted @ 4:08 AM by Egger, Markus (email@example.com) -
Thursday, April 10, 2008
Milos Web Development supports jQuery
<!-- Other stuff here... -->
<add verb="*" path="Milos_simplewebcontrols_*.aspx"
With this in place, you can simply add a <script> element to your page to get the jQuery features:
Note: This aspx page does not really exist. Whenever this URL gets hit, Milos intercepts the call and returns a dynamically generated script stream to the client.
With this in place, you can now add jQuery stuff like this:
alert("Main document content loaded!");
For more information on jQuery syntax and features, visit www.jscript.com, or get one of the many jQuery books out there (the jQuery site lists several).
Note: Milos also uses jQuery features for some of its advanced scripting. For this reason, it could happen that the script reference gets included multiple times, which could lead to unexpected results. For that reason it is better to add the script reference in the Load() event of the page (or a control) using this code:
This automatically adds the script reference from above, but it only adds it if the reference isn't there already.
There is a lot of cool stuff that can be done with jQuery, from simplified event handling to relatively advanced (for HTML) visual effects. Milos uses this for a number of things, such as the cool new overlay dialogs. But that is a topic of a different post... :-)
Posted @ 1:03 PM by Egger, Markus (firstname.lastname@example.org) -
Friday, April 04, 2008
Lessons learned - Little new ones, big old ones
We’ve got an in-house application that we’re working on as a training exercise. Like most projects of this type we find ourselves relearning old lessons.
We wanted to extend the functionality of the standard windows DateTimePicker control by creating a new composite control with a DateTimePicker and adding spinners for hours/minutes. We started out with the DateTimePicker and two spinners (pretty obvious first step) and gave the class a DateTime property to hold the core DateTime value. We then data bound the DateTimePicker and the two spinners to the DateTime property. The DateTimePicker was bound to the DateTime property and the spinners were hooked up to the hour or minute components of class’ DateTime property.
We wired everything up and tried running the shell application. Every time we touched the composite control we got exceptions revolving around one of the constituent controls (dtPicker or spinner) having a null value. Mike Yeager wandered in and made the fateful observation that we had “grossly over engineered” the composite control by having each constituent control separately data bound to the same property. After all, the entire DateTime value was stored within the dateTimePicker control.
We removed the databinding of the two spinners to the DateTime property and created properties for hours and minutes that were based on the existing hour/minute components of the dateTimePicker. The getter of the hours/minutes properties returned the hour or minute component of the DateTime value in the dateTimePicker. The setter of the properties called a method that concatenated the year/month/day components of the dateTimePicker with the values of the hour and minute spinners into a new DateTime value. The spinners were hooked up to the hour and minute properties.
It took about 15 minutes to scrap the old code, reassemble the controls and properties, and then bind everything together. It worked on the first try!
The “old” lesson is: “Think about what you’re going to do before you even touch the keyboard. You should have a clear vision of your objective before writing the first line of code."
- The “new” lesson learned was specific and almost trivial: When extending the functionality of a multi-faceted control, use that control’s internal value as the basis for your work rather than reinvent the (DateTime value) wheel by pushing three separate controls at one value.
Claudio will be amplifying on this in his blog, complete with code samples.
Posted @ 4:13 PM by Chichester, Thom (email@example.com) -