ClientUI & DevForce Part 2: Contact Sandbox Editor

A while back, we released the first version of Contacts sample application to demonstrate the best practices in building MVVM applications that support Silverlight and WPF using one codebase. The sample application was jointly developed by Intersoft and IdeaBlade. In case you missed the story, be sure to check out the whole coverage in my blog post here.

One of the fundamental concepts in the Silverlight/WPF data binding is that every modification on the entity that bound to elements through data context would automatically propagate that changes to the bound UI elements. The MVVM pattern, actually, built upon this data binding capability. However there are certain cases where the automatic propagation is not desired, for instance, when an object is in editing context.

Not so long after we released the first Contacts application, we received feedback from customers asking if it is possible to “isolate” the editing context, so that changes won’t reflect to UI elements bound to the entity. The customers couldn’t go wrong in this case, because reflecting the changes in such editing context while it has not been saved is simply confusing to end users, or I would say, counter intuitive.

The following illustration shows the editing dialog box in the Contacts sample application.

Contact editor

Notice that the “Name” in the list box will reflect as you modify the Name text box in the Contact editing dialog box. As developers, we understood that it was an effect of data binding, unfortunately it’s simply unacceptable to stake holders and application users.

In this post, I will introduce our new approach, called sandboxed editing mode, to shoot the problem in the most efficient and elegant way possible.

Introducing ContactSandboxEditor

The approach of isolating the editing process of an entity is widely known as “sandboxed” editing mode. In this second series of our joint Contacts sample, we introduced ContactSandBoxEditor, an improved editor that implement isolated persistence editing.

The new ContactSandBoxEditor doesn’t reinvent the wheel, instead, it plays nicely with the existing architecture that we designed in the first place. The ContactSandBoxEditor derives from ContactEditor class, then we simply overriding three key methods that are used to add, edit and get saved contact, see the snippet code below.

public class ContactSandboxEditor : ContactEditor
{
    public ContactSandboxEditor(IContactsRepository callerRepository)
        : base(ContactsRepository.CreateRepository())
    {
        CallerRepository = callerRepository;
    }

    private IContactsRepository CallerRepository { get; set;  }

    public override void AddNewContact(Action<contact> onOk, Action onCancel)
    {
        Repository.ClearAllContacts();
        var contact = Repository.CreateContact();
        ShowContactDialogBox(contact, onOk, onCancel);
    }

    public override void EditExistingContact(
        Contact sourceContact, Action<contact> onOk, Action onCancel)
    {
        Repository.ClearAllContacts();
        var contact = Repository.ImportContact(sourceContact);
        ShowContactDialogBox(contact, onOk, onCancel);
    }

    protected override Contact GetSavedContact(
                             ContactEditViewModel viewModel)
    {
        return CallerRepository.ImportContact(viewModel.Contact);
    }
}

As seen in the code above, DevForce provides a number of built-in methods to work with and manage entities, such as FindEntities, ImportEntities and RemoveEntities, making it easy and straightforward to implement contact import and rollback functionality.

Another nice benefit with this approach is that you can easily switch between the editing mode by simply changing the default contact editor in the ContactsViewModel.cs, see below.

private void SetDefaultContactEditor()
{
    // this.ContactEditor = new ContactEditor(Repository);
    this.ContactEditor = new ContactSandboxEditor(Repository);
}

The following illustration describes the interaction between the ContactsView, ContactsViewModel, Repository and the new ContactSandBoxEditor.

Contact Sandbox Editor

As seen in the above illustration, the ContactSandBoxEditor exposes the following processes:

  1. The user clicks “edit” in the ContactsView; the view alerts the ContactsViewModel
  2. The ContactsViewModel calls the ContactEditor
  3. The ContactEditor performs the following:
    a. makes a copy of the Contact and imports it into its own private repository
    b. creates the window,
    c. creates the editing View,
    d. creates the editing ViewModel using the private repository
    e. puts the View and ViewModel inside the window,
    f. shows the window, and waits for the user to finish editing.
  4. When the user closes the window the ContactEditor:
    a. if the user saved, it copies the saved Contact back into the main Repository
    b. If the user canceled, the changes to the Contact copy are abandoned.
  5. The ContactEditor cleans up and tells the ContactsViewModel what happened.

As the results of the sandbox editor implementation, changes on the editing dialog box will no longer reflecting the UI elements bound to the entity. Of course, the changes will be merged and reflected later when the Save button is clicked. See the following screenshot.

Sandbox contact editor

To learn more how to implement and use sandbox editor in depth details, please read the PDF walkthrough that we’ve prepared for you.

Download the Solution

Click here to download the Contacts project source code along with the walkthrough documents. Feel free to play around with the code and use it in your apps! Note that DevForce version 6.0.7 is required to run this sample. You can download the latest DevForce bits here.

In case you missed the news, we recently announced an official strategic partnership with IdeaBlade to focus on an integrated development solution for Silverlight and WPF. We are making available a variety of cost-effective product bundle. Click here to find out more.

While we’ll be kicking-in some nice features for the next series, we’d love to hear your feedback on the Contacts application so far. Are there any specific features you wish to see? Or, perhaps architectural challenges that you are struggling with? Drop them in the comment box, and we will get back to you with solutions.

All the best,
Jimmy Petrus

About these ads

6 thoughts on “ClientUI & DevForce Part 2: Contact Sandbox Editor

  1. Bill Gower

    This addition of the SandBox editor is an important step in the evolution of the application. While the Contact app in Part 1 was following MVVM and it worked well, it allowed access from many parts of the code to objects that didn’t require that access. For example, the ListViewModel had the responsibility of creating the object, opening the editor, passing in the object and then determining the outcome of the add or edit. I like the approach of the ListView Model calling an add or an edit method and these methods create the objects, access the repository, call the editor and determine the outcome. It is a much cleaner approach and narrows the reponsibilities of the ListView Model. With my calls to the add or edit method I usually pass in the parent object so that the create of the child object and take what values it needs from the parent at the time of instantiation. Since the introduction of the ClientUI-Devforce Contacts App, I have been applying these principles and ideas to my own line of business app. I can’t even begin to estimate how much time I have saved and how many less headaches I have had because of this sample. Many thanks to both Jimmy and Ward for their efforts in developing this application.

    Reply
  2. Bill Gower

    What would I like to see in future versions of the appliation:

    1. Handling of lookup tables and drop downs on the form.
    2. Having a grid show detail lines on the form and the proper way to retrieve the rows and display them in the grid.
    3. move the save routine to a unit of work pattern.

    Reply
    1. jimmyps Post author

      @Bill: These are all nice feedback, thank you for sharing them with us. I really like the idea of having a grid that shows detail lines, and have it retrieved and saved using MVVM pattern.

      We will definitely give it some thoughts and include them in our the application roadmap. Most possibly we can include it in the upcoming UXGridView bits.

      Reply
  3. jimmyps Post author

    Hi Bill, glad to hear that you can take advantage of the MVVM and Sandbox Editor pattern in the Contacts application, and apply them to your business applications. Can’t wait to see your applications live in the web :)

    Reply
  4. Ward Bell

    Hi Bill – Glad you like how we’re progressing. A few thoughts on your suggestions for the future:

    1) Configuring ComboBox drop-down lists with entities is a task that consistently bewilder developers, as evidenced by question appearing on numerous forums.

    We should add one of these to the next release of our example. We’ll have to think of a sensible use case but I’m sure we’ll come up with one :-).

    2) Jimmy and Intersoft are all over the nested grid.

    3) Can you elaborate on what you mean by “move the save routine to a unit of work pattern”?

    I think of the DevForce EntityManager wiht its cache of entities and its transactional SaveChanges method as an implementation of the UoW pattern.

    In this sample application, the ViewModel calls an asynchonous Save method of the IContactsRepository which, in its concrete ContactsRepository implementation, invokes the SaveChangesAsync method.

    SaveChanges and SaveChangesAsync gather all cached entities that have pending changes (adds, mods, deletes) and submit them as a batch to the server for save. The Server revalidates and (assuming all as well) begins a transactional save of the batch to the database.

    What are we missing from the UoW pattern you have in mind?

    Reply
  5. Pingback: ClientUI & DevForce Part 3: Enhance Editing Experiences with MVVM Advanced Input Controls | Intersoft Solutions Corporate Blog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s