Intersoft ClientUI 8 > ClientUI Fundamentals > Window and Dialog Boxes Overview > Advanced Window Features |
This topic describes the advanced features of ClientUI windowing framework and controls, and provides guidance to implement the advanced features in your applications. For information about the fundamental concepts and features of ClientUI windowing framework, see Window and Dialog Boxes Overview.
This topic contains the following sections:
ClientUI windowing framework provides a set of comprehensive controls that lets you build rich multiple document interface (MDI) application with best design pattern available. The desktop and window controls are the main building block of an MDI application which is explained in Window and Dialog Boxes Overview.
Additionally, the desktop and window controls can be integrated to a task bar interface for even more compelling application. ClientUI windowing framework uses a loosely-coupled architecture that enables the desktop and window to integrate to an external task bar interface without knowing the actual type of the task bar. This eliminates the need to have a strong reference to the assembly that contains the actual task bar control. Consequently, this architecture enables better scalability and more future proof, as a variety of task bar controls can be used without code changes in the desktop and window.
The following sections describe the architecture overview of ClientUI windowing framework, and explains the important points you need to know to build rich applications using desktop, window and task bar integration.
The windowing components integration is thoughtfully engineered through the efficient use of the routed events, routed commands, routed input and focus scope. To learn more about these concepts, see ClientUI Fundamentals.
The following illustration describes the windowing framework architecture.
As seen in the above illustration, the UXDesktop class represents a container that acts as desktop manager, which manages the windows lifetime and connects the window to the taskbar.
A window is represented by a class that implements IWindow interface which is the basic requirement of a window to be managed by the desktop manager. Examples of window controls that implement the IWindow interface are , UXWindowChrome, UXDialogBox and UXNavigationWindow.
A task bar is represented by a class that implements ITaskBar interface which is required for the desktop manager integration. In this release, you use UXDesktopDock control to implement the task bar interface that support desktop manager and window integration.
The most basic implementation to integrate a UXDesktop to a task bar such as UXDesktopDock is by specifying the target task bar instance to the TaskBar property of the UXDesktop. This can be done through element binding in XAML.
The following example shows a basic implementation of integration between the UXDesktop, UXWindow and UXDesktopDock.
XAML |
Copy Code
|
---|---|
<Intersoft:UXDesktop TaskBar="{Binding ElementName=desktopDock, Mode=OneWay}"> <Intersoft:UXWindow x:Name="UXWindow1" Header="UXWindow1 Title"> <Grid> <TextBlock Text="Content for UXWindow1"/> </Grid> </Intersoft:UXWindow> </Intersoft:UXDesktop> <Intersoft:UXDesktopDock x:Name="desktopDock"> ... </Intersoft:UXDesktopDock> |
There are several fundamental concepts that explain how the window and dock works, which you need to understand before implementing applications that take advantage of the windowing framework in ClientUI.
One of the key objectives of the integration architecture design in ClientUI windowing framework is to streamline rich MDI application development in a way that allows you to rapidly add new windows and then logically define the buttons to be associated to the windows in 1:1 mapping. This is a state-of-the-art implementation in ClientUI windowing framework that enables automatic status synchronization between the window and the task bar, which ultimately delivers consistent and reliable user experiences.
At the heart of the integration is the window identity concept that defines the uniqueness of a window. Each window that managed by the desktop manager should be unique, which is crucial in the desktop and task bar integration, particularly in the desktop manager logic to determine the relationship between a window and the task bar button that represents the window.
The identity of a window is determined through the following properties:
To make a window unique, you need to set at least one of the properties listed above. You can define more than one of the properties above, but you generally define the properties based on your scenarios, which is explained further in the following section.
The task bar queries the above properties when it needs to synchronize the buttons according to the windows status. For example, when a window is opened, the task bar button associated to it should be indicated as active. In more details, the task bar synchronization occurred during the following actions:
Through the solid identity mapping concept described above, a task bar is capable to perform many functions automatically, without requiring you to write extra code or implementation. All you need is to define one or more of the properties above to create a unique identifier for your windows.
The following points describe the operations that performed automatically as the results of the relation between window identity and task bar implementation:
For the above operations to work automatically as expected, you need to carefully implement and review the unique identifier for your window instances. |
The following illustration shows the benefits of the relation between windows and buttons in the task bar such as described above.
In the previous section, you have learned about the concept of window identity, and how it relates to the task bar interface in many ways. This section explains several scenarios that take advantage of the integration features, which can be found in typical business applications.
You implement the window identity based on the one of the scenarios described in the following sub sections.
The simplest integration scenario is where a window is mapped in 1:1 to a button. In this scenario, you have a button that represents the window through its WindowName. Both the WindowName property of the button and the window should be identical, which is shown in the following example.
XAML |
Copy Code
|
---|---|
<Intersoft:UXDesktop TaskBar="{Binding ElementName=desktopDock, Mode=OneWay}"> <Intersoft:UXWindow Header="UXWindow1 Title" WindowName="MyFirstWindow"> <Grid> <TextBlock Text="Content for UXWindow1"/> </Grid> </Intersoft:UXWindow> </Intersoft:UXDesktop> <Intersoft:UXDesktopDock x:Name="desktopDock"> <Intersoft:UXDesktopDockButton WindowName="MyFirstWindow" Text="Application 1" Icon="/SomeApp.png"/> </Intersoft:UXDesktopDock> |
In certain cases, a button in the task bar can represent more than one window instances. For example, consider the Windows Explorer application in the Windows operation system where you can open several Windows Explorer instances, yet they are represented as one button in the task bar.
You can also achieve this kind of scenario in ClientUI windowing framework by specifying a value to the GroupName property of the windows having the same group, which is then mapped to the WindowGroupName of the task bar button.
The following example shows the XAML code to achieve multiple windows (group) scenario.
XAML |
Copy Code
|
---|---|
<Intersoft:UXDesktop TaskBar="{Binding ElementName=desktopDock, Mode=OneWay}"> <Intersoft:UXWindow Header="UXWindow1 Title" IsClientVisible="True" GroupName="MyWindowGroup"> <Grid> <TextBlock Text="Content for UXWindow1"/> </Grid> </Intersoft:UXWindow> <Intersoft:UXWindow Header="UXWindow2 Title" IsActive="True" GroupName="MyWindowGroup"> <Grid> <TextBlock Text="Content for UXWindow2"/> </Grid> </Intersoft:UXWindow> </Intersoft:UXDesktop> <Intersoft:UXDesktopDock x:Name="desktopDock"> <Intersoft:UXDesktopDockButton Text="Application 1" WindowGroupName="MyWindowGroup" Icon="/SomeApp.png"/> </Intersoft:UXDesktopDock> |
When using this scenario, you may want to consider to pair it with dynamic window scenario which is explained in the following subsection. |
In a real world application, it is uncommon to show all windows during the application startup. You typically show a list of applications in the task bar (or shortcut) and allow users to launch the applications on demand. In this scenario, the window that associated to the application is dynamically created upon user's requests.
To open a window dynamically, you set the ApplicationUri of the button to the target URI of the physical XAML in your project. Using this technique, it is not necessary to define the window in the desktop manager since the dynamic window will be added to the desktop manager at runtime.
With ApplicationUri, the dynamically launched window will be automatically associated to the button in the task bar and the value of the ApplicationUri becomes the unique identifier that differentiate it from the other windows. The similar mechanism is applied to NavigateUri property of the button. When specified, the target XAML will be launched in a new UXNavigationWindow instance instead of UXWindow.
The main difference of the ApplicationUri and NavigateUri concept is that the ApplicationUri is best paired with target XAML that encapsulates a window such as UXWindow or UXDialogBox, while the NavigateUri is best paired with target XAML that encapsulates a page such as UXPage. To learn more about navigation window, see UXNavigationWindow Overview. |
The following illustration shows the dynamic windows that are associated to buttons through ApplicationUri and NavigateUri property.
The following example shows the XAML that encapsulates a window and its content.
/Views/HomeWindow.xaml |
Copy Code
|
---|---|
<Intersoft:UXWindow xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" xmlns:Intersoft="http://intersoft.clientui.com/schemas" x:Class="ClientUIApplication_Docs.Desktop.HomeWindow" Header="HomeWindow" d:DesignWidth="640" d:DesignHeight="480"> <Grid x:Name="LayoutRoot"> <TextBlock Text="Put some content here..."/> </Grid> </Intersoft:UXWindow> |
The following example shows the page that contains the desktop and task bar button which opens the window in the previous example through the ApplicationUri definition.
XAML |
Copy Code
|
---|---|
<Intersoft:UXDesktop TaskBar="{Binding ElementName=desktopDock, Mode=OneWay}" /> <Intersoft:UXDesktopDock x:Name="desktopDock"> <Intersoft:UXDesktopDockButton Text="Home" ApplicationUri="/Views/HomeWindow.xaml" Icon="/Home.png"/> </Intersoft:UXDesktopDock> |
For the guided walkthrough to implement desktop-style (MDI) application, see Walkthrough: Create Rich Application using Windowing and MVVM Pattern.
ClientUI provides project and item templates that let you rapidly develop desktop-style (MDI) application using Visual Studio 2010. To learn more about the project and item templates installed with ClientUI, see Introduction to ClientUI Project Templates. |
In addition to physical XAML in the same project, you can also open a window of which its XAML is physically located in a different application package (.xap). This is a fundamental architecture to build composite applications that capable to load applications that are typically made available on demand, and then inject its content to the main application as if the content was physically existed in the main application.
ClientUI provides a powerful application framework that allows you to build scalable composite applications with key features such as on-demand downloading, integration with navigation, as well as integration with windowing framework.
For more information about creating dynamic windowing application that integrates to application framework, see Application Framework Overview.
The ClientUI windowing framework does not only provide rich windowing controls that you can use to create compelling MDI applications, it also provides solid architecture that thoughtfully engineered to enable you easily achieve windowing tasks commonly found in line-of-business applications, for instances, open a window with preconfigured properties and passing parameters using commanding pattern. This pattern also allows you to address a variety of UI challenges in more elegant way through the efficient use of MVVM pattern. For more information about commanding, see Commanding Overview. For information about MVVM pattern development, see MVVM Pattern Overview.
ClientUI windowing framework provides a number of pre-implemented windowing commands that you can consume directly such as LaunchApplication, Close, SetActive and more. To learn more about the commands available in ClientUI windowing framework, see Window and Dialog Boxes Overview.
This section describes how to use LaunchApplication command to perform a number of windowing-related tasks which are explained in the following sub sections.
To open a window based on the target URI, you use the LaunchApplication command and set the value of the CommandParameter property in the particular command source (such as UXButton) to the target URI the window to be opened.
The following example shows how to open a window based on the given URI using command.
XAML |
Copy Code
|
---|---|
<Intersoft:UXDesktop TaskBar="{Binding ElementName=desktopDock, Mode=OneWay}" /> <Intersoft:UXDesktopDock x:Name="desktopDock"> <Intersoft:UXDesktopDockButton Text="Home" ApplicationUri="/Views/HomeWindow.xaml" Icon="/Home.png"/> </Intersoft:UXDesktopDock> |
Although the target URI can be any XAML that contains supported Silverlight content type such as UserControl, the LaunchApplication command is best used to target a XAML file that encapsulates a UXWindow, or a UXPage. |
In certain cases, you may want to open a window with certain settings applied, such as the window width, window height, title, and icon. Often times, you may also want to pass custom data as parameter to the window being opened. You can use WindowOptions to achieve many of these tasks. The WindowOptions is a DependencyObject, which means you can instantiate this class in the XAML and bind it to the CommandParameter of a command source.
WindowOptions class provides numerous properties that you can set to preconfigure a window when used with LaunchApplication command, which is described in the folllowng list.
The settings specified in the WindowOptions has higher precedence than the default settings of the window. This means that the settings specified in WindowOptions will override the settings defined in the window. |
The following example shows how to open a window based on a target URI using command.
XAML |
Copy Code
|
---|---|
<Intersoft:UXWindow xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:Intersoft="http://intersoft.clientui.com/schemas"> <Grid x:Name="LayoutRoot"> <StackPanel> <Intersoft:UXButton Content="Button" HorizontalAlignment="Left" Command="Intersoft:WindowCommands.LaunchApplication" CommandParameter="/Desktop/HomeWindow.xaml"/> </StackPanel> </Grid> </Intersoft:UXWindow> |
The following example shows how to open a window and pass a custom data to the startup parameter, then obtain the passed data in the target window in Loaded event.
XAML |
Copy Code
|
---|---|
<Intersoft:UXWindow xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:Intersoft="http://intersoft.clientui.com/schemas"> <Grid x:Name="LayoutRoot"> <StackPanel> <Intersoft:UXButton Content="Button" HorizontalAlignment="Left" Command="Intersoft:WindowCommands.LaunchApplication"> <Intersoft:UXButton.CommandParameter> <Intersoft:WindowOptions Uri="/Desktop/HomeWindow.xaml" StartupParameters="Hello ClientUI"/> </Intersoft:UXButton.CommandParameter> </StackPanel> </Grid> </Intersoft:UXWindow> |
C# |
Copy Code
|
---|---|
public partial class HomeWindow : UXWindow { public HomeWindow() { InitializeComponent(); this.Loaded += new RoutedEventHandler(HomeWindow_Loaded); } private void HomeWindow_Loaded(object sender, RoutedEventArgs e) { object data = this.StartupParameters; if (data is string) MessageBox.Show(data.ToString()); } } |
Since the StartupParameters is a dependency property, you can also pass complex data through data binding, for example, binding to the selected item in a list box. This allows you to use MVVM pattern in conjunction with the commanding. To learn more about using MVVM pattern in UI development, see MVVM Pattern Overview. |
The following example shows how to open a window that target a URI with single instance option, and automatically activate the existing instance if found.
XAML |
Copy Code
|
---|---|
<Intersoft:UXWindow xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:Intersoft="http://intersoft.clientui.com/schemas"> <Grid x:Name="LayoutRoot"> <StackPanel> <Intersoft:UXButton Content="Button" HorizontalAlignment="Left" Command="Intersoft:WindowCommands.LaunchApplication"> <Intersoft:UXButton.CommandParameter> <Intersoft:WindowOptions Uri="/Desktop/HomeWindow.xaml" ForceSingleInstance="true" ReactivateExistingInstance="true"/> </Intersoft:UXButton.CommandParameter> </StackPanel> </Grid> </Intersoft:UXWindow> |
The following example shows how to open a window with customized size, title and icon.
XAML |
Copy Code
|
---|---|
<Intersoft:UXWindow xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:Intersoft="http://intersoft.clientui.com/schemas"> <Grid x:Name="LayoutRoot"> <StackPanel> <Intersoft:UXButton Content="Button" HorizontalAlignment="Left" Command="Intersoft:WindowCommands.LaunchApplication"> <Intersoft:UXButton.CommandParameter> <Intersoft:WindowOptions Uri="/Desktop/HomeWindow.xaml" WindowWidth="400" WindowHeight="250" WindowTitle="Custom Window Title" WindowIcon="/CustomImage.png"/> </Intersoft:UXButton.CommandParameter> </StackPanel> </Grid> </Intersoft:UXWindow> |
The UXWindow control provides built-in busy state management allowing you to create compelling window interface that responsive to user interactions. To set a window as busy, you simply set the IsBusy property to true. In addition, ClientUI also provides similar features for other frameworks such as navigation. To learn more about navigation framework, see Navigation Overview.
The windowing controls in ClientUI implement many user experience features that conform to ISO Standards 9241, such as the behaviors for busy indicator.
When you set a window as busy and its BlockUIOnBusy property is enabled, you can notice the following behaviors:
The following figure shows an example of a window in busy mode.
When a window is set as busy, the other windows in the desktop can continue to receive user interactions. This simulates a multi-threading operation similar to Windows operating system. As in above example, you can click on the UXWindow1 or UXWindow2, while the DetailsWindow is busy.
To learn more about user experience features implemented in ClientUI controls, see User Experiences Overview.
While processing a long running operation, such as in report generation and asynchronous data retrieval scenario, you may want to show a customized busy indicator in addition to the built-in behaviors described in the previous section.
You can add your own busy indicator to be displayed when the window is busy by setting your custom XAML template to the BusyIndicatorTemplate property of the window.
The following example shows how to setup the UXWindow to show a progress bar when the window is busy. This is done by specifying a custom data template to the BusyIndicatorTemplate property.
XAML |
Copy Code
|
---|---|
<Intersoft:UXWindow xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:Intersoft="http://intersoft.clientui.com/schemas" Header="DetailsWindow"> <Intersoft:UXWindow.BusyIndicatorTemplate> <DataTemplate> <Border CornerRadius="4" Width="200" Height="80" Background="#CC000000"> <Intersoft:UXProgressBar Width="160" Height="20" HorizontalAlignment="Center" IsIndeterminate="True"/> </Border> </DataTemplate> </Intersoft:UXWindow.BusyIndicatorTemplate> <Grid x:Name="LayoutRoot"> <StackPanel Orientation="Vertical"> <StackPanel> <Intersoft:FieldLabel Header="Name: "> <Intersoft:UXTextBox Width="120"/> </Intersoft:FieldLabel> <Intersoft:FieldLabel Header="Address: "> <Intersoft:UXTextBox Width="150"/> </Intersoft:FieldLabel> </StackPanel> <Intersoft:UXButton Name="SaveButton" Content="Save" HorizontalAlignment="Center" Click="SaveButton_Click" /> </StackPanel> </Grid> </Intersoft:UXWindow> |
The result looks like the following illustration.