Monday, January 16, 2012

Silverlight 5

Diversion

Okay so this post was supposed to be the next part in the trilogy regarding the FormViewModel class hierarchy however as with all good plans, this one ran into an unexpected event – the release of Silverlight v5 – not only that but the Async CTP was also updated to remain compatible too – that meant the composition framework could be updated and that is why the next stage in the trilogy has been usurped by this post!

Abstract

To build the new version of the composition framework lead to some interesting issues – first off I needed to recompile the common service locator, unity and the rest of the enterprise library (v5) to target the latest v5 bits (otherwise you end up with a mix of CLR versions) not difficult but that lead to changes in the version of assemblies used in downstream projects which was a real pain (one solution in particular has over 100 project files around half of which needed modifying)

However all that was done in a serious session – the next task is taking advantage of the new v5 features – this is a much more subtle undertaking.

Thankfully this is more of an issue with applications using the composition framework rather than the composition framework itself although the DataContextChanged event is one which will need to be taken up in the refactoring – the current code makes use of attached properties via a binding shim to achieve the same…

Update

The codeplex update will arrive in due course – I am still validating the current build – only last week I found a weird bug in the FormViewModel/Form code – interesting since I was only just blogging about that – so that needs to be investigated properly…

Sunday, October 17, 2010

TriStateFormModel, EditorFormModel and EditorForm

For many line-of-business applications there is a common requirement for user-interfaces that can function in one of three contextual modes; view, edit, new. Typically these user-interfaces are often shown in modal dialog scenarios. To cater for this specific scenario the view-model class, TriStateFormModel, was created.

The TriStateFormModel class exposes a number of properties that assist in making dynamic user-interfaces that are dependent on the contextual state of the model.

The EditorFormModel class extends this by providing built-in support for dirty state management and including hooks for saving changes.  The accompanying EditorForm class inherits from Form and extends the ChildWindow template by including additional buttons to handle “save and close”, “apply changes” and “close” commands.

The buttons have the following behaviour;

  • The “apply changes” button is optional and is only enabled if the model is dirty.
  • The “save and close” button is only shown if the model is dirty.
  • The “close” button is marked “cancel” if the view-model is dirty.

These classes are heavily used in one of my serious LOB applications… Smile

Latest Zen Silverlight source available

The latest drop of the Zen Silverlight composition framework has been uploaded to CodePlex – find it here http://www.codeplex.com/ZenSilverlight …

Thursday, October 14, 2010

Turning SilverlightFX into a true MVVM

The original SilverlightFX framework by Nikhil Kothari is a fabulous piece of software. It demonstrates how to create applications where the user interface can be realistically designed in Blend without (in most cases) requiring the use of any code-behind logic.

Currently I have melded this framework together with Prism, Unity, MEF and .NET4 to produce a new all-encompassing framework…

Views

One aspect which I chose to refactor was the code dealing with Views.

The primary motivation for this was a desire to create a custom control view that provided a basic property page. Secondly I wanted my property page to derive from the new ChildWindow control instead of the SilverlightFX Form.

What I really want is four different flavours of view each derived from a different point in the control hierarchy like this;

View – derived from Control

UserView – derived from UserControl

ChildView – derived from ChildWindow

ContentView – derived from ContentControl

The first problem with this approach is that there is already a ContentView in the SilverlightFX framework so the first task is to rename this to TransitioningContentControl which is perhaps a better description of what it does…

Next problem is that of the PageLoader and Controller classes which expect to talk directly to a View – no problem – we will create an IView interface and derive all our ViewXXX classes from it. To get the PageLoader to work we need to add a few methods to this interface.

public interface IView
{
bool IsEnabled
{
get;
set;
}

bool Focus();
void InitializeViewData(IDictionary<string, object> viewData);
}



The implementation of IsEnabled and Focus can be reused from the base implementation in Control.


The remaining method simply caches the dictionary – it is used in the OnLoaded event handler to initialise the view.


While we are here we will also revise the implementation of ViewModel so we can pass the IView object to the view-model during initialisation – this will allow the view-model to communicate with the view in an alternative way to properties and events.

public abstract class ViewModel : Model
{
public virtual void InitializeView(IView view)
{
}
}

Each View class defines an attached-property for storing the ViewModel (I’m sure I only need to do this once and in a single class but in the interests of getting it done I opted for the simplest route – please feel free to experiment!)


The constructor for each View registers for the Loaded event and provides a virtual OnLoaded method. This method is where the heavy lifting of view-model initialisation is performed. To avoid having four copies of the view-model initialisation code this has been refactored into its own class…

protected virtual void OnLoaded()
{
object viewModel = UserView.GetViewModel(this);
if (viewModel == null)
{
viewModel = ViewModelAttribute.CreateViewModel(this);
if (viewModel != null)
{
UserView.SetViewModel(this, viewModel);
}
}
ViewModelInitializer.InitializeModel(this, _viewData, viewModel);
}



The view model initializer class contains the original View code that initialised the view-model using reflection.


The ViewModelAttribute class is almost unchanged although some of the method signatures changed from UserControl to Control to accommodate the new hierarchy.


Controller and PageLoader


The controller and page-loader classes expect View classes and these all had to be changed to use IView instead – makes the code look much nicer in my humble opinion too!


Form


So you make all these changes and eventually the framework will compile again. We don’t get to rest for long because the next change is the one we need to make in order to support our new property page!


Currently the Form is derived from UserView (well it used to be View but to get the code to compile you have probably worked out it now needs to be derived from UserView!) however what would be really cool is to derive the Form from ChildView instead. If we can get this to work we will gain the advantage of using the .NET control for popup forms (which supports being moved, close buttons and a built-in title bar) plus we will be able to create custom controls derived from this and Visual Studio will be happy…


This change isn’t too bad – seems the two classes do play nicely together with a little help.


Here’s what I came up with…

    public class Form : ChildView
{
/// <summary>
/// Represents the CloseEffect property.
/// </summary>
public static readonly DependencyProperty CloseEffectProperty =
DependencyProperty.Register("CloseEffect", typeof(AnimationEffect), typeof(Form), null);

/// <summary>
/// Represents the ShowEffect property.
/// </summary>
public static readonly DependencyProperty ShowEffectProperty =
DependencyProperty.Register("ShowEffect", typeof(AnimationEffect), typeof(Form), null);

private bool _canClose;
private bool _pendingResult;
private bool _executedModelCommand;

private DelegateCommand<object> _cancelCommand;
private DelegateCommand<object> _okCommand;

/// <summary>
/// Gets or sets the effect to be played when the form is closing.
/// </summary>
public AnimationEffect CloseEffect
{
get
{
return (AnimationEffect)GetValue(CloseEffectProperty);
}
set
{
SetValue(CloseEffectProperty, value);
}
}

/// <summary>
/// Gets or sets the effect to be played when the form is being shown.
/// </summary>
public AnimationEffect ShowEffect
{
get
{
return (AnimationEffect)GetValue(ShowEffectProperty);
}
set
{
SetValue(ShowEffectProperty, value);
}
}

/// <summary>
/// Closes the Form with the specified FormResult code.
/// </summary>
/// <param name="result">The result of the Form.</param>
public void Close(bool result)
{
if (!_canClose)
{
return;
}

_canClose = false;

// Run the close effect if we have one otherwise close directly
AnimationEffect closeEffect = CloseEffect;
if (closeEffect == null)
{
// Setting dialog result will automatically close the dialog
// NOTE: I think this is a bug in the ChildWindow...
DialogResult = result;
}
else
{
// Cache the result - we will apply it when the anim finishes
_pendingResult = result;
if (((IAttachedObject)closeEffect).AssociatedObject != this)
{
((IAttachedObject)closeEffect).Attach(this);
closeEffect.Completed += OnCloseEffectCompleted;
}
closeEffect.PlayEffect(AnimationEffectDirection.Forward);
}
}

protected override void OnLoaded()
{
base.OnLoaded();

_cancelCommand = new DelegateCommand<object>(OnCancelCommand);
_okCommand = new DelegateCommand<object>(OnOKCommand);

Resources.Add("CancelCommand", _cancelCommand);
Resources.Add("OKCommand", _okCommand);
}

protected override void OnOpened()
{
// Play the opening effect if we have one
AnimationEffect showEffect = ShowEffect;
if (showEffect == null)
{
_canClose = true;
base.OnOpened();
}
else
{
_canClose = false;

if (((IAttachedObject)showEffect).AssociatedObject != this)
{
((IAttachedObject)showEffect).Attach(this);
showEffect.Completed += OnShowEffectCompleted;
}
showEffect.PlayEffect(AnimationEffectDirection.Forward);
}
}

protected override void OnClosing(CancelEventArgs e)
{
// If we haven't called into the model yet then do it now
if (!_executedModelCommand)
{
ExecuteModelCommand(DialogResult.HasValue ? DialogResult.Value : false);
e.Cancel = true;
return;
}

// Delegate to base class to raise event
base.OnClosing(e);
}

private void ExecuteModelCommand(bool result)
{
FormViewModel model = ChildView.GetViewModel(this) as FormViewModel;
if (model != null)
{
_executedModelCommand = true;
if (result)
{
model.Commit(
delegate()
{
if (model.HasCompleted)
{
if (DialogResult.HasValue)
{
Close();
}
else
{
_canClose = true;
Close(result);
}
}
else
{
// Completion was undone - we will not close
// at this time so re-enable the close action
// and ensure model command will be retried.
_canClose = true;
_executedModelCommand = false;
}
});
}
else
{
model.Cancel(
delegate()
{
if (DialogResult.HasValue)
{
Close();
}
else
{
_canClose = true;
Close(result);
}
});
}
return;
}

if (DialogResult.HasValue)
{
Close();
}
else
{
_canClose = true;
Close(result);
}
}

private void OnCancelCommand(object args)
{
ExecuteModelCommand(false);
}

private void OnOKCommand(object args)
{
ExecuteModelCommand(true);
}

private void OnShowEffectCompleted(object sender, EventArgs e)
{
_canClose = true;
base.OnOpened();
}

private void OnCloseEffectCompleted(object sender, EventArgs e)
{
// Setting dialog result will automatically close the dialog
// NOTE: I think this is a bug in the ChildWindow...
DialogResult = _pendingResult;
}
}



The open and close effect animation stuff should make a fair amount of sense – this is the code that SilverlightFX has that the ChildWindow does not.


The slightly smelly code is that required to call into the view-model – the SilverlightFX version had the advantage of access to methods that are private in the ChildWindow hence the is a little more state needed. If the user uses the close button we want to notify the view-model (obviously if the user uses the cancel command then we can be more explicit in calling the model)


The eagle-eyed among you will have noticed that I sneaked in a HasCompleted property into the view-model – the backing field for this property already exists in the FormViewModel class – I just provided a public getter fot it! It is added to enable the view-model to abort a commit and stop the close action from taking place – this is only supported during commit (not cancel).


The FormModel class gains the following method – this is a breaking behaviour change and means that handlers that connect to the Completed event of a FormModel must check whether the model actually completed before processing the IsCommitted flag…

        protected void CompleteUndo()
{
if (_completed)
{
throw new InvalidOperationException("Model has already been completed.");
}

if (_completedHandler != null)
{
_completedHandler(this, EventArgs.Empty);
}
if (_completeCallback != null)
{
_completeCallback();
}
}



This change will probably come back to bite me real soon…


That will do for now – I will present the TriStateFormModel and finally the EditorForm/EditorFormModel classes in the next episode – until then happy coding!


Oh these view changes have not been uploaded to CodePlex yet – my day job keeps getting in the way but it will happen soon and I’ll blog on here when it does!


Technorati Tags: ,,,

Tuesday, September 14, 2010

Modular Silverlight Applications

So this project of mine is getting out of hand – well okay, so far it’s all simple but it needs to be split before it gets out of hand – so I started looking at how to split the code.

I wanted a solution that would allow the following;

1. Composite Silverlight modules.

2. Composite server service modules.

3. Silverlight shell and corresponding web-server shell.

To ensure loose coupling I also want the Silverlight parts to be loaded using MEF and feature UI integration based on Prism regions.

Seems reasonable enough until you start writing the code…

WCF RIA Integration

I want client/server module communications based on WCF RIA – so there will be a one-to-one match of client module and server module – this allows reuse of the WCF RIA development experience with the least amount of messing about.

The first issue with working in this way is that WCF RIA won’t find the DomainService implementations that are lurking in dynamically loaded assemblies (not to surprising to be honest) so you will need to write the code that publishes the WCF endpoints in a manner that the client modules will be able to find using the default configuration.

Thankfully a short trip on the Reflector road to see how the WCF RIA version is implemented allows us to write a variant of that code that utilises MEF to discover the available DomainServices instead of assuming that the DomainServices are only in the assemblies loaded into the current AppDomain…

Next we need a way to get the DomainService types from the server-side plugins…

Attempt #1

Place the MEF Export attribute directly on the DomainService in the server plugin assembly. This works and the wire-up code even correctly redirects calls to it with little fuss (that code actually worked first time…) however the problems begin when you have a Silverlight client application hooked up to the server project – the Export attribute is propagated to the client-side code – opps! Not required and not possible to disable either… Worse still MEF is used in the Silverlight side too so we can’t even define a dummy Export attribute!

Attempt #2

Harvest the DomainService types in a given plug-in assembly and pass this list of types to the server shell via an MEF exported class. This has none of the problems seen in the first attempt because the MEF attributes are never placed on the DomainService. The solution feels better too as exporting DomainService objects just didn’t feel right!

The only problem is the harvester class must be added to each server module project – a little code smell – alas it was the best I could come up with…

Prism Integration

From the Silverlight side, the shell is built on a heavily modified version of Prism and SilverlightFX (the two frameworks being co-joined, adapted to coexist with MEF and Unity and updated to run under Silverlight v4 – not an insignificant amount of work)

Given this platform the first thing to do is create a Prism IModuleCatalog implementation that can publish the information on the modules available on the server to the default ModuleManager.

The server knows what modules are available to it is a simple leap to create a WCF RIA DomainService in the server shell that can pass this information to the client shell. This is the ClientModuleDomainService. The information passed is much the same as that required by Prism;

  • Module name
  • Module dependencies
  • Load mode
  • Module SHA1 hash
  • Offline-Capable flag

Note: The last two fields are used to extend the OOB install experience to allow modules to be installed to a user’s computer and allow change detection. During start-up in OOB mode the shell will attempt to detect the server and if we determine the server is offline then only the offline-capable modules will be reported to Prism for loading (more on that another time.)

Conclusion

Modular WCF RIA applications are challenging with many ways of implementing a solution that depend on the specific scenario you wish to fill. In my particular case I don’t use the delayed loading feature of Prism – modularity is simply about code organisation and creating focused, loosely-coupled, testable code. Your mileage may differ…

Thursday, July 1, 2010

WCF RIA Services and Silverlight 4

History

Silverlight 4 and WCF RIA Services mark the coming of age for the Silverlight platform and for the creation of Rich Internet Applications as a whole.

Silverlight: the idea is not new but the ability to leverage developer knowledge by reusing the desktop programming framework is.

WCF RIA is a communication framework and as such, it is not new but the integration of the developer tooling and automatic code generation is a marked improvement on all that have come (and gone) before.

What Do We Need?

There is a pressing need for composition – both in terms of UI composition and of application composition. Composite Application Block (aka Prism) was the first implementation from Microsoft that attempted to deal with this feature.

To aid testing, mocking frameworks and loose coupling we also have a need for an integrated IoC solution.

Next we must wait to find out whether the Coordination and Concurrency Runtime (CCR) from the Microsoft Robotics Toolkit will not only be migrated to .NET 4 but also finally put in an appearance on the Silverlight platform. For those of you who have used this framework in robotic/desktop applications will realise that it represents a different approach to parallel programming which also turns out to be very scalable and possess high performance…

We also need a version of SQL Compact Edition for Silverlight – either downloaded as an XAP or available to out-of-browser applications via COM (actually it is possible to hook SQL Compact through Silverlight 4 COM interop – at least it looks like it is possible! I have not yet investigated whether SL4 COM is capable of talking to non-dual/automation COM objects yet…)

Finally we need a version of the Sync Framework for Silverlight (apparently this is in the pipeline) so we can stop writing the synchronisation code…

Yet Another Silverlight Framework

I’m not sure we need yet another Silverlight framework but I know I certainly need something that fills the gap between what I have and what I need.

To this end, I will be creating Yet Another Silverlight Framework that is the lovechild of the following bits and pieces;

1. Built on a foundation of IoC provided by Microsoft Unity v2. The base IoC feature-set is augmented with support for Lazy enumerations and is fully integrated with the .NET Framework v4 composition features exposed by System.ComponentModel.Composition. Encapsulating code originally part of the MEF Contrib CodePlex project (http://mefcontrib.codeplex.com/). Composition is a first-class citizen here. Smile

2. Next I added the composition features of Prism – in particular the module and region management for creating composite UI. The prism source was pretty much lifted as-is.

3. Next I added the Model-View-ViewModel features of the excellent SilverlightFX framework (http://projects.nikhilk.net/SilverlightFX). In so doing, this framework was refactored to take advantage of Silverlight 4 language features and the proprietary IoC replaced in favour of Unity.

4. Next we will integrate a message processor that is capable of queuing operations to a domain service. The queue is actually a priority queue so that different classes of message are handled with differing levels of promptness. The purpose of this queuing logic is two-fold. Firstly it simplifies the code needed to communicate with a domain-service (because you no longer need to check the state of the domain client before issuing a new command) and secondly, it allows for offline and occasionally connected scenarios where the queue can be paused when network connectivity is broken and resumed when connectivity is restored. If the queue is made persistent (via isolated storage) then true off-line capability is then possible. Note that to be truly offline it must be possible to submit requests for data which either go to the server via RIA or are satisfied by some kind of local storage if offline – this is another area I would like to explore in the fullness of time. Imagine if you will, a domain service client proxy object…

5. In lieu of a Silverlight database the best we can do is wrap that functionality into isolated storage and XML files and hide the ugliness with a LINQ-to-XML facade… This at least will work on non-Microsoft client platforms (as opposed to COM interop solutions)

6. With the “XML database” in order we can then take a long hard look at a proxy object alluded to in point 4.

7. Returning to Prism philosophies of supporting dual WPF/Silverlight development paths to ease the creation of composite WPF, MVVM, occasionally connected applications.

So where is it? Okay the first draft has been uploaded to CodePlex and can be seen in all its glory here.

Welcome to Zen Silverlight blog

Hi all,

The purpose of this blog is to discuss various issues and challenges that face all developers hoping to make Silverlight programming more straightforward, powerful and feature-packed.

I will be looking at various issues – most of these are issues I have encountered in commercial projects. I will be attempting to provide source code listings that escape from the typical “hello world” application and showcase enterprise-level application programming techniques, tooling and frameworks.

I’m not at all sure where this will go or (obviously) how it will get there or even if I will know when the destination has been reached – my advice is to just hitch a ride and enjoy the view…