Model-View-ViewModel pattern is a simple and effective set of guidelines for designing and implementing a Silverlight/WPF application. It allows you to create a strong separation between data, behavior, and presentation, making it easier to control the software development process primarily on the user interface engineering.
Intersoft ClientUI includes comprehensive frameworks such as commanding and base classes as well as hundreds of rich presentation controls that support MVVM pattern entirely. To learn more about the basic concepts of MVVM pattern, its benefits, and how ClientUI supports MVVM pattern, see MVVM Pattern Overview.
This topic discusses a number of more advanced techniques in implementing MVVM using the rich user interface controls available in ClientUI. For an instance, many developers found it very difficult to implement busy state management or searching capability in their applications due to the lacking of controls that specifically engineered to support the MVVM semantics. In ClientUI, you use UXSearchBox for searching functionality that provides properties such as IsSearching and SearchResult which you can use to implement MVVM pattern in an elegant fashion.
Built-in Busy State Management
ClientUI includes frameworks and presentation controls that make it easy for you to create compelling line-of-business applications that target the Silverlight and WPF platform. One of the most common user experiences pattern in modern applications is the busy state management which often requires a lot of works, effort and code to make it work.
Certain flagship controls in ClientUI provide built-in features to handle busy state management using MVVM semantics allowing you to consistently control the busy state from within the ViewModel. The busy management also complies with strict user experience standards. For more information on MVVM pattern, see MVVM Pattern Overview. For more information on UX standards implementation in ClientUI, see User Experiences Overview.
The following sections describe the flagship controls that support built-in busy state management feature.
Navigation Frame and Page
ClientUI features UXFrame, an advanced navigation frame that built on the top of Silverlight's navigation infrastructure and extended it with ClientUI's powerful frameworks such as routed events and commanding. This allows UXFrame to provide more advanced features that rely on routed events architecture such as busy state management, authentication and the navigation life cycle.
One of the most requested features in UXFrame is the built-in state management that provides developers with an easy way to manage the busy state when a longer asynchronous operation occurred in the page that currently hosted by the navigation frame. The busy state management feature is designed in a way that lets you rapidly manage the busy state of the page with MVVM pattern using centralized approach. This eliminates the needs to duplicate the busy template to each modular page.
You can set a page to busy state by settings the IsBusy property of the UXPage to true. Similarly, set the property to false to set the page back to the normal state. To disable user interaction while the page is busy, you set the BlockUIOnBusy property of the page to true. In this case, the UXFrame will automatically disable the content of the page and display the busy indicator defined in its BusyIndicatorTemplate property.
The following code shows the ViewModel of the RegisterForm that responsible to manage the busy state according to the business logic. Notice that the IsBusy property of the ViewModel is bound to the IsBusy property of the UXPage.
Finally, when the UXFrame detects that the UXPage that it currently hosted changes its IsBusy property, the UXFrame will show the busy indicator defined in the BusyIndicatorTemplate such as shown in the following example.
Notice that the user interface elements will become disabled when the page is busy, this is done through the BlockUIOnBusy property which is shown in the above XAML example code.
The following illustration shows the result of the above example.
To learn more about the concepts and features of navigation frame and page model in ClientUI, see Navigation Overview.
Search box is among the input controls that requires a sophisticated busy state management due to its default functionality that performs an asynchronous query to server to obtain search results. ClientUI includes a UXSearchBox control with built-in busy state management feature that makes it easy for you to control the busy status using MVVM pattern.
The MVVM semantics for the UXSearchBox is centered around three properties: IsSearching, QueryText and SearchResult. In this section, you learn how to use IsSearching property to indicate that a searching operation is currently in progress. When this property is set to true, the text specified in the BusyText property will be displayed in the result box.
The following example shows how to setup UXSearchBox to maintain its busy state using MVVM pattern.
The result of the above example is shown in the following illustration.
To learn more about the busy state and other features of the search box control, see UXSearchBox.
Window and Dialog Boxes
Similar to the navigation framework, the windowing controls in ClientUI such as UXWindow and UXDialogBox provide built-in busy state management that supports MVVM semantics. It also consistently exposes the BlockUIOnBusy semantic which disables the UI controls in the window content. Consequently, users cannot make further changes to the content while the window is busy. This is one of the user experience standards that implemented in ClientUI's windowing controls. To learn more about user experiences implemented in ClientUI controls, see User Experiences Overview.
The following example shows how to setup a UXDialogBox to show as busy when the Save button is clicked. The example uses MVVM pattern that controls the busy state from within the ViewModel.
The result of the above example is shown in the following illustration.
To learn more about the window and dialog boxes in ClientUI, see Window and Dialog Boxes Overview.
Streamlined Input and Focus Management
MVVM Pattern promotes the separation of concerns between the user interface, the user interaction logic and behaviors of the View, and the entities of the application. While it makes UI programming a lot easier by introducing a pattern that you can consistently apply, the MVVM pattern fall short in certain user interaction logics that require a direct reference to the view, such as input handling and focus management.
For example, consider you have a login form where users provide their credentials in the text boxes and then press enter on any of the text boxes to submit (which is actually calling the same function as the button is clicked).
In the classic UI programming, the above scenario is straightforward and can be easily achieved such as shown in the following code.
Using MVVM pattern, you cannot use the above technique since MVVM pattern disallows you to reference the user interface elements from the ViewModel. In other words, a ViewModel should have no ideas about the existence of a View.
ClientUI is engineered to address such UI programming and common scenarios with comprehensive features that specifically designed for MVVM pattern usage, such as discussed in the following sections.
IsDefault, IsCancel and DialogResult
All input controls in ClientUI are designed with an advanced input handling mechanism that takes account the focus scope and special keyboard keys such as Enter and Escape key. This allows you to define a logical characteristic on your command buttons with a simple semantic that associates whether a command button is a default button or a cancel button. For a default button, pressing Enter on a valid input field like text box will execute the button as if the button is clicked. The same goes true for a cancel button invoked with an Escape key.
Many of these characteristics are engineered to meet the ISO-standards in usability and user interactions. For more information about UX standards implemented in ClientUI controls, see User Experiences Overview.
With the IsDefault and IsCancel feature consistently implemented in the entire ClientUI command controls, creating application with rich user interaction using MVVM pattern becomes easy and straightforward. The following example shows how you can setup the Login button to respond on the Enter key, while the Cancel button to respond on the Escape key.
Notice that there is no C# or VB code needed to achieve this scenario since the user interaction related behaviors are addressed in the View layer. Consequently, this implementation is the most ideal technique for MVVM pattern development that emphasizes separation of concerns.
The IsDefault and IsCancel also work closely with DialogResult semantic which is particularly useful when using the input and command controls are hosted in a window control such as UXDialogBox. The DialogResult property, which is consistently implemented in all button lineups such as UXButton, UXHyperlinkButton, UXSplitButton and more; automatically determines the action of the window, for instance, closing the current window when Escape key is pressed, which is actually mapped to a Cancel button with DialogResult set to Cancel. To learn more about the concepts and features in windowing, see Window and Dialog Boxes Overview.
The following example enhances the previous example by adding the DialogResult property to the Login and Cancel button.
With these properties applied, the window can now be automatically closed when Escape key is pressed. In addition, the DialogResult of which command button is invoked will be synchronized to the DialogResult of the current window. This allows you to write logics that process certain task based on the value submitted in the DialogResult of the dialog box.
DefaultFocus and SetFocus API
Similar to the scenario described in the previous section, focus management is one of the key challenges in implementing MVVM pattern because you cannot reference to a user interface control directly from a ViewModel and hence disallow you to write code such as textBox1.Focus() in the ViewModel.
ClientUI addresses this particular scenario by exposing DefaultFocus property in several components that make sense to have an initial focus, such as in UXPage and UXWindow. To set the focus to a control in the first load, set the DefaultFocus property of the UXPage and UXWindow to the name of the control to be focused, such as shown in the following example.
In addition, the ClientUI framework also provides a static SetFocus API allowing you to set focus to a certain control in the ViewModel. Since it accepts the name of the control in form of string as the parameter, it does not require a direct reference to the control thus makes it an ideal technique for use in MVVM pattern.
Using Dialog Boxes and Message Boxes with MVVM
ClientUI includes a comprehensive windowing controls such as dialog boxes and message boxes to let you create desktop-rich user interface. While these window controls are intuitive and straightforward to implement using classic UI programming, it requires more advanced techniques to implement using MVVM pattern due to the loosely coupling concept between the View and the ViewModel.
Showing a UXDialogBox from ViewModel
The UXDialogBox class implements IModalWindow interface which allows you to create an instance of a UXDialogBox from within the ViewModel and reference it as the IModalWindow interface. The interface approach allows the ViewModel to interact with the object without actually knowing the type of the object.
In addition, ClientUI also provides a number of classes that take advantage of solid design patterns such as provider and shell pattern to interact with the UXDialogBox in the ViewModel. The use of these design patterns are recommended for code efficiency that promotes separation of concerns which is particularly useful for cross-platform development such as in Silverlight and WPF.
The following example shows how to create an instance of a UXDialogBox asynchronously, show the dialog box and handle the callback when the dialog box is closed.
Showing a UXMessageBox from ViewModel
Similar to the UXDialogBox, you can also display a desktop-like message box using MVVM pattern with the provided UXMessageBox API. You can show a message box using intuitive syntaxes that already common in general UI development such as using UXMessageBox.Show static method.
The following example shows how to show a UXMessageBox from ViewModel and handle the close callback.
Using Interactive Callout with MVVM
Certain controls that expose interactivity features such as UXPopup and UXCallout are also designed to support MVVM pattern by exposing their behaviors and features as dependency properties which allows you to easily interact with the control in the ViewModel. For instances, instead of calling the Show method of the control which breaks the compliance with MVVM pattern, you use the IsOpen property to determine when the UXCallout control should open.
When paired with button controls that support MVVM semantics such as UXToolBarButton, showing a UXCallout becomes easy and straightforward through a two-way data binding to the IsChecked property of the UXToolBarButton, while the IsOpen property of the callout is bound to a property in the ViewModel. This allows you to design consistent user experiences without writing extensive code.
The following example shows how to setup a UXCallout to be consistently displayed when you click on a button.
Notice that the button will remain in "pressed" state while the callout is open. The button state will be consistently synchronized when the callout is closed due to user interaction, such as when you click on the modal area of the callout.
Working with Window using Commanding and MVVM
In addition to the frameworks and controls, ClientUI also includes a number of windowing controls that you can use to display basic information or gather user input in a modal form. For more information about the windowing controls and dialog boxes in ClientUI, see Window and Dialog Boxes Overview.
The windowing controls such as UXWindow, UXDialogBox and UXNavigationWindow expose several API that you can use to interact with the window such as Show and Close method. However, these methods are not suitable for use in MVVM pattern as the ViewModel cannot have a direct reference to the user interface controls existed in the View layer. To address this particular MVVM requirement, the ClientUI windowing controls take advantage of the advanced data binding and commanding architecture available in ClientUI's framework. For more information about commanding concept, see Commanding Overview.
The following sections describe how to work with the windowing controls using commanding and MVVM pattern.
Using commands, you can setup a button to open a new UXWindow based on its Uri location using declarative XAML code. This means that you can interact with the windowing controls without have to write code, which is an ideal solution for a MVVM pattern application.
In the above example, notice that a new WindowOptions instance can be created directly in the XAML and then assigned to the CommandParameter of the button. When the target, in this case is the UXDesktop, dispatches the command, it recognizes the WindowOptions object in its parameter and execute the action according to the data in the WindowOptions.
ClientUI includes a number of window-related commands that are readily usable in your project. These commands expose the same results as if they were called via API. The following list shows several examples of window-related commands: