For the past few months, I have been engaged in the development of Windows Presentation Foundation (WPF) based SDK called MixModes Synergy 2010 in my company. MixModes Inc. Synergy is a WPF toolkit that unleashes the power of WPF via simpler programming constructs and provides out of the box custom controls that allows Rapid Application Development of line of business applications. MixModes Synergy 2010 can be downloaded here.
This SDK will be ongoing development that MixModes Inc. will pursue to provide best possible support for WPF and Silverlight development. Some of the features in version 1.0 include:
- Base framework for WPF development
- Easy and type-safe adoption of Model-View-ViewModel pattern
- Custom visual adorners
- Logical behaviors
- Out of the box custom controls
MixModes Synergy 2010 is free for all uses and is MixModes Inc.’s initiative to contribute to the developer community. In this blog, I will uncover the solutions Synergy provides in each of the above categories.
Base Framework for WPF Development
CommandBase class provides a flexible implementation for custom commands. This class works on an
Action<object> instance for command invocation and an optional
Predicate<object> for command execution evaluation. If predicate is not specified, it is assumed that command can execute at any time. Also,
CanExecuteChanged event that is registered with
CommandManager which then re-queries validity of command execution based on user interaction with the application.
Simply speaking, one can instantiate a command base class as follows:
CommandBase myCommand = new CommandBase(arg=>DoFoo(arg), arg=> CanFoo(arg));
FrameworkElementExtensions class contains a list of extension methods for
FrameworkElement instances that help in finding logical and visual parents of specified type, clearing adorner layer for element, enforcing element size and displaying tooltips very easily.
CustomWindow class provides a fast way to create a custom window by just declaring a template for custom window and specifying the named parts for window controls.
Dialog Window Enhancements
DialogWindow provides a true dialog box look and feel for modal dialogs by setting appropriate window style on the dialogs. This fixes WPF bugs around inability of dialog windows to hide control box.
DependencyProperty Change Detection
ObservableDependencyProperty class can monitor change in a dependency property of a dependency object without the need for separate events. To monitor changes in a dependency property for a dependency object, one needs to supply a callback delegate of type
DependencyPropertyChangedEventHandler. The following code illustrates usage of
ObservableDependencyProperty descriptor = new ObservableDependencyProperty(
void OnTextChanged(object sender, DependencyPropertyChangedEventArgs e)
TextBox changedBox = sender as TextBox;
string oldValue = e.OldValue as string;
string newValue = e.NewValue as string;
If monitoring of a specific dependency property on a list of elements is required,
ObservableDependencyPropertyCollection provides the necessary plumbing for ease of tracking changes.
_dockPaneStateMonitorList.DependencyPropertyChanged += OnDockPaneStateChanged;
private void OnDockPaneStateChanged(object sender, DependencyPropertyChangedEventArgs e)
DockPane pane = sender as DockPane;
DockPaneState state = (DockPaneState)e.NewValue;
Easy and Type-safe Adoption of Model-View-ViewModel Pattern
ViewModelBase class provides a type safe
RaisePropertyChanged method for derived classes and hence provides compile time property name checks. Rather than passing in a
string as the property name, derived classes raise
PropertyChanged event as follows:
Custom Visual Adorners
MixModes Synergy allows for visual creation of adorners. In fact, any visual can be transformed into an adorner with practically few lines of code. All this magic is done through the use of
ContentAdornerBase class that makes creating visual adorners no different than creating a user control. It just takes a few steps to create a visual adorner:
- Create a visual resource in your resource dictionary – This can be done using Blend designer. Ensure that
x:Shared is set to
False on the resource. This means that anytime you host the resource on multiple elements, a copy of visual tree shall be created preventing duplicate parenting issues.
- If the resource dictionary is different from default application resource dictionary, place a link in the merged dictionary section of default application dictionary to load it.
- Derive a class from
ContentAdornerBase; load and pass in the visual resource from resource dictionary and pass it onto the base constructor.
- Add the derivative class to adorned element’s adorner layer.
As an example, let’s assume that you want to create a reusable adorner that helps resize adorned element. Following the steps above, you could define a resource in the resource dictionary ResizableAdorner.xaml:
<Grid x:Key="ResizableAdorner" x:Shared="False">
Link ResizableAdorner.xml to your application resource dictionary as one of the merged
<ResourceDictionary Source="ResizableAdorner.xaml" />
Create a class
ResizingAdorner deriving from
ContentAdornerBase as follows:
internal class ResizingAdorner : ContentAdornerBase
internal ResizingAdorner(UIElement adornedElement)
: base(adornedElement, Application.Current.Resources["ResizableAdorner"] as FrameworkElement)
private void AttachNamedParts()
Finally, just place the adorner to adorned element’s adorner layer:
AdornerLayer layer = AdornerLayer.GetAdornerLayer(someFrameworkElement);
if (layer != null)
That’s all the steps you need to create a visual adorner!
Logical behavior is a new concept introduced by MixModes Synergy that decouples behavior from its visual parent. The idea is to define visual behavior in control templates that can then bind to an ancestor visual element or a template parent in attaching the behavior. To create a logical behavior, follow the steps given below:
- Derive a behavior from
LogicalParentBehavior<T> class and supply the logical parent as the generic parameter during derived class definition.
- In the overridden
OnAttached method, call
base.OnAttached and then access
LogicalParent property of the base class to access the logical parent to attach behavior.
- In the XAML, just declare behavior in the usual fashion to any visual element.
Out of the Box Custom Controls
MixModes Synergy provides out of the box custom controls that are easily consumable from your WPF based applications. All the controls released as part of MixModes Synergy 2010 SDK are completely look-less and can be custom themed on top of the standard themes that ships as part of the SDK. MixModes will release additional custom controls on a regular basis to enrich Synergy and provide out of the box support in the development for line of business applications.
One major control release in the current release is the window docking solution similar to docking windows in Microsoft Visual Studio. Using docking window control is very simple. In your XAML just add the
WindowsManager as the name suggests is the primary manager for Windows in docking solution. Each dockable window is an instance of
DockPane class which is a derivative of
DockPane instance can have a
Header (which serves as the title of the
DockPane) and a
Content (which serves as the content of the
DockPane can be added in many different ways to the
- As pinned window – via
WindowsManager.AddPinnedWindow(DockPane, Dock) method
- As auto hidden window – via
WindowsManager.AddAutoHideWindow(DockPane, Dock) method
- As floating window – via
- As a document in the main document area – via
DocumentContainer is the component that organizes documents within
WindowsManager (this excludes pinned, auto-hidden and floating windows since they are not considered documents).
MixModes Synergy 2010 also provides window state serialization and deserialization for your application environment to preserve and load the window environment of any complexity.
Out of the box, Synergy provides XML serialization of window states through
XmlWindowsManagerDeserializer classes. Custom serialization is supported via specialization of base classes
XML serialization of
XmlWindowsManagerSerializer requires two pieces of information during construction:
DockPane writer – An
Action<XmlElement, DockPane> instance that can write additional metadata about a
DockPane to the
- Document writer – A
Func<DocumentContent, string> instance that takes in a
DocumentContent and returns a
string representation of the content. Note:
DocumentContent.DockPane property returns the associated
DockPane, however the
Content properties of
DockPane are set to
null. To access
Content property, use the
Content properties of
DocumentContent instance directly.
XmlWindowsManagerSerializer instance is created, a call to
Serialize(Stream, WindowsManager) method serializes
WindowsManager to the
Similar to serialization process, deserialization process requires an instance of
Action<DockPane, string> within the constructor of
XmlWindowsManagerDeserializer to de-serialize a
DockPane from previously saved
string representation. Deserialization does not require additional
Action to realize
DocumentContent is inherently a serialization wrapper for
XmlWindowsManagerDeserializer instance is created, a call to
Deserialize(Stream, WindowsManager) deserializes the
WindowsManager to previously saved state.
MixModes Synergy 2010 is an ongoing project and several additions will be made to the SDK based on customer requests. Everyone is encouraged to download and play with the SDK and please send me your questions and suggestions here. Thank you all very much.