Knowledge is power. We love to share it.

News related to Mono products, services and latest developments in our community.


Using Mono DataManager

11/02/2011Categories: MonoX
Every developer deals with data retrieval, display and manipulation - or data binding - on a daily basis. It is one of the most common (and often one of the most boring) part of our lives. Unlike data binding in desktop environments, where all changes can be instantly reflected on a data model, Web applications require a different approach. Mono DataManager is designed to simplify data binding and transformation tasks. You can see it in action in most of the data-oriented MonoX Web parts.

Here's how you can use DataManager in your code. Data binding is configured by adding DataManagerBindings objects to the DataBindings collection. DataManagerBindings is used to define a series of data model-to-view mappings, specifying which data object properties should be bound to specific UI control properties. DataBindings collection add method comes with a bunch of overloads that helps you to easily create bindings without the need to explicitly create DataManagerBindings object. Lets see few examples how we can configure binding

DataManager dataManager = new DataManager();
// Set binding for edit control
dataManager.DataBindings.Add(editControl, "FieldName");
// Set binding for preview and edit control
dataManager.DataBindings.Add(previewControl, editControl, "FieldName");
// Or we can set it by explicitly creating and setting DataManagerBinding object
dataManager.DataBindings.Add(new DataManagerBinding()
    EditControl = editControl,
    PreviewControl = previewControl,
    PreviewControlValueProperty = "Value",
    FieldName = "FieldName"

To define valid binding settings, only FieldName and EditControl parameters are required, all other options are optional. DataManager supports dot notation format for FieldName so you can bind control on child object properties (e.g. "Name.FamilyName").  In scenarios where you want to use a preview (read-only) mode, you can set a preview control to bind. DataManager uses ControlValuePropertyAttribute to find which control properties to use for reading and setting values. In cases where UI control doesn't implement this attribute or you want to have different fields for getting and setting values, you can use EditControlValueProperty to define the edit control value property or PreviewControlValueProperty for preview control value. There are two more properties that are used for visibility management - we will discuss them later in this article.

Now when we have configured binding we can move our data easily to and from our UI via two methods, TransferDataToControls and TransferDataFromControls. I thing they have pretty self-explanatory names; all you need to do is to pass your data object as a parameter to these methods and DataManager will try to work its way throught their properties and transform data to appropriate fields and data types.

Of course, things are rarely so simple in the real life. More often, you will have scenarios in which you can't simply bind value to a property or you need to perform additional manual transformations, like when you have to use multiple select list. DataManager provides four events that can be used to control data transfer: ToControlsTransfering, ToControlTransfering, ToControlTransfered and ToControlsTransfered - of course, there is the same sequence of events for transfer from controls. When you call TransferDataToControls, first event to be fired will be ToControlsTransfering, taking two parameters: source object and data binding configuration. This is the last place where you can adjust the binding configuration. After this, for every binding configuration, ToControlTransfering and ToControlTransfered will be fired with DataManagerTransferEventArgs argument containing the source object field value, a control to bind, a control property name and its type. After binding is complete, ToControlsTransfered is fired with the source object and a data binding configuration passed in as parameters. This is usually a good place to do all manual binding tasks.

Another handy DataManager feature is ClearControls method. This method will reset your form on the server side by setting control value to the default type value. If you need to set some different default value or you need to reset control manually, similarly to transfer methods, ClearControls will fire chain of events where you can control form reset. 

DataManager can control the visibility of dependant controls. It supports two working modes, preview and edit, via its IsPreviewMode property. When it is set to true data will be bind to preview controls and all edit controls will be hidden. Alternatively, setting this property to false causes all edit controls to be bound, while preview controls remain unvisible. To change this behavior, you need to call InitControlVisibility explicitly. All transfer methods and the clear method will call InitControlVisibility, so there is no need to call it manually after data transfer or form reset. Unlike various ASP .NET built-in controls like FormView, where you have separate templates for view and edit mode (or sometimes an insert template), DataManager doesn't put any restrictions on how you define your views. Similar to the transfer events, you can control visibility initialization through four events: VisibilityInitializing, ControlVisibilityInitializing, ControlVisibilityInitialized and VisibilityInitialized. The parameters and working modes are just the same as for the transfer events explained earlier. 

DataManager supports form validation mechanisms and takes care of synchronizing validator visibility with the current working mode. Validators are hidden when DataManager is in the preview mode, and shown in the edit mode. You can easily assign validators to UI controls at the very same time the data mapping is configured - in the Add method described above. Alternatively, you can control validators' visibility through InitControlVisibility events.

MonoX features a specialized DataManager called DataManagerHideEmptyFields. This is an extended DataManager that will hide all the fields that aren't populated by user when preview mode is active. In most cases we are going to have rich HTML code surrounding our edit and preview controls, and it also has to be hidden is such scenarios. That's why DataManagerHideEmptyFields comes with the ReferencedContainers collection, where you can specify all HTML code that is to be hidden when a field is not populated. You can see how to use it in the example below:

<asp:PlaceHolder ID="Name" runat="server">
  <div class="field">
     <asp:Label ID="NamePreview" runat="server" />
     <asp:TextBox ID="NameEdit" runat="server" />

DataManager dataManager = new DataManager();
dataManager.DataBinidings.Add(new DataManagerBinding()
    EditControl = NameEdit,
    PreviewControl = NamePreview,
    FieldName = "FieldName",
    ReferencedContainers = new Control[] { Name }

If DataManagerHideEmptyFields detects that field is not populated, it will hide the complete HTML together with all server controls by hidding the referenced container - in this case PlaceHolder with the ID "Name".

I have attached a small sample page you can put inside your MonoX installation and try out DataManager in action. Happy data binding!
Rated 5.00, 2 vote(s). 
Very nice!
ControlValuePropertyAttribute link is broken (has extra http in it)
Thanks for spotting broken link, it's fixed now.