Monday, October 13, 2008

Composite Extensions for Windows Forms

Have you by chance looked at the cool stuff we produced for Composite Application Guidance for WPF (aka Prism), and wished you could have the same capabilities for Windows Forms, but without needing to adopt CAB/SCSF? Now you can get at least part of those capabilities.

When we were drawing to a close on Prism 1, there were certain things that we would have liked to do, but had to skip to stay within scope and schedule.

One of those things was that we realized that a lot of what we had come up with could be used in Windows Forms as well. Specifically, our module loading, events, and UI Composition patterns could all be used in the context of a Windows Forms application with just a little more effort. For those things that we knew were more general, we at least factored them out to a separate library, Microsoft.Practices.Composite. Alas, that is as far as it went because our charter was for WPF, not Windows Forms.

So I have been trying to find time to complete the work needed to use the non-WPA capabilities of CAL in Windows Forms and finally found a chunk of time at 37K feet on a trip to get it done.

For now I've created these as a stand alone set of libraries that you can add into your own solutions. Feel free to take the code, change the namespaces, etc. Eventually I'll integrate the capabilities into the CompositeWPFContrib libraries so it will be accessible there as well. What I added includes the following:

  • A SimpleUnityBootstrapper base class that removes the dependence on WPF and which removes the parts that create the Shell and Region related stuff. Regions in Prism were implemented in a way specific to WPF, and the CreateShell override in the UnityBootstrapper that comes with Prism expects you to return a DependencyObject, which is also a WPF base class. The SimpleUnityBootstrapper makes it so you can follow the same bootstrapping process as a WPF Prism application to get the container, module, and event services registered and ready to go.
  • A CompositeEvent class and supporting classes that allows you to have the same programming model and infrastructure as Prism loosely coupled Pub / Sub events, but this class supports UI thread dispatching to either Windows Forms, WPF, or any SynchronizationContext aware subscriber. If you are not familiar with the SynchronizationContext class, it came in with .NET 2.0 and provides a standard thread dispatching mechanism that is used by both WPF and Windows Forms under the covers. You can also create custom synchronization contexts for other places that you have thread affinity. If you want to see an example of a custom SynchronizationContext, check out the unit tests. I needed to write a mock SynchronizationContext to verify the dispatching worked correctly.
  • A sample application that shows a way to get a Prism Region-like capability to inject views into the shell.
  • Unit tests for all the supporting library code, most of which were blantantly adapted (mostly direct copy/paste) from the unit tests of Prism since I was trying to create something with pretty much the same API and the same behavior as the Prism counterparts.

I'm not going to pick apart the implementation here unless demand is great enough, but you are welcome to dig into the code in the source.

However, the point was to make it easy to have modular loading and loosely coupled events in a Windows Forms application. So let me show you the use of these capabilities in a sample application. The app itself is very simple, just a drop down list of products and a save selection button to simulate a save operation.

The app, in all its stunning UI glory, looks like this:

AppGrab

The combobox and button are part of a view loaded up by a module, which is loaded through the standard module enumeration and loading services in Prism. When the button is pressed in the view, its ViewModel fires a pub/sub event, which the shell subscribes to and updates the status bar. The view is a Windows Forms user control that I was able to add dynamically to the shell using a simple form of region based on resolution through the container.

So the derived bootstrapper class from the SimpleUnityBootstrapper base class looks like this:

internal class Bootstrapper: SimpleUnityBootstrapper
{
    protected override void ConfigureContainer()
    {
        base.ConfigureContainer();
        Shell = Container.Resolve<Shell>();
    }
    protected override IModuleEnumerator GetModuleEnumerator()
    {
        return new StaticModuleEnumerator().AddModule(typeof(CompositeWFModule));
    }

    public Shell Shell { get; private set; }
 
}

I used the override of ConfigureContainer (same purpose as the UnityBootstrapper ConfigureContainer method) as a convenient place to construct the shell through the container, so that it can participate in dependency injection. This is an alternative approach to the CreateShell override that is required in the UnityBootstrapper of CAL, which is needed in CAL because the base class uses WPF Dependency Properties to add the RegionManager reference as an attached property to the shell after its construction. Since we are in Windows Forms land, that approach won't work, so regions don't exist in my modified libraries, but my sample app shows a way to achieve a lightweight form of dependency injection based on the shell being available through the container.

For module enumeration, you can see that I am just using the StaticModuleEnumerator that ships with CAL. All that is really needed to take advantage of the modular loading capabilities of CAL is a suitable bootstrapper base class that doesn't assume you are in WPF land. Thus my SimpleUnityBootstrapper class.

The Shell property is exposed to make it easy to get the shell to pass to Application.Run in the program's main method:

[STAThread]
static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Bootstrapper bootstrapper = new Bootstrapper();
    bootstrapper.Run();
    Application.Run(bootstrapper.Shell);
}

To create a similar capability to Regions for view injection in the Shell in Windows Forms, I simply have the shell register its containers that it wants to act as a region with the container so they can be resolved by the modules that load up:

public partial class Shell : Form
{
    int m_UIThreadId = Thread.CurrentThread.ManagedThreadId;

    public Shell(IUnityContainer container,IEventAggregator evtAggregator)
    {
        InitializeComponent();
        container.RegisterInstance<Panel>("MainRegion",m_MainRegionPanel);
        evtAggregator.GetEvent<ProductSavedEvent>().Subscribe(OnProductSaved,
ThreadOption.SubscriberAffinityThread); } void OnProductSaved(Product p) { Debug.Assert(Thread.CurrentThread.ManagedThreadId == m_UIThreadId); m_StatusLabel.Text = p.Name + " saved"; } }

Notice that the shell is able to have the container and the CAL event aggregator service injected as dependencies because it was constructed through the container itself (in the bootstrapper shown earlier). It then registers the existing instance of a container control with the container as a named instance (MainRegion in this case) so that a loading module can resolve that named instance to know where to add its views as children.

Ignore the event subscription code for now, I'll get back to that.

The solution has a module library with a module class in it following the patterns of Prism and using the CAL IModule interface definition.

public class CompositeWFModule : IModule
{
    IUnityContainer m_Container;
    public CompositeWFModule(IUnityContainer container)
    {
        m_Container = container;
    }

    public void Initialize()
    {
        Panel mainRegion = m_Container.Resolve<Panel>("MainRegion");
        ModuleView view = m_Container.Resolve<ModuleView>();
        view.Dock = DockStyle.Fill;
        mainRegion.Controls.Add(view);
    }
}

Here you can see how the module injects the view into the pseudo-region. It just resolves the region out of the container with a known container type (yes, you do have to live with some type coupling here, at least to the minimal common denominator base class Panel), and once it has that, it just adds the view as a child control. For  more advanced scenarios such as adding tabs to a tab control you would need more type information to add the child, activate it, set the tab text, etc., but you could still be reasonably loosely coupled to where that control exists in the UI and how it gets constructed.

That is about it for the module loading and a lightweight substitute approach for regions in Windows Forms.

Then the real thing I wanted to get working for Windows Forms is Prism's loosely coupled pub/sub events model. This took a little more work simply because we tied ourselves a little too tightly (in my opinion) to WPF when implementing the UI Thread dispatching option for events in Prism. Both WPF and Windows Forms actually share a common approach to UI thread dispatching under the covers - SynchronizationContext. They both use it a little differently and encapsulate it so you can't directly get to it through their API, but since Windows Forms 2.0, that is available under the covers and in WPF that is what the DispatcherObject base class of UIElements is using to dispatch things to the UI thread.

So what I wrote was a more generic approach to UI thread dispatching under the covers of the CompositeEvent class (following the patterns of the CompositeWpfEvent class in CAL). The dispatching approach checks to see if the subscriber has a synchronization context, and if so, captures it and uses it to dispatch the event back to the UI thread through the SynchronizationContext when the event is fired if the subscriber asked for the event to be dispatched on the "SubscriberAffinityThread" (the name of the ThreadOption enum member I came up with.

I didn't want to call it UIThread because the pattern is actually more general than that. You can create your own SynchronizationContexts with a little work (in fact, I had to do just that to write a mock for the SynchronizationContext to test the code I was writing), and you might do that for specialized scenarios. For example, say you were going to be doing some background work in your app, you wanted to have a custom thread pool of 5 threads, and those threads had thread affinity (i.e. using ThreadLocalStorage). In that case, you could implement a thread pool synchronizer (see the example Thread Pool Attribute in our downloads at IDesign) that would ensure that there was a SynchronizationContext to dispatch to the appropriate thread. In that case, the CompositeEvent class I came up with will properly dispatch based on that SynchronizationContext instead of just a UI one.

So anyway, it is way more complicated to try to explain it than it is to use it. It follows the same simple but powerful patterns and capabilities as the CAL event.

To define an event type, you just derive from my CompositeEvent class instead of the CAL CompositeWpfEvent class, specifying the strongly typed event argument or payload as the generic type parameter:

public class ProductSavedEvent : CompositeEvent<Product>
{
}

To subscribe, you have the single line of code shown earlier in the shell constructor which points to the handling method (strongly typed based on the event argument type:

evtAggregator.GetEvent<ProductSavedEvent>().Subscribe(OnProductSaved,           
ThreadOption.SubscriberAffinityThread);

 

In this case I show the overload that just specifies the threading option, but just like the CAL events, this one supports the same three options in addition to just loosely coupled pub/sub:

  • Weak references or not for the subscriber object to avoid holding the subscriber object alive if the subscription is the only thing keeping it alive
  • Thread dispatching option for the notification
  • Filter delegate based on Predicate<T> to allow strongly typed decision based on the event payload to determine if your subscriber should be called or not.

The publisher code, in this case in the view being loaded up from the module, is just a single line of code like in CAL:

 evtAggregator.GetEvent<ProductSavedEvent>().Publish(product);

So there it is. If you have no exposure to Prism, you really need to start there, because I am not going to try to duplicate all the documentation on the capabilities of Prism. But once you are comfortable with the capabilities of Prism for WPF, now you have some code that will let you directly repeat the use of modules and events from Prism in a Windows Forms application with the exact same patterns, and you also have an example of how to pull off a "Region-like" capability using the IoC container and container controls in Windows Forms.

Feedback highly welcomed. I want to get any needed changes in there before I add it to the trunk for CompositeWPFContrib.

Here's the goods.





Monday, October 13, 2008 2:31:58 AM (GMT Standard Time, UTC+00:00)
Comments [4]  | 


  Saturday, October 11, 2008

SDC Day 2 - Composite WPF and WPF Data Binding

Gave two sessions on the second day at the Software Developers Network conference (aka SDC) in Netherlands.

First was on Prism (Composite Application Guidance for WPF). I covered the architecture of a Prism app and each of the features of Prism (Modules, Regions, Composite Commands, and Composite Events).

You can grab the slides and demos for Developing Composite Applications with Prism here:  Slides   Demos

Second session was on WPF Data Binding, where I showed the many capabilities and how to use WPF data binding.

You can get the slides and demos for WPF Data Binding here:  Slides   Demos





Saturday, October 11, 2008 10:58:00 PM (GMT Standard Time, UTC+00:00)
Comments [0]  | 


  Tuesday, October 07, 2008

SDC Day 1 - SO Workflows and WPF Interop

Gave two sessions yesterday at the Software Developers Network conference (aka SDC) in Netherlands.

First was on using WF as a service technology. I talked about where WF fits into a SO architecture, as well as SO tenets, WF capabilities for services, and then of course, several demos of how to use it. I showed simple use of Send/Receive activities, how to split out the context instance ID from the proxy so it can be handed off to multiple clients, and how to make callsbacks from one workflow to another with service calls.

You can grab the slides and demos for Developing Service Oriented Workflows here:  Slides   Demos

Second session was on Windows Forms and WPF interop, where I showed how easy it is to embed controls from one technology into the other, and then covered some of the limitations and things to be aware of.

You can get the slides and demos for WPF in Windows Forms and Vice Versa here:  Slides   Demos





Tuesday, October 07, 2008 7:30:13 AM (GMT Standard Time, UTC+00:00)
Comments [0]  | 


  Friday, October 03, 2008

Connecting Applications with WCF Talk at RVNUG

I gave a talk on WCF last night at Roanoke Valley .NET Users Group. Thanks to Robin and crew for inviting me and for running the meeting. You've got a great group and facility there!

The talk covered the fundamentals of WCF along with some brief coverage of the advanced capabilities including security, transactions, queued calls, callbacks, reliability, interoperability, and other aspects. A lot of material to pack into an hour and a half along with an end to end demo coded from scratch in terms of the WCF aspects (had an existing business layer and a client that I tacked on to the back and front ends respectively, but did all the service contract, data contracts, config, proxies, etc. on the fly just to show it could be done in an hour easy.

If you are interested in the slides and demos from that talk, you can find them below.

Slides

Demos

For those who attended, the little glitch towards the end of the live coding demo was simply a matter of having two connectionStrings elements in my web.config after pasting in the EF connection string for the database.

This demo, like many of mine, use a music library database I generate from my music collection. You can either download and attach a DB backup from here or you can read about how to generate one of your own from your own collection here.





Friday, October 03, 2008 7:45:09 PM (GMT Standard Time, UTC+00:00)
Comments [0]  | 

Prism on DNRTV

Looks like my episode on Composite WPF (Prism) went live on DNRTV. You can find it here. didn't get through as much as I would have liked due to good questions, so will definitely try to follow up with another one soon covering events and commands.





Friday, October 03, 2008 1:50:09 PM (GMT Standard Time, UTC+00:00)
Comments [2]  | 


  Friday, September 12, 2008

TechEd Online Prism Session is live

Glenn Block (Microsoft) and I did a video interview on buidling composite WPF applications with WPF at TechEd this year, and that interview has now gone live. You can find it in various formats off the TechEd Online landing page or here is a direct link to the low res version.





Friday, September 12, 2008 2:43:45 PM (GMT Standard Time, UTC+00:00)
Comments [0]  | 


  Tuesday, September 02, 2008

MSDN Magazine Article Live - Routed Events and Commands

My article on WPF Routed Events and Commands has gone live at http://msdn.microsoft.com/en-us/magazine/cc785480.aspx. In the article I discuss both how to use them, what is going on under the covers, and how to go beyond their limitations.

 

Also be sure to check out Glenn Block's article on Prism in the same issue: http://msdn.microsoft.com/en-us/magazine/cc785479.aspx





Tuesday, September 02, 2008 2:02:09 PM (GMT Standard Time, UTC+00:00)
Comments [1]  | 


  Monday, September 01, 2008

Custom Refactor Pro Plug-in - Convert Property

UPDATE: Thanks to some excellent feedback from Rory Becker, I changed my plug in from a Refactor provider to a Code provider. A refactoring should be structural and should not change the functionality of the code, whereas this plug in changes behavior. That just means the prompting is a little different as shown in the updated screen grab below. I also made it work for VB as well with some more help from the DevExpress folks. The code download at the bottom gives you the latest version.

Something I frequently find myself doing is starting a type out with simple, auto-implemented properties in C# along these lines:

public string Name { get; set; }

 

Then at some point I realize I want that type to implement INotifyPropertyChanged and have that property and possibly some of the others raise PropertyChanged notifications when they change. I got really tired of doing this manually, and my first way of automating it was to just create a code snippet for a property changed notification property, and I would overwrite the simple property with the property changed property.

But then I found myself needing to see if INotifyPropertyChanged was already implemented, if not add it, resolve it, see if the property already had a backing member variable, if not add it, yadda yadda... screaming for automation.

Unfortunately code snippets in VS are not that powerful, but fortunately I already use a tool that I think every developer should have on their desktop - CodeRush + Refactor Pro.

These two products are built on top of an extensibility engine called DxCore, which allows them as well as VS to be extensible based on a fairly straightforward API (that is all managed code, unlike the VS extensibility model).

In this case what I really wanted was an intelligent refactoring where I could just right click on an existing property, have it figure out if it had a member variable or not, if not add one, see if the type had INotifyPropertyChanged implemented, if not add it, add the using statement for System.ComponentModel if it was not already there, and add the PropertyChanged event with an anonymous method subscriber (so that you don't need to null check and don't have to worry about multithreaded race conditions with unsubscribing).

With a few hints and a starter project from my friends at DevExpress I got a Refactor Pro plug-in working in no time that does just that. I can invoke Refactor Pro (keystroke or a mouse click) on a simple property (auto-backing member or not) and get this:

refactor

When I invoke the conversion, it adds the INotifyPropertyChanged implementation if needed. So the following simple class:

public class Customer
{
    public string Name { get; set; }
}

 

Becomes this:

public class Customer : INotifyPropertyChanged
{
    string m_Name;
    public string Name
    {
        get
        {
            return m_Name;
        }
        set
        {
            if (value != m_Name)
            {
                m_Name = value;
                PropertyChanged(this, new PropertyChangedEventArgs("Name"));
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged = delegate { };
}

It also adds the using statement for System.ComponentModel if not already present. If I invoke it on another simple property in that class, it just adds the expanded property syntax and leaves the type declaration alone.

The code is a little too long to list here, but you can download the plug-in code here. If there is enough demand through comments, I'll do a follow on post with a walk through of the code.





Monday, September 01, 2008 10:41:58 PM (GMT Standard Time, UTC+00:00)
Comments [3]  | 

Accelerating Code Analysis and Improving Code Quality with NDepend

I've been working on a project for a customer where a fairly large pile of code has been written by an offshore vendor and I was brought in to do a code review and some clean up and verification of the logic. As I dove into the code, the smells started to become overwhelming.

Trying to work through the entire code base and figure out where to focus my clean up efforts first was a daunting task. However, a wonderful tool called NDepend came to the rescue. If you haven't ever heard of this awesome tool and you have oversight responsibility for a team of developers, you should really check it out.

I can't show screenshots here because the code has namespaces that reveal the client name, but you can find a number of screenshots on the NDepend site itself.

Basically NDepend will do a static analysis of your code base and help you identify everything from tightly coupled code containing too many dependencies (thus the name), but tons of other code metrics including line of code count, cyclomatic complexity, and others. It has a rich interactive UI for drilling into the code from the graphical charts that present you color coded views of where you need to focus as well as a web report generated view that you can view through a browser. You can analyze the code through a number of metrics, and it comes with a powerful query language called CQL (Code Query Language) that lets you look for particular patterns that you want to focus on.

I'd say this is a tool any technical lead, senior developer, or architect in charge of code quality should have in their toolbox.





Monday, September 01, 2008 4:31:08 PM (GMT Standard Time, UTC+00:00)
Comments [0]  | 


  Friday, August 22, 2008

TechEd Online Session posted

One of the many events I had at TechEd this year was recording a TechEd Online video interview. That has finally gone online. The subject was Selecting the Right Client Technology.

You can find all of the TechEd Online sessions here:

http://msdn.microsoft.com/en-us/events/teched/cc676818.aspx

You can download / view my session from the following links:

Hi Res: 08_NA_Dev_techtalk_48_high.wmv

Low Res: 08_NA_Dev_techtalk_48_low.wmv

Audio Only: 08_NA_Dev_techtalk_48_audio.MP3





Friday, August 22, 2008 9:17:36 PM (GMT Standard Time, UTC+00:00)
Comments [0]  | 

Composite Application Guidance podcast is up

I recorded a podcast on Composite Application Guidance for WPF (aka Prism) this week and it just went live. If you are trying to get your head around how to build complex UI applications with WPF and have been considering Composite WPF as a way to help manage the complexity, you should check it out.

http://getpixel8ed.com/shows/prism





Friday, August 22, 2008 9:13:38 PM (GMT Standard Time, UTC+00:00)
Comments [0]  | 





















Sign In
Copyright © 2006-2007 Brian Noyes. All rights reserved.
designed by NUKEATION STUDIOS