A different approach to initializing a View?

Topics: CAB & Smart Client Software Factory
Mar 25, 2007 at 6:09 PM
I'm finding that as my views become more complex and utilize more and more database backed data and web services that the showing of the view is ugly. What I mean is the view is partially displayed right away, then it calls _presenter.OnViewReady() which loads data to be displayed in the View. Typical. I end up with a partial view being displayed, and it looks like some controls are visible, then finally it's all visible.

It's hard to explain, sorry. What I would like is to see either a fully displayed view with no data, then as the data is ready it appears or no View until all the data is ready (basically until OnViewReady() returns).

I've looked for other events of UserControl that I could use but nothing is jumping out at me. If you understand what I'm trying to describe and have a solution, please share your thoughts or suggestions. :)

Thanks,
Steve
Mar 25, 2007 at 8:15 PM
Sklett,

We resolve this issue by collecting all the data before we paint the view.

One way of accomplishing this is to collect all the data in the presenter of the calling view and only when we have all the data do we show the view.
Mar 25, 2007 at 8:42 PM
Hi Allan,

Thanks for the reply.

So are you using something like:
View.OnLoad()->Presenter.OnViewReady()->(load data)->View.UpdateControls() ?

This is what I'm doing, but it appears that the view starts to draw itself before it even calls Presenter.OnViewReady().
I suppose I could pre-load my model in the WorkItemController.Run() method, but that I have the challenge of getting the model to the presneter via State or Services, both of which I would rather not have to do.

Maybe I'm missing something?

"only when we have all the data do we show the view." - can you explain a little more what you mean by "show the view"?

Thank you,
Steve
Mar 25, 2007 at 11:16 PM
What you might want to do Steve is put the querying of backend database services and the like on a background worker thread.
Mar 26, 2007 at 12:56 AM
Hi Chris,

I thought about that, it would be cool to have the controls display "Loading..." then one by one have their data populated. A bit of a headache though to manage the enabled state of the various controls to prevent the user from performing operations that require valid data that might not be there yet. Beggers can't be choosers though, right?

I'm sure I could devise a solution that wouldn't be too difficult. I just wanted to check to make sure I wasn't missing something that was already in place to solve the problem.

Thanks for the post,
Steve
Mar 26, 2007 at 5:02 AM
Edited Mar 26, 2007 at 5:06 AM
>> cool to have the controls display "Loading..." then one by one have their data populated

Rule Number 1
Only do one trip to the WebService!
The slow part of your application is the trip to the web server, so we want to ensure we only do it once.

I'll try and put this into an example. Say we have a view that lists our customers and we want to edit a paricular customer.

That means I need the Customer Details, a list of phone numbers, a list of email address's (I'm just making this up), etc.
You also require when you are editing the customer a dropdown list populated with all the categories that a customer may belong to.

In my the WebService I create a DataType and call it something like CustomerEditInformation. In this DataType i can store all the above. i.e. the customer, the phone numbers, the email addresses AND the DataSource for the Dropdownlist, and any other controls I need to fill.

In the presenter of my CustomerListViewPresenter it is detected that the operator has requested to edit a particular Customer.
        internal void ShowCustomerDetails(int customerID)
   {
     // I have a Service which I call that will go and 
     // and populate my CustomerEditInformation datatype
     // I pass the service the CustomerID and a Delegate.
     // The service calls the WebService on a background 
     // thread and on completion calls the delegate, passing
     // back the result.
     EditCustomerDelegate = new EditCustomerDelegate(EditCustomer)
     customerService.GetEditCustomerData( customerID, EditCustomerDelegate);
    }
 
        public delegate void EditCustomerDelegate(CustomerEditInformation customerEditInformation);
        private void EditCustomer(CustomerEditInformation customerEditInformation)
        {
            // When this method is called then I have a DataType 
            // populated with all the required information.
            // So now I show the View
 
            const string workItemID = "CustomerEditViewController";
            ControlledWorkItem<CustomerEditViewController> workItem;
            if (!this.WorkItem.WorkItems.Contains(workItemID))
            {
                workItem = this.WorkItem.WorkItems.AddNew<ControlledWorkItem<CustomerEditViewController>>(workItemID);
                workItem.Controller.Run();
            }
            else
            {
                workItem = WorkItem.WorkItems[workItemID] as ControlledWorkItem<CustomerEditViewController>;
            }
            // I pass the dataType to the Controller and the controller passes 
            // this on to the view.
            //
            // Now Chris is going to tell you that this is wrong --- and he's right!
            //
            // Really you should store the datatype in the workItem and then
            // pick it up as a dependency in the Customer Edit View.
 
            workItem.Controller.Activate(customerEditInformation);
 
            // You may need to re-read my previous note on how I'm using ControlledWorkItems.
 
        }
 

To summarise this routine goes and collects all the data required for the new view before it shows the view and we only do one trip to the web service.

I hope this has been of benefit you you!
Mar 28, 2007 at 12:09 AM
Allan, thank you very much for the detailed reply!

I had never thought of loading the model the way your are, very interesting.

Anyway, thank you again for the detailed post.
-Steve