Archive for the ‘Design Patterns’ Category

Adding An Additional Item To A Collection In Entity Framework With Repository Pattern

October 13, 2011

My application has Entities named ‘Hazards’ and ‘Hazard Groups’. A HazardGroup contains many Hazards and the Hazards may be moved from one HazardGroup to another via a Dialog Box.

I found when trying to add an existing Hazard to an existing HazardGroup that I was getting (to paraphrase) ‘Cannot create association: Objects were created in different Data Contexts’ error message. So I needed to put the Hazard and the HazardGroup in the same Object Context.

Here’s how I ended up doing it:

using (var ctx = new HazardContext())
{ {
Hazard movedHazard = _moved hazard returned from my Dialog Box_;
ctx.HazardGroups.Attach(SelectedHazardGroup);
ctx.Hazards.Attach(movedHazard);
SelectedHazardGroup.Hazards.Add(movedHazard);
}

Just to make it spicier I was also using the Repository Pattern, so I had to make sure that my SelectedHazardGroup was attached to the active Repository, like so:

using (var ctx = new HazardContext())
{
IRepository (Of HazardGroup) repo =
new Repository (Of HazardGroup)(ctx);

repo.Attach(SelectedHazardGroup);
Hazard movedHazard = _moved hazard returned from my Dialog Box_;
ctx.Substations.Attach(movedHazard);
SelectedHazardGroup.Hazards.Add(movedHazard);
repo.SaveChanges()
}

HTH.

Integrating WPF Ribbon With Prism and MVVM (with VB.NET example)

January 31, 2010

The WPF Ribbon control is an exciting UI element that provides instant Wow factor to applications and is fun to use, but the current CTP version for Framework v3.5 which is a parallel release for the WPF June 2009 toolkit, does not natively integrate with Prism or MVVM.

Firstly, the RibbonCommand is based on WPF’s standard RoutedUICommand class which does not have the same capacities as Prism’s DelegateCommand and secondly the RibbonCommand requires its CanExecute and Execute Event Handlers in Code Behind which violates the MVVM pattern. In addition, RibbonCommands must be declared as Static Resources which is an unusual restriction on WPF development.

Fortunately there are some smart programmers out there who have grappled with these issues. It turns out you need to:

  1. Sub-class RibbonCommand in order to delegate (that’s dele-GATE as a verb) the RibbonCommand to a Prism DelegateCommand via ICommand;
  2. Provide a Bridging Class which allows Static Resources to connect to a ViewModel Property instead of requiring EventHandlers in Code Behind.

The above is the discovery of sergioesp on the Prism Discussion Forum. I translated his code into VB.NET and added support for InputGestures (Menu Short Cuts).

SergioEsp, you are a legend!

So here’s the beef…

In the XAML for the RibbonWindow you need the following markup:

NB, inf is the xmlns for my Infrastructure project in which I have defined the classes CommandReference and DelegatedRibbonCommand

Window.Resources
inf:CommandReference x:Key="SaveAllCommandReference"
Command="{Binding SaveAllCommand}"/

inf:DelegatedRibbonCommand
x:Key="SaveAllCommand"
LabelTitle="Save All"
LabelDescription="Save all edits (Ctrl+S)"
ToolTipDescription="Save All edits"
ToolTipTitle="Save All (Ctrl+S)"
SmallImageSource="/Images/Ribbon/disk.png"
LargeImageSource="/Images/Ribbon/disk.png"
InputGestureKey="Ctrl+S"
DelegatedCommand="{StaticResource SaveAllCommandReference}" /

/Window.Resources

CommandReference is the Bridging Class that allows StaticResources to connect to a ViewModel Property by exposing a Dependency Property. SergioEsp got this class by using the WPF Futures MVVM Visual Studio Template, version 0.1. I didn’t want to use the MVVM Template, so I just downloaded the code and stole the CommandReference class. Here it is, translated to VB.NET

Imports System
Imports System.Windows
Imports System.Windows.Input

'''
''' This class facilitates associating a key binding in XAML markup to a command
''' defined in a View Model by exposing a Command dependency property.
''' The class derives from Freezable to work around a limitation in WPF when data-binding from XAML.
'''
'''
''' Taken from MSDN WPF Futures MVVM Toolkit v0.1 source. Converted from C# to VB
'''
Public Class CommandReference
Inherits Freezable
Implements ICommand

#Region "Constructor..."

Public Sub CommandReference()
'// Blank
End Sub

#End Region

#Region "Properties..."

Public Shared ReadOnly CommandProperty As DependencyProperty = _
DependencyProperty.Register("Command", GetType(ICommand), GetType(CommandReference), _
New PropertyMetadata(New PropertyChangedCallback(AddressOf OnCommandChanged)))

Public Property Command() As ICommand
Get
Return CType(GetValue(CommandProperty), ICommand)
End Get
Set(ByVal value As ICommand)
SetValue(CommandProperty, value)
End Set
End Property

#End Region

#Region "ICommand Members"

Public Function CanExecute(ByVal parameter As Object) As Boolean Implements ICommand.CanExecute

If Not Command Is Nothing Then
Return Command.CanExecute(parameter)
End If

Return True
End Function

Public Sub Execute(ByVal parameter As Object) Implements ICommand.Execute
Command.Execute(parameter)
End Sub

#End Region

Public Event CanExecuteChanged As EventHandler Implements ICommand.CanExecuteChanged

Private Shared Sub OnCommandChanged(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)

Dim commandReference As CommandReference = CType(d, CommandReference)
Dim oldCommand As ICommand = TryCast(e.OldValue, ICommand)
Dim newCommand As ICommand = TryCast(e.NewValue, ICommand)

'If oldCommand IsNot Nothing Then
' 'RemoveHandler oldCommand.CanExecuteChanged, commandReference.CanExecuteChanged
'End If
'If newCommand IsNot Nothing Then
' newCommand.CanExecuteChanged += commandReference.CanExecuteChanged.Canxecute

'End If

commandReference.Command = newCommand
CommandManager.InvalidateRequerySuggested()

End Sub

#Region "Freezable"

Protected Overrides Function CreateInstanceCore() As Freezable

Throw New NotImplementedException()
End Function

#End Region

End Class

The DelegatedRibbonCommandClass is a translatation of SergioEsp’s RibbonCommandEx class with added support for InputGestures. As you can see, the RibbonCommand is made to use the CanExecute and Execute handlers of the ICommand in the DelegatedCommand Property of DelegatedRibbonCommand.

Since we are using Prism, that DelegatedCommand Property is a Prism DelegateCommand. The ViewModel code is shown further below, but first, here’s the DelegatedRibbonCommandClass:

Imports System.Windows.Input
Imports Microsoft.Windows.Controls.Ribbon

'''
''' Class to delegate a RibbonCommand to an ICommand.
''' Allows RibbonCommands to be used within WPF Prism in a MVVM design pattern
'''
'''
''' Code taken from MSDN Prism Discussion Forum
''' http://wpf.codeplex.com/Thread/View.aspx?ThreadId=52089
'''
Public Class DelegatedRibbonCommand
Inherits RibbonCommand

'''
''' KeyGestureConverter for all DelegatedRibbonCommand instances
'''
'''
Private Shared _myKeyGestureConverter As KeyGestureConverter
Public Shared ReadOnly Property MyKeyGestureConverter() As KeyGestureConverter
Get
If _myKeyGestureConverter Is Nothing Then
_myKeyGestureConverter = New KeyGestureConverter
End If
Return _myKeyGestureConverter
End Get
End Property

'''
''' ICommand that this RibbonCommand will delegate to
'''
'''
Private _delegatedCommand As ICommand
Public Property DelegatedCommand() As ICommand
Get
Return _delegatedCommand
End Get
Set(ByVal value As ICommand)

Me.SetKeyGesture()

If Not _delegatedCommand Is value Then
_delegatedCommand = value
If Not _delegatedCommand Is Nothing Then
AddHandler Me.CanExecute, AddressOf DelegatedRibbonCommand_CanExecute
AddHandler Me.Executed, AddressOf DelegatedRibbonCommand_Executed
Else
RemoveHandler Me.CanExecute, AddressOf DelegatedRibbonCommand_CanExecute
RemoveHandler Me.Executed, AddressOf DelegatedRibbonCommand_Executed
End If
End If
End Set
End Property

'''
''' Property which contains String for InputGesture
'''
'''
Private _inputGestureKey As String
Public Property InputGestureKey() As String
Get
Return _inputGestureKey
End Get
Set(ByVal value As String)
_inputGestureKey = value
End Set
End Property

#Region "Event Handlers..."
'''
''' Event handler for Execute event.
''' Calls Execute method on DelegateCommand
'''
'''
'''
'''
Private Sub DelegatedRibbonCommand_Executed(ByVal sender As Object, _
ByVal e As ExecutedRoutedEventArgs)
DelegatedCommand.Execute(e.Parameter)
End Sub

'''
''' EventHandler for CanExecute event
''' Calls CanExecute function on DelegatedCommand
'''
'''
'''
'''
Private Sub DelegatedRibbonCommand_CanExecute(ByVal sender As Object, _
ByVal e As CanExecuteRoutedEventArgs)
e.CanExecute = DelegatedCommand.CanExecute(e.Parameter)
End Sub

#End Region

'''
''' Set the KeyGesture for this DelegatedRibbonCommand
'''
'''
Private Sub SetKeyGesture()
If Not String.IsNullOrEmpty(Me.InputGestureKey) Then
MyBase.InputGestures.Add( _
MyKeyGestureConverter.ConvertFromString(Me.InputGestureKey))
End If
End Sub

End Class

In the ViewModel, we define the Prism DelegateCommand that we want the Ribbon to use. This is standard Prism and MVVM code.

Private _saveAllCommand as ICommand
Public Property SaveAllCommand() As ICommand
Get
return _saveAllCommand
EndGet
Set(value As ICommand)
_saveAllCommand = value
EndSet

In ViewModel Constructor or some arbitrary InitialiseCommands method:
SaveAllCommand = new DelegateCommand(Of Object)(Address Of Me.SaveAll)

The StaticResource to the ViewModel Property by the markup further up.
The WPFRibbon then uses the Prism DelegateCommand in the ViewModel by referencing the StaticResource.
Note below that the SaveAllCommand is the x:Key for the DelegatedRibbonCommand in the Window Resource, NOT the ICommand ViewModel Property.

r:Ribbon.ApplicationMenu
r:RibbonApplicationMenu Command="{StaticResource MainMenuRootCommand}"
!-- Hack to make sure sub-menu items appear.
Add a RecentItems List
http://www.chakkaradeep.com/post/Proper-way-to-create-Menus-2b-Submenus-in-WPF-Ribbon.aspx--
r:RibbonApplicationMenu.RecentItemList
Rectangle Height="200"/Rectangle
/r:RibbonApplicationMenu.RecentItemList
r:RibbonApplicationMenuItem Command="{StaticResource SaveAllCommand}" /
r:RibbonApplicationMenuItem Command="{StaticResource CloseAllCommand}" /
/r:RibbonApplicationMenu
/r:Ribbon.ApplicationMenu

Happy to answer any questions if any of the above is not clear.

The word in the forums is that Microsoft are rewriting the WPF Ribbon to make it natively compatible with MVVM so hopefully before long we won’t need these additional classes to make it possible.

WPF: Replicating MDI Application Behaviour

November 25, 2009

I decided to use Prism, aka Microsoft Composite Application Guidance For WPF and Silverlight.

This is very much like using a supersonic jet fighter to pop down to the local shops but its effective, not very hard and does not require you to write reams of fragile custom code. You just need to spend a bit of time getting used to Prism. Now that’s not a trivial task, but you should have covered the fundamental concepts within a working week, assuming you have some prior knowledge of Dependency Injection.

The huge advantage to you is that Prism is written by people who are much better programmers than you or I are, so the code is robust, whereas writing a custom MDI Window Manager is out of the league of most Intermediate-level developers (most of us).

Very simply, Prism allows the development of Modular Applications in which the User Interface of an application is decomposed into loosely-coupled Modules, each of which occupies a specific area on the screen, known as a Region.

No window (known in Prism as a View) can move outside the Region in which it is contained. This replicates the MDI-like behaviour you’re looking for.

Prism is also a library of Best Practices – it’s produced by the Microsoft Patterns and Practices team – so you get heaps of built-ins for free. And there’s a helpful forum where others using Prism are happy to help us newbies.

You can also have multiple windows (views) open simultaneously if you want, but this will render as a tabbed interface which is not exactly the same as MDI.

I embarked upon this approach and have been successful in producing a MDI-like app. It wasn’t too hard and I learnt heaps along the way. Go for it.

Update 27-Jan-2010

Ahmed in comments asked me to post the code for my MDI sample.

All I did was use a WPF ContentControl for each Prism Region. A ContentControl can only display one View at any one time, so each time you activate a View the one currently in the Region becomes invisible and the new one you activated becomes visible.

This provides the illusion that there is only one window present at any one time. In fact, all the Views you activated are still there, just invisible until you explictly RegionManager.Remove the View from the Region. This is kind of good though, because the ‘invisible’ views are there in memory and so become visible again instantly you do RegionManager.Activate on them. Effectively this is caching the Views for performance.

So here’s my Shell Window markup:

Grid/
ContentControl Grid.Column="1" Grid.Row="1" cal:RegionManager.RegionName="MainRegion"
VerticalContentAlignment="Top"
VerticalAlignment="Stretch" HorizontalAlignment="Stretch"

ContentControl Grid.Column="1" Grid.Row="1" Name="AdminRegion"
cal:RegionManager.RegionName="AdminRegion"
VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
Grid.ColumnSpan="2"

ContentControl Grid.Column="2" Grid.Row="1" cal:RegionManager.RegionName="ToDoListRegion"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"

/Grid

So you notice I have three ContentControls, one for each of my regions. I also have a Menu with a gazillion MenuItems (not shown).

Each Menu Item is bound to a Prism DelegateCommand like so:

'''
''' Initialise Commands On The Module Menu
'''
Private Sub InitialiseContentCommands()
Me.ContentShowLocalContentCommand = _
New DelegateCommand(Of Object)(AddressOf Me.ShowLocalContent)
Me.ContentShowModuleContentCommand = _
New DelegateCommand(Of Object)(AddressOf Me.ShowModuleContent)
Me.ContentShowModuleDetailsCommand = _
New DelegateCommand(Of Object)(AddressOf Me.ShowModuleDetails)
End Sub

And here’s the ViewModel code related to those DelegateCommands to show the View:

#Region "Module View Injection..."

'''
''' Show Module Content View
''' Update MainRegion with Module Content View
'''
Public Sub ShowModuleContent()
Dim mainRegion As Region = mainView._regionManager.Regions(RegionName.MainRegion)

Dim existingView As Object = mainRegion.GetView(ViewName.ModuleContentView)

If (existingView Is Nothing) Then

Dim moduleContentViewModel As IModuleContentViewModel = _
mainView._container.Resolve(Of IModuleContentViewModel)()
mainRegion.Add(moduleContentViewModel.View, ViewName.ModuleContentView)
mainRegion.Activate(moduleContentViewModel.View)
Else
mainRegion.Activate(existingView)
End If

End Sub

#End Region

Also in the Shell ViewModel I handle a Prism CompositeEvent that is published every time a View is closed in the MainRegion (i.e. by the User clicking on the Close Button for a View. This removes (destroys) the View as opposed to just letting it get overwritten by the next View that gers activated.

#Region "Event Handlers..."

'''
''' Handler for Composite CloseViewEvent
'''
Public Sub CloseViewEventHandler(ByVal closeViewInfo As CloseViewInfo)
Dim regionManager As RegionManager = _
mainView._container.Resolve(Of IRegionManager)()

'Find the region
Dim regionQuery = _
From regn In regionManager.Regions _
Where regn.Name = closeViewInfo.RegionName _
Select regn

' Find the View in the region
Dim region As Region = regionQuery.Single()
Dim view As Object = region.GetView(closeViewInfo.ViewName)

' Remove the view
If view IsNot Nothing Then
region.Remove(view)
End If

' Since ContentControl can only show one view at a time, if any one View is closed
' then no views are visible
Me.AllViewsClosed()
End Sub

I also have a CloseAll MenuItem which closes all the cached (invisible) Views in the Main Region, to give the users and the application the opportunity to clean up all those Views. This is done by having every View Register its CloseButton Command with the a Prism CompositeCommand called CloseAllCommand and having every View provides a handler which Publishes a Prism Event Aggregation event I defined called CloseView.

The Shell ViewModel subscribes to the Event Aggregation CloseView event and removes the calling View from the MainRegion. Since all Views do this, all Views are Removed

In XAML:

MenuItem Header=”_ Close Background Windows” Name=”mniCloseAll”
Command=”{x:Static inf:GlobalCommand.CloseAllCommand}” FontSize=”9″ /

In the ViewModel:

”’
”’ Subscribe to Event Aggregator CloseViewEvent
”’
”’
Private Sub SubscribeCloseViewEvent()

Dim ea As EventAggregator = mainView._container.Resolve(Of IEventAggregator)()

‘ Subscribe to CloseViewEvent
Dim closeViewevent As CloseViewEvent = ea.GetEvent(Of CloseViewEvent)()

If _closeViewSubscriptionToken IsNot Nothing Then
closeViewevent.Unsubscribe(_closeViewSubscriptionToken)
End If

‘ Perform the event on the UIThread
‘ keepSubscriberReference Alive is false. This means the event maintains a
‘ weak reference to the subscriber instance, allowing the garbage collector to
‘ dispose the subscriber instance when there are no other references to it.
‘ When the subscriber instance gets collected, the event automatically unsubscribes.
_closeViewSubscriptionToken = _
closeViewevent.Subscribe(AddressOf CloseViewEventHandler, ThreadOption.UIThread, False)
End Sub

So hopefully you can see that each region only has one View visible at any one time (kind of like a MDI application that I am porting) and because the Views are situated in a Region, they can’t move out of there, which is MDI-like behaviour. No letting your users drag windows all over the screen and losing them.

Careless users.

Over-Complexifying WPF Applications using Prism

October 27, 2009

For those getting started in WPF I recommend the WPF Boot Camp 2008 videos. Make sure you clink on the extended list of links.

An unexpected highlight was Glenn Block of Microsoft Patterns and Practices talking about Prism, the Composite Application Block for WPF. While valiantly attempting to explain Prism to a beginner audience in WPF without assuming prior knowledge of Dependency Injection, Glenn tells us:

There are things we can do to avoid over-complexifying an application beyond its natural complexity

I had trouble understanding this so I used Babelfish to Refactor it into Portuguese, from there into French, from there into German, from there into Greek and than back into English:

It exists things that we can make avoid a sobre-complexifying application apart from their natural complexity

That was a little better, but for added clarity I performed a second-phase refactoring, repeating the previous steps:

It exists the things that a application sobre-complexifying omitted their natural complexity you avoid this they can it can

If you have any further questions, please ping the Microsoft Patterns and Practices Team.

WPF MVVM in VB.NET: Delegating Event Subscriptions for RoutedCommand (or any ICommand) in the ViewModel

October 21, 2009

Just started a new project in WPF. It’s my first WPF project and the firm’s first WPF project. Should be lots to blog about.

Stick One In His Eye

We are using MVVM because the WPF Pantheon (e.g. John Grossman, Josh Smith and Jason Dolinger) are in agreement that this pattern is eminently suited to WPF. So, yeah, we’re taking a bit of a Voodoo Architecture approach.

I am writing a Proof Of Concept using MVVM and found an absolutely brilliant video by Jason Dolinger here which shows a comprehensive refactoring example in MVVM while lucidly explaining the pattern. I was following the vid while coding my Proof Of Concept but got well and truly stuck on the part where Jason delegates (that’s del-e-GATEs as a verb) event subscriptions for the RoutedCommand in the ViewModel.

The Google To End All Googles

The reason I got stuck was that the vid is in C# whereas I am using VB.NET, which is not a problem in itself, but Jason was using C# Event Accessors to delegate the Event subscription. I had never heard of Event Accessors, Jason did not say what they were and VB.NET does not have them (at least not by that name).

I commenced a Google and soon saw that all the MSDN WPF examples are in C# only and not in VB.NET. I was looking for something I didn’t know the name of to do something I didn’t understand in a language which did not have the construct I needed. I was just about to wave a Dead Chicken at the monitor when, in the end Google did cough up an answer…in French. Impossible n’est pas français.

Here’s what had me stuck. What I needed was the VB.NET translation for this code

public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}

First I had to figure out what the heck it was doing. Jason just said ‘now we have to wire the ICommand into the WPF Commanding system’ which left me very little the wiser. Well, ladies and gentlemen what you are witnessing above is the use of an Event Accessor to delegate (That’s del-e-GATE as a verb, not DEL-e-gate as a noun) event subscriptions.

In more detail, the ‘add’ Event Accessor is fired when an Event Subscription to CanExecuteChanged occurs. Value contains the Delegate i.e. Event Handler which is subscribing to the Event. Hence, the Event Handler denoted by value is being added to the Event Handler List for the CommandManager RequerySuggested event. This has the effect of wiring the WPF ICommand object that has that event subscription into the WPF Commanding infrastructure, thus allowing that ICommand to take effect.

VB.NET does not have Event Accessors but it does have a direct equivalent, namely Custom Events. Here’s the equivalent VB.NET code:


Public Custom Event CanExecuteChanged As EventHandler Implements System.Windows.Input.ICommand.CanExecuteChanged
AddHandler(ByVal value As EventHandler)
'This is the AddHandler block
AddHandler CommandManager.RequerySuggested, value
End AddHandler

RemoveHandler(ByVal value As EventHandler)
'This is the RemoveHandler block
RemoveHandler CommandManager.RequerySuggested, value
End RemoveHandler
'
RaiseEvent(ByVal sender As Object, ByVal e As System.EventArgs)
'This is the RaiseEvent block
CommandManager.InvalidateRequerySuggested()
End RaiseEvent
End Event

You can see its the same thing as a set of C# Event Accessors.

For the above code I am sobbing in helpless gratitude to binoo, moderateur of the WPF Forum at Devellopez.Com who posted the above code in this thread, entitled Modèle MVVM – Implémentation ICommand

What Are Custom Events ?

Mesdames and messuirs, you may read about Custom Events here. They enable custom handling of AddHandler, RemoveHandler and RaiseEvent calls for any event.

The above code, for example says that when AddHandler is called for a CanExecuteChanged event that the event handler for that event should be added to the RequerySuggested event of the CommandManager. The inverse happens for RemoveHandler and CommandManager.InvalidateRequerySuggested() is called when a RaiseEvent is done on a CanExecuteChanged event.

Further Reading

I will assume that anyone interested in this post knows about MVVM in WPF and why I would be wanting to wire up ICommand objects in the ViewModel, but for those who have heroically read this far without that pre-requisite knowledge, just click on the MVVM link at the start of the article and the one about the MVVM refactoring video.

And to binoo, now my favourite moderateur in the world, may your hovercraft be ever full of eels and your Brie only Triple Cream.