Archive

Archive for the ‘Patterns’ Category

Coding for XAML

April 1, 2010 1 comment

XAML is basically a way of describing object structures, which will be instantiated by the XAML parser when a page, resource or template is used. Since one of the ideas in WPFGlue is to configure components in XAML, I had to wrestle a bit with the VS XAML designer and my classes in order to make them work well with each other. This post is about what patterns you can use in order to make classes nice to use in XAML, and how to implement them.

Basics

A XAML tag is basically nothing but a class name and some attributes. The class name stands for the component, the attributes, for its properties. What the XAML parser will do is to create an instance of the class using a parameterless constructor, and to set the properties which have the same names as the attributes to the provided attribute values. So, the basic rules for creating a class for use in XAML are:

  • The class must be public.
  • It must have a public, parameterless constructor.
  • All properties that will be accessed in XAML must be public.

Two other best practices turned out to influence the XAML experience of my custom components, even though I didn’t quite find out why, and I expect this behaviour to change with version 4.0… Well, the problem was that the VS 2008 XAML editor didn’t recognize collection types properly, and that its Intellisense function would suggest every available element, not only the one which are allowed in the collection.

In order to fix that, I did the following:

    Using the ContentProperty Attribute

    XAML elements can have one or many content elements. A content element is something like the “natural” or most important child element of its parent. It is special because you can set it in XAML without mentioning the name of the property which references it. However, in order to create an object structure, the XAML parser needs to know the property name. Therefore, you can set the name of the property which holds the child element by adding the System.Windows.Markup.ContentProperty(“MyChild”) attribute to the class declaration, where “MyChild” would be the name of the property which holds the child.

    If the property is of an collection type, the element can contain multiple child elements, and they will all be added to the collection which the property holds.

    Collections for XAML

    If you set up your project like I explained in the first section, all you have to do is to derive a collection class from List(Of T) or ObservableCollection(Of T), where T is your item type.

    Public Class XamlCollection
        Inherits List(Of XamlCollectionItem)

    End Class

    Public Class XamlCollectionItem

        Private _IntegerValue As Integer
        Public Property IntegerValue() As Integer
            Get
                Return _IntegerValue
            End Get
            Set(ByVal value As Integer)
                _IntegerValue = value
            End Set
        End Property

    End Class

    If you do it this way, the XAML will display and compile without problems, and Intellisense will offer you only the available classes of the correct type. Normally, since we are talking about configuring components through XAML, the collection is not expected to change during run time, so it would be enough to use List(Of T).

    If you want to use a collection type as the content for an element, you’d have to do the following further steps:

    • Create a read-only property which holds an instance of the collection type.
    • Initialize it with an empty collection in the elements constructor.
    • Set the ContentProperty attribute to the property’s name.
    <System.Windows.Markup.ContentProperty("Children")> _
    Public Class XamlCollectionParent
        Private _Children As New XamlCollection
        Public ReadOnly Property Children() As XamlCollection
            Get
                Return _Children
            End Get
        End Property
    End Class

    Referring to Objects by Name I: Keyed Collections

    Sometimes you want to refer to be able to refer to specific children of an element. The best way to make sure that you get the correct child is to name the children and to refer to them by name. In XAML, you would do this in a binding’s property path, like this: {Binding Path=MyParentElement.Children[ChildName]}

    In order to be able to do that, you’d derive the collection class from KeyedCollection(Of T). Then you’d have to override the GetKeyForItem function, which is supposed to create a unique string key from an item of type T.

    Public Class XamlDictionary
        Inherits System.Collections.ObjectModel.KeyedCollection(Of String, XamlDictionaryItem)

        Protected Overrides Function GetKeyForItem(ByVal item As XamlDictionaryItem) As String
            Return item.Key
        End Function
    End Class

    Public Class XamlDictionaryItem
        Private _Key As String
        Public Property Key() As String
            Get
                Return _Key
            End Get
            Set(ByVal value As String)
                _Key = value
            End Set
        End Property

        Private _IntegerValue As Integer
        Public Property IntegerValue() As Integer
            Get
                Return _IntegerValue
            End Get
            Set(ByVal value As Integer)
                _IntegerValue = value
            End Set
        End Property
    End Class

    You may ask why I don’t use Dictionary(Of TKey, TValue). Well, it seems that XAML’s support for dictionaries is very much geared towards the special needs of ResourceDictionaries, and I believe it is not intended to be used generally. However, KeyedCollection offers you the additional benefit that you can simply iterate over the items and don’t have to worry about mapping Key / Value pairs, since the keys are taken directly from the items.

    Referring to Objects by Name II: NameScopes

    A NameScope in WPF is what makes element names in a page unique and allows to reference elements by name using their x:Name attribute. If you have a tree structure of elements, but need to reference single elements by name also, a NameScope is the thing to use.

    A Namescope is defined through a root element XAML. All descendants of this element which have an x:Name attribute will automatically be registered to the Namescope. In order for this to work, you have to do the following:

    • The class which is the root element has to implement the System.Windows.Markup.INameScope interface. Internally, the implementation can be based on the NameScope class, which comes with the WPF framework.
    • The classes which are used as descendants of the root element need to use the System.Windows.Markup.RuntimeNameProperty attribute in their declaration, so that the XAML parser knows which property of the class stores the name.
    • In order to access the items by name, one needs an indexer. XAML is a little bit limited in its support for indexed properties: you have to have a class which declares the indexer as its default property. In order to provide indexed access to the named elements, this examples uses a nested class which does nothing but find the elements through its parent’s NameScope.
    Private _Indexer As New NamescopeIndexer(Me)
    Public ReadOnly Property Node() As NamescopeIndexer
        Get
            Return _Indexer
        End Get
    End Property

    Public Class NamescopeIndexer
        Private _Root As XamlNamescopeRoot
        Friend Sub New(ByVal root As XamlNamescopeRoot)
            MyBase.New()
            _Root = root
        End Sub

        Default Public ReadOnly Property Item(ByVal name As String) As NamescopeNode
            Get
                Return _Root.Namescope.FindName(name)
            End Get
        End Property
    End Class

     

    Markup Extensions

    Markup extensions are helpful in situations where you have to do more complicated things than just creating an instance of a class and assign it some values. For example, you can use a Markup extension if you want to establish a binding, or if you want to access a backing store which itself is not accessible to XAML, like application settings, localized resources or a configuration file.

    However, I am not very fond of markup extensions. They are basically a convenience: normally, you can achieve the same using just a more verbose syntax. And the convenience comes at a price:

    Markup extensions have to execute well both at runtime and in the VS designer. Both environments are radically different, and it is not trivial to find out the difference from inside the markup extension. Also, if there is any problem in design mode, there is no debugging support, since the designer always uses the release compiled version of the markup extension. Moreover, I even couldn’t use structured error handling inside the class, since my catch blocks never were called, and sometimes VS crashes when compiling or editing markup extensions.

    Anyway, for the sake of completeness, here what I learned:

    • Derive a markup extension from System.Windows.Markup.MarkupExtension and override the ProvideValue method.
    • Set the MarkupExtensionReturnType attribute to the correct type.
    • If the type of the serviceProvider parameter is System.Windows.Markup.ProvideValueServiceProvider, you are in runtime mode, otherwise, you are in design mode.
    • Use serviceProvider.GetService(GetType(IProvideValueTarget)) in order to retrieve information about the property which will receive the value. If the TargetProperty parameter is of type DependencyProperty, the property is a dependency property and you can do things like set up a binding, so that the value will be updated automatically if the underlying data source changes.
    • Always return a valid value of the correct type, even if the value is some message like “I couldn’t find what you wanted”.
    • Whatever you do, avoid exceptions in the ProvideValue method at all costs. In this case this doesn’t mean “catch”, but really “avoid”, since structured exception handling doesn’t seem to work when the extension is used in the designer.

    Reporting Configuration Errors

    As a rule, your component shouldn’t raise any exceptions if it doesn’t have all the information it needs to do its job, but just make do without it, using intelligent default behaviour or gracefully reducing the functionality. However, sometimes you just have to report something.

    In this case, you can raise an ArgumentException with an appropriate message in the property setter which receives the invalid value. Exceptions that are raised in this way will show up in the VS Error List and keep the project from building.

    Other Best Practices

    • Don’t do complex things like e.g. accessing a database in a constructor. Constructors will run at design time as well as at run time. So, if they need information from the application they are running in, this information might not be accessible at design time. Therefore, one might see strange error messages at design time which are difficult to debug.
    • Don’t rely on a certain order in which the properties of your component should be set. If you need several property values in order to do a job, either don’t access the values until you need to do the job, or check whether you have a complete set of values each time any of the properties changes, and start the job as soon as you have a valid set of values.

    Conclusion

    If you follow these guidelines, your components will behave similar to the components that come with the WPF framework, and they will integrate into the support given by the VS XAML editor.

    There are some other techniques which I haven’t covered here, but which I would like to mention: using dependency properties and using type converters. You can find examples for dependency properties all over this blog, e.g. here: https://wpfglue.wordpress.com/2009/12/16/the-sticky-viewmodel-pattern/ . An example for using type converters is given in this post: https://wpfglue.wordpress.com/2009/11/30/css-class-equivalent-in-wpf/ . Otherwise, you will find the patterns which I discussed here everywhere in the WPFGlue code. A special example project for this post is available for download here:

    (as always on wordpress.com, you will have to rename it to a .zip extension in order to extract it).

    Categories: Patterns

    The Sticky ViewModel Pattern

    December 16, 2009 1 comment

    A Sticky ViewModel is a special type of Sticky Component which adds functionality to the ViewModel instead of to the View. By binding to the DataContext of its base element, the Sticky ViewModel is able to provide services which the ViewModel itself doesn’t include. In this respect, it is similar to the Mini-ViewModel pattern, which you might prefer if you want to provide an encapsulated reusable View for the added functionality as well.

    An Example

    The model or ViewModel might have a property which contains a persons name. In the View, you might want to be able to edit first name and last name separately. I have already discussed this example in the context of the Stateless Sticky ViewModel pattern, so here I want to add some extra: the new implementation should format the name either John Smith or Smith, John, depending on a boolean property LastNameFirst which one can use to configure the behaviour.

    The example is contained in the StickyComponentExample project which you will find in the WPFGluePublished solution on the Downloads page.

    Using a Sticky ViewModel

    Like any other Sticky Component, you would initialize a Sticky ViewModel in the resources of an element that wants to use them:

    <Grid.Resources>
      <ex:NameStickyViewModel x:Key="viewModel"
          LastNameFirst="True" FullName="{f:StickyBinding Name}"/>
    </Grid.Resources>

    Using the LastNameFirst property, we specify that we want the full name displayed in the Smith, John format.

    But what is the meaning of the {f:StickyBinding } markup extension? It is understood that the Sticky ViewModel somehow accesses the DataContext of its base element in order to enhance it. In fact, there is a DataContext property in the StickyViewModel base class which is synchronized with the base’s DataContext automatically.

    However, if the Sticky ViewModel would get the information it needs directly from the DataContext, it would have to know its type, thus being closely coupled to the ViewModel, which we want to avoid, since we want to be able to re-use the Sticky ViewModel wherever we need its functionality. So, the idea is to get the necessary information from the DataContext through data binding. Unfortunately, since the Sticky ViewModel is not part of the logical WPF tree, normal bindings cannot access the base element’s DataContext implicitly, like child controls. So, we use a special binding class, the StickyBinding, which allows us to bind to the DataContext of the StickyViewModel, instead. By writing FullName=”{f:StickyBinding Name}” we instruct the StickyViewModel to look for the value it should edit in the Name property of the model the element is bound to.

    As usual, the Sticky ViewModel is attached to its base through an attached property:

    <Grid x:Name="base"
      ex:NameStickyViewModel.ViewModel="{DynamicResource viewModel}"
          HorizontalAlignment="Stretch">

    In this case, we have to refer to it with a DynamicResource extension, since it is contained in the resources of the element it is used on and thus is referred to before it is declared. We could also put it into the page’s resources and use a StaticResource extension. (StaticResource extensions are less complicated, so they are a little bit safer and faster, but they can only be specified where the definition comes before the reference in the XAML). However, in the example, the NameStickyViewModel is used in a DataTemplate for a ListView. So, every row of the ListView needs its own instance of the Sticky ViewModel, otherwise the names from different rows will start mixing. We can make sure of this either by putting the declaration of the StickyViewModel into the DataTemplate itself, as I have done here, or by setting x:Shared=”False” where we declare it, which tells WPF to create a new instance of a resource every time it is accessed.

    The rest of the DataTemplate defines three TextBoxes for each row:

    <TextBox Text="{Binding Name, TargetNullValue='[New Customer]'}"
             Margin="30,0,0,0"/>
    <TextBox Grid.Column="1" Text="{Binding ElementName=base,
      Path=(ex:NameStickyViewModel.ViewModel).LastName}"/>
    <TextBox Grid.Column="2" Text="{Binding ElementName=base,
      Path=(ex:NameStickyViewModel.ViewModel).FirstName}"/>

    The first TextBox is bound directly to the DataContext of the DataTemplate. It refers to the property in the model that contains the full name of a person. The other two TextBoxes are bound to the StickyViewModel that lives on the element named “base”; this element is the Grid from above.

    Implementing the Sticky ViewModel Pattern

    In order to support binding on their properties, Sticky ViewModels are derived from DependencyObject and expose their working properties as DependencyProperties. Configuration properties don’t need to be data bound, so they are defined as normal properties.

    Like in the Stateless Sticky ViewModel, after implementing the logic which does what the model should do, the main point is distributing the change notifications from the different properties so that the logic is called at the right time. This happens in the OnPropertyChanged method of the Sticky ViewModel, which is originally defined in DependencyObject:

    Protected Overrides Sub OnPropertyChanged(ByVal e As System.Windows.DependencyPropertyChangedEventArgs)
        MyBase.OnPropertyChanged(e)
        Static changeInitiator As DependencyProperty = Nothing

        If changeInitiator Is Nothing Then
            changeInitiator = e.Property

            Select Case e.Property.Name
                Case "FullName"
                    FirstName = DetermineFirstName(FullName)
                    LastName = DetermineLastName(FullName)
                Case "FirstName", "LastName"
                    FullName = DetermineFullName(FirstName, LastName)
            End Select

            changeInitiator = Nothing
        End If
    End Sub

     

    Again like in the Stateless Sticky ViewModel, we remember between invocations which property started the change and cancel subsequent invocations of the method. However, this time the code is a little bit shorter and cleaner and not distributed between different methods (I just notice that one could implement it the same way with a Stateless Sticky ViewModel, but alas… never get it perfect the first time.)

    Under the Hood

    The Sticky Component Framework supports the Sticky ViewModel pattern with two components: the StickyViewModel base class, which can be used to derive one’s own Sticky ViewModels, and the StickyBinding, which one needs to be able to bind to the properties of the Sticky ViewModel’s DataContext.

    The StickyViewModel class mainly manages attaching and detaching the ViewModel on its base element:

    Public Sub OnAttach(ByVal sender As Object, ByVal e As System.EventArgs) Implements IStickyComponent.OnAttach
        Me.DataContext = StickyComponentManager.GetDataContext(sender)
        StickyComponentManager.AttachDataContextChanged(sender, AddressOf _DataContextChanged)
        Attach(sender, e)
    End Sub

    Public Sub OnDetach(ByVal sender As Object, ByVal e As System.EventArgs) Implements IStickyComponent.OnDetach
        Me.DataContext = Nothing
        StickyComponentManager.DetachDataContextChanged(sender, AddressOf _DataContextChanged)
        Detach(sender, e)
    End Sub

    It adds a handler to the base’s DataContextChanged event, so that the DataContext stays synchronised with the base’s DataContext. DataContext is a DependencyProperty, so it provides its own change notifications. Furthermore, the class defines a generic ViewModel attached property which can be used in derived classes in order to attach the model to the element.

    The StickyBindingExtension basically is a BindingExtension with a reduced set of properties (everything related to input and validation is not needed on the StickyBinding), and in principle delegates all it does to this binding:

    Public Overrides Function ProvideValue(ByVal serviceProvider As System.IServiceProvider) As Object
        Dim target As System.Windows.Markup.IProvideValueTarget = serviceProvider.GetService(GetType(System.Windows.Markup.IProvideValueTarget))
        If target IsNot Nothing Then
            If TypeOf target.TargetProperty Is DependencyProperty Then
                If TypeOf target.TargetObject Is StickyViewModel Then
                    Dim dataPath As String = "DataContext"
                    If Not String.IsNullOrEmpty(Path) Then
                        If Path.StartsWith("/") Or Path.StartsWith("[") Then
                            dataPath &= Path
                        Else
                            dataPath &= "." & Path
                        End If
                    End If
                    Dim b As New Binding(dataPath)
                    b.Source = target.TargetObject
                    b.Mode = Mode
                    b.Converter = Converter
                    b.ConverterCulture = ConverterCulture
                    b.ConverterParameter = ConverterParameter
                    Return b.ProvideValue(serviceProvider)
                End If
            End If
        End If
        Return Me
    End Function

     

    The trick here is to prefix the binding’s path with the DataContext property and always use the target object as source. Thus, following the principles of WPFGlue, I avoid to implement my own version of change notification listeners and instead use what is already there. Since the DataContext is always synchronized with the the base’s DataContext and provides change notification, the StickyBinding will always be able to find the correct property without any explicit dependencies.

    Notice that the last line in the block that creates the binding returns Binding.ProvideValue. This is necessary in order to mimic Binding’s behaviour in all contexts.

    Comparing Stateless and Stateful Sticky ViewModel

    As mentioned before, the main advantage of the Stateful Sticky ViewModel is that it bundles configuration properties in one place and forms a better defined unit than the Stateless version. Its main focus is on the base’s DataContext. Sticky Bindings don’t support binding to properties of elements in the logical tree, as it would be possible with the ElementName or RelativeSource properties of a normal binding. However, if one needs that, one can combine the two patterns and define attached properties on the Sticky ViewModel for no other purpose than to be able to bind them to logical tree elements, and access them through a reference to the base that is acquired during Attach and of course released during Detach.

    Coming Soon…

    The Sticky Component Framework is still once removed from a real application… the next step will be a Commanding Framework based on Sticky Components which allows to define RoutedCommands, their keyboard shortcuts and display texts in one place, delegating their invocations to methods or ICommand implementations in the ViewModel or model.

    The Sticky Component Framework

    December 11, 2009 3 comments

    What is a Sticky Component? A Sticky Component is a component that can be attached to any FrameworkElement or FrameworkContentElement in order to enhance its functionality, without the need to subclass the element or to write code behind for it. Because of this, Sticky Components can be used very effectively to encapsulate specialized behaviours in a reusable way, and to enhance either the View or the ViewModel of an MVVM application without changing its code.

    Sticky Component Interaction Patterns

    In order to enhance the functionality of an element, the Sticky Component needs to interact with the element. There are several possible ways to connect the two:

    • Through registering event handlers: The Sticky Component can subscribe to events of the element it is attached to, and trigger its own functionality through these events.
    • Through registering CommandBindings: The Sticky Component can add its own CommandBindings to the element’s CommandBindings collection, thus enabling the element to handle the specified command.
    • Through registering InputBindings: the Sticky Component can enable an element to invoke commands by adding InputBindings to its InputBindings collection.
    • Through data binding: the Sticky Component can bind its own properties to the properties of the element. These bindings could in principle have the element as target or as source. But since many properties in the WPF framework are readonly, it is less error prone to always make the Sticky Component the binding target by convention.
    • Through binding to the element’s DataContext: a special class of Sticky Component, the Sticky ViewModel, doesn’t enhance the View, but the ViewModel, by binding to its properties and adding functionality that isn’t present in the ViewModel without the need to change it.

    Some of these patterns require references between the Sticky ViewModel and the element it is attached to (its “base”). References are dangerous. They may cause memory leaks and unintended behaviour, e.g. if events are handled even if the view that established the event subscription is already out of scope. Therefore, the core of the Sticky Component Framework is concerned with managing the lifetime of a Sticky Component and its interaction patterns so that all these references are cleaned up when appropriate.

    Sticky Component Lifetime

    The life cycle of a Sticky Component looks like follows:

    • It is defined and configured in the Resources of the application, a window, or an individual element.
    • It is referenced in an attached property on the base element it is attached to. This is the time when the Sticky Component is actually instantiated.
    • It attaches itself to the base. This can happen either immediately or delayed, depending on whether the base must be in initialized or loaded state before the component can attach to it.

    The end of the component’s relationship to the base could come in two ways:

    • Either the attached property which connects the component to the base is reset,
    • or the base itself is unloaded.

    In both cases, all references between the Sticky Component and its base should be removed, leaving either object ready for garbage collection. If the component still exists after it has been detached from its base (e.g. because it is kept as a shared instance in a ResourceDictionary), it could be attached again to a different base, or even the same, if that still is available.

    This lifetime pattern is expressed in the following interface definition:

    Public Enum AttachMode As Integer
        Immediate = 0
        OnInitialized = 1
        OnLoaded = 2
    End Enum

    Public Interface IStickyComponent

        Sub OnAttach(ByVal base As Object, ByVal e As EventArgs)

        Sub OnDetach(ByVal base As Object, ByVal e As EventArgs)

        ReadOnly Property Mode() As AttachMode

    End Interface

    OnAttach will be called whenever the Sticky Component will be attached to a base, OnDetach will be called when it is detached. Both methods have EventHandler signatures, so that they can be invoked by the Initialized, Loaded or Unloaded events, respectively. The Mode property defines when the component should attach itself to the element. If possible, the component should attach itself immediately. However, if it needs to modify existing bindings, it will have to do that during the Initialized event, and if it needs to access properties that are data bound, like e.g. the DataContext of the base, it might have to wait until the Loaded event. Since these requirements depend on what the component does, it would be expected that a class that implements IStickyComponent would return a constant value here.

    The StickyComponentManager

    The StickyComponentManager is a static class that encapsulates the different ways to establish and remove interaction connections between a Sticky Component and its base. It offers overloaded Attach and Detach procedures in pairs with corresponding parameters. So, one would attach an event to a base using the Attach(base,event,handler) overload, and remove it again using the Detach(base, event,handler) overload. There are overloads for all cases discussed here; some of these overloads offer additional services; e.g. there are overloads for attaching event handlers which automatically remove the event handler after it has fired once (using the One Shot Event pattern), or if another specified event occurs before the event that the handler is supposed to handle.

    In your Sticky Component, you would set up the connection to the base by calling the appropriate Attach methods of the StickyComponentManager in your OnAttach implementation, and remove the connection by calling the corresponding Detach methods in the OnDetach implementation.

    The most important overloads of these methods are the ones that attach / detach Sticky Components. There is a special implementation of a DependencyPropertyChangedHandler that you can use with your attached properties that attach Sticky Components which calls these overloads:

    Public Shared Sub OnStickyComponentChanged(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
        Dim c As IStickyComponent
        If e.OldValue IsNot e.NewValue Then
            c = TryCast(e.OldValue, IStickyComponent)
            If c IsNot Nothing Then
                StickyComponentManager.Detach(d, c)
            End If
            c = TryCast(e.NewValue, IStickyComponent)
            If c IsNot Nothing Then
                StickyComponentManager.Attach(d, c)
            End If
        End If
    End Sub

    This will ensure that the lifetime of the sticky component is managed according to the life cycle described above.

    In addition to the Attach and Detach methods, the StickyComponentManager contains several utility methods which hide the difference between FrameworkElement and FrameworkContentElement when attaching Sticky Components. So, elements derived from both of these classes could be the base for Sticky Components; on other elements, the Attach / Detach methods would simply do nothing.

    Using Sticky Components

    In XAML, you would normally declare and configure a Sticky Component in a Resources section, like this:

        <ex:TestStickyPatterns x:Key="UseEvents"
            Name="UseEvents" UseCommand="False"/>
    </Page.Resources>

    This would define a Sticky Component of class TestStickyPatterns and configure it by setting its Name and UseCommand properties.

    You would then use it on a base element like this:

        <Button x:Name="TestEventPatternsButton"
              ex:TestStickyPatterns.Component="{StaticResource UseEvents}">
        Test Event Patterns</Button>

     

    If you need the Sticky Component more than once on your page, consider setting the x:Shared attribute to false on its declaration. Thus you make sure that each time the component is used, you start with a fresh instance. Otherwise it could happen that the component is attached to multiple elements on your page at the same time, with unwelcome results.

    Implementing Sticky Components

    The TestStickyPatterns.Component attached property would be defined like this:

    Public Shared ReadOnly ComponentProperty As DependencyProperty = _
        DependencyProperty.RegisterAttached("Component", _
        GetType(IStickyComponent), GetType(StickyTestComponent), _
        New PropertyMetadata(AddressOf StickyComponentManager.OnStickyComponentChanged))
    Public Shared Function GetComponent(ByVal d As DependencyObject) As IStickyComponent
        Return d.GetValue(ComponentProperty)
    End Function
    Public Shared Sub SetComponent(ByVal d As DependencyObject, _
                                   ByVal value As IStickyComponent)
        d.SetValue(ComponentProperty, value)
    End Sub

    Notice that the property metadata refers to the shared (static in C#) method StickyComponentManager.OnStickyComponentChanged in order to enable lifecycle management for the component.

    Its OnAttach and OnDetach implementations look as follows:

    Public Sub OnAttach(ByVal sender As Object, ByVal e As EventArgs) Implements IStickyComponent.OnAttach
        MyBase.OnAttach(sender, e)
        If _UseCommand Then
            StickyComponentManager.Attach(sender, MyCommand, AddressOf OnExecuted, Nothing)
            StickyComponentManager.Attach(sender, New KeyGesture(Key.Space, ModifierKeys.Control), MyCommand)
        Else
            StickyComponentManager.Attach(sender, ButtonBase.ClickEvent, AddressOf OnClick)
            StickyComponentManager.Attach(sender, ButtonBase.ClickEvent, AddressOf OnClickOneShot, True)
            StickyComponentManager.Attach(sender, ButtonBase.ClickEvent, AddressOf OnClickCancel, FocusManager.LostFocusEvent)
        End If
    End Sub

    Public Sub OnDetach(ByVal sender As Object, ByVal e As EventArgs) Implements IStickyComponent.OnDetach
        MyBase.OnDetach(sender, e)
        If _UseCommand Then
            StickyComponentManager.Detach(sender, New KeyGesture(Key.Space, ModifierKeys.Control))
            StickyComponentManager.Detach(sender, MyCommand)
        Else
            StickyComponentManager.Detach(sender, ButtonBase.ClickEvent, AddressOf OnClick)
            StickyComponentManager.Detach(sender, ButtonBase.ClickEvent, AddressOf OnClickOneShot)
            StickyComponentManager.Detach(sender, ButtonBase.ClickEvent, AddressOf OnClickCancel)
        End If
    End Sub

     

    Grouping Sticky Components

    Since the idea in using Sticky Components is that their behaviour is very narrow and specialized, so that they are suitable for many different contexts, there is a need to be able to group Sticky Components and attach a whole group at once to the same base element. The Sticky Component Framework contains a generic collection to help with that: StickyComponentCollection(Of T as IStickyComponent). This collection attaches and detaches its items at the right times, provides change notification, and if you implement the INamedStickyComponent interface on the collection’s items, you even can refer to the components inside the collection using string indexers in XAML. Here is an example of the use of this collection:

    <Page.Resources>
        <ex:StickyTestComponentSet x:Key="test2">
            <ex:StickyTestComponent Name="Page Immediate"/>
            <ex:StickyTestComponent Name="Page OnInitialized" AttachMode="OnInitialized"/>
            <ex:StickyTestComponent Name="Page OnLoaded" AttachMode="OnLoaded"/>
        </ex:StickyTestComponentSet>

     

    StickyTestComponentSet is defined by inheriting a concrete type instance of the generic collection:

    Public Class StickyTestComponentSet
        Inherits StickyComponentCollection(Of StickyTestComponent)
        Implements IStickyComponent, IList

     

    Notice that for some reason the Visual Studio XAML designer (Cider) will only let you add direct content to the class if you specify “Implements IList” again, even though this interface is already implemented by the base class.

    The StickyComponent Example

    On the Downloads page you will find the source code for the framework and an example project called StickyComponentExample. This project mainly focuses on demonstrating the different interaction techniques between StickyComponents, their usage patterns, and their life cycle. In order to trace the life cycle, a lot of debug output is written to Debug.Print, so you should run the project in the Visual Studio Debugger and follow the output in the Immediate window.

    Coming Soon…

    There is one special case of a Sticky Component: the Sticky ViewModel. It deserves special attention, and even though the example is already in the example solution, I’d like to cover it in a separate post.

    The Stateless Sticky ViewModel Pattern

    December 6, 2009 1 comment

    What do you do when you want some functionality in your application that is too small to justify creating a full ViewModel, or that you want to reuse in different places and applications? You create a Sticky ViewModel. A Sticky ViewModel is a ViewModel that doesn’t replace the DataContext, but attaches itself to it and provides some functionality that closes a gap between what the model can do and what WPF needs.

    While I want to introduce Sticky ViewModels in general in a later post, today I had the idea for a special case which is easy to implement and demonstrate: the Stateless Sticky ViewModel.

    What is a Stateless Sticky ViewModel?

    A Stateless Sticky ViewModel is a ViewModel that provides all its functionality in shared (static in C#) code, and stores all its state in attached properties. This pattern is suitable for cases where you have a simple dependency between a small group of values, all of which could be data bound.

    For example, you might have a data model which exposes the name of a person as one property. In the UI, you’d like to edit first name and last name separately.

    Implementing the Pattern

    The first step in implementing the pattern would be to create a class that provides the code and attached properties. Since the class needs to define attached properties, it has to be based on DependencyObject. Then it would have to provide code in order to determine first name, last name and full name depending on what other information is already known.

    Public Class NameViewModel
        Inherits DependencyObject

        Public Shared Function DetermineLastName(ByVal fullname As String) As String
            Dim result As String = fullname
            If result Is Nothing Then
                result = String.Empty
            Else
                result = result.Trim
                Dim pos As Integer = result.LastIndexOf(" "c)
                If pos >= 0 Then
                    result = result.Substring(pos).Trim
                Else
                    result = String.Empty
                End If
            End If
            Return result

        End Function

        Public Shared Function DetermineFirstName(ByVal fullname As String) As String
            Dim result As String = fullname
            If result Is Nothing Then
                result = String.Empty
            Else
                result = result.Trim
                Dim pos As Integer = result.LastIndexOf(" "c)
                If pos >= 0 Then
                    result = fullname.Substring(0, pos).Trim
                End If
            End If
            Return result
        End Function

        Public Shared Function DetermineFullName(ByVal firstname As String, ByVal lastname As String) As String
            If firstname Is Nothing Then
                firstname = String.Empty
            Else
                firstname = firstname.Trim
            End If
            If lastname Is Nothing Then
                lastname = String.Empty
            Else
                lastname = lastname.Trim
            End If
            Dim result As String = String.Empty
            If String.IsNullOrEmpty(firstname) Or String.IsNullOrEmpty(lastname) Then
                result = firstname & lastname
            Else
                result = firstname & " " & lastname
            End If
            Return result
        End Function

     

    Notice that all these functions are declared “Shared”. This means that we actually never have to create an instance of our ViewModel.

    The next bit would be to declare the attached properties which contain the data and are bound to model and UI. Let’s take the FirstName property as an example:

    Public Shared ReadOnly FirstNameProperty As DependencyProperty = _
        DependencyProperty.RegisterAttached("FirstName", GetType(String), GetType(NameViewModel), _
        New FrameworkPropertyMetadata(String.Empty, _
        FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, _
        AddressOf OnFirstNameChanged))
    Public Shared Function GetFirstName(ByVal d As DependencyObject) As String
        Return d.GetValue(FirstNameProperty)
    End Function
    Public Shared Sub SetFirstName(ByVal d As DependencyObject, ByVal value As String)
        d.SetValue(FirstNameProperty, value)
    End Sub
    Private Shared Sub OnFirstNameChanged(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
        If CStr(e.NewValue) <> CStr(e.OldValue) And GetChangeInitiator(d) Is Nothing Then
            SetChangeInitiator(d, FirstNameProperty)
            SetFullName(d, DetermineFullName(e.NewValue, GetLastName(d)))
            SetChangeInitiator(d, Nothing)
        End If
    End Sub

     

    The first three declarations are the standard declaration of an attached property: shared get and set methods, and the registration of the property with the property system. It contains a flag that causes the property to update any property to which it is bound by default, because this is what is probably supposed to happen if someone binds this property to their data model. But the most important point in this declaration is that it registers the OnFirstNameChanged method to be called every time the value of the property changes.

    In the OnFirstNamedChanged method, we need to make the FullName property reflect the new value of the FirstName property. So, we need to call DetermineFullName and set the FullName property to the new value. In order to do that, we need the last name; since NameViewModel itself is stateless, we take this information from another attached property on the same object.

    If we change the FullName property, of course its change handler will try to update the FirstName property. In order to avoid endless circular calls, we only set the FullName property if the value of the FirstName has really changed.

    Tracking Dependencies Between the ViewModel’s Properties

    But what is the meaning of the bit about the ChangeInitiator? Well, what would be the difference if we set “John A.” to the FirstName or to the FullName? In the first case, we’d expect the LastName to remain unchanged, in the second case we’d expect it to be set to “A.”. Since changing the FirstName changes the FullName and changing the FullName in turn changes the LastName, we need a way to determine that the LastName shouldn’t be changed in this special case.

    In general, if we have multiple interdependent properties which all could be changed by the user, we need to make sure that the changes are propagated in the right direction. One way which helps in simple cases like this is storing a reference to the property which originated the change. Since we cannot store state in the ViewModel, we need another attached property:

    Private Shared ReadOnly ChangeInitiatorProperty As DependencyProperty = DependencyProperty.RegisterAttached("ChangeInitiator", GetType(DependencyProperty), GetType(NameViewModel))
    Private Shared Function GetChangeInitiator(ByVal d As DependencyObject) As DependencyProperty
        Return d.GetValue(ChangeInitiatorProperty)
    End Function
    Private Shared Sub SetChangeInitiator(ByVal d As DependencyObject, ByVal value As DependencyProperty)
        d.SetValue(ChangeInitiatorProperty, value)
    End Sub

    This property is declared private, since it is intended for internal use, only. Using the ChangeInitiator property, we can make sure that property changes trigger other properties to change only if it is necessary.

    Using the NameViewModel

    We use the NameViewModel by binding the model’s Name property to the FullName attached property, and the user controls to the other properties.

    <Window x:Class="Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
        xmlns:ex="clr-namespace:SharedStickyViewModelExample"
        Title="Shared Sticky ViewModel Example" Height="300" Width="300" x:Name="Window">
        <Grid x:Name="SVMHost" DataContext="{Binding ElementName=Window}"
              ex:NameViewModel.FullName="{Binding Path=MyName}">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="auto"/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="auto"/>
                <RowDefinition Height="auto"/>
                <RowDefinition Height="auto"/>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <Label Grid.Row="0" Grid.Column="0">First Name:</Label>
            <TextBox Grid.Row="0" Grid.Column="1"
              Text="{Binding ElementName=SVMHost,
              Path=(ex:NameViewModel.FirstName)}"/>
            <Label Grid.Row="1" Grid.Column="0">Last Name:</Label>
            <TextBox Grid.Row="1" Grid.Column="1"
              Text="{Binding ElementName=SVMHost,
              Path=(ex:NameViewModel.LastName)}"/>
            <Label Grid.Row="2" Grid.Column="0">Full Name:</Label>
            <TextBox Grid.Row="2" Grid.Column="1"
              Text="{Binding ElementName=SVMHost,
              Path=(ex:NameViewModel.FullName)}"/>
            <Label Grid.Row="3" Grid.Column="0">Model Value:</Label>
            <Label Grid.Row="3" Grid.Column="1" Content="{Binding Path=MyName}"/>
        </Grid>
    </Window>

     

    Notice that since the ViewModel needs an object to which it can attach its properties, we name the Grid that hosts the other controls “SVMHost”, and refer to when binding to the Stateless Sticky ViewModel’s properties.

    Conclusion

    The approach introduced here has the advantage that it is very lightweight and has no dependencies whatsoever except those imposed by WPF itself. However, because the Stateless Sticky ViewModel is kind of scattered on the XAML elements that make up the view, it is prone to become confusing when the properties become many and their relationships become complicated. If you need a more structured approach, you could try a full Sticky Component or a Mini-ViewModel.

    Coming Soon…

    Shortly, I want to introduce Sticky Components and the WPFGlue Sticky Component Framework. However, before I do that, I want to get the Navigation Command off my desk, which I promised in one of the first posts…

    Switching the Keyboard to Different Languages

    November 21, 2009 1 comment

    Handling different languages with different keyboard layouts within the same document has only recently become a common feature in text processing applications. However, since I frequently have to work with data in different languages, I wouldn’t like to miss this ability.

    In WPF, the class responsible for managing different keyboard languages is called InputLanguageManager. It exposes an attached property, InputLanguage, that accepts a culture identifier and switches the keyboard to the defined layout for this language, if one is installed. Unfortunately, this only works when the control receives focus. So, if you are typing something in a TextBox and change the InputLanguage while you are typing, e.g. through a keyboard shortcut, this change doesn’t become active unless the keyboard focus leaves the TextBox and returns again.

    Also, in principle you can define different languages for paragraphs in a RichTextBox by setting the InputLanguageManager.InputLanguage on the Paragraph elements in the RichTextBoxes FlowDocument, but the keyboard doesn’t automatically change to the appropriate layout when the selection enters a section in a different language. This feature is extremely useful, so I decided to create a Sticky Property which allows to change the keyboard language effective immediately, and a Sticky Behaviour that sets the current input language according to what is set in this attached property on the FrameworkContentElements inside a RichTextBox’s FlowDocument.

    Changing the Keyboard Language at Runtime

    The way the KeyboardLanguage property is implemented is a typical example for the Sticky Property design pattern. A Sticky Property is an attached property that has an OnPropertyChanged handler which does some useful work, so that the property has an effect aside from storing data with the object it is set on. In the case of the KeyboardLanguage property, this work would be looking up the available keyboard languages, checking whether one of them fits the value, and activating this keyboard layout.

    Public Shared ReadOnly KeyboardLanguageProperty As DependencyProperty = DependencyProperty.RegisterAttached("KeyboardLanguage", GetType(String), GetType(Localization), New FrameworkPropertyMetadata(Nothing, System.Windows.FrameworkPropertyMetadataOptions.Inherits, AddressOf OnKeyboardLanguageChanged))
    Public Shared Function GetKeyboardLanguage(ByVal d As DependencyObject) As String
        Return d.GetValue(KeyboardLanguageProperty)
    End Function
    Public Shared Sub SetKeyboardLanguage(ByVal d As DependencyObject, ByVal value As String)
        d.SetValue(KeyboardLanguageProperty, value)
    End Sub
    Public Shared Sub OnKeyboardLanguageChanged(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
        If TypeOf d Is FrameworkElement Then
            Dim l As System.Globalization.CultureInfo = FindKeyboardLanguage(e.NewValue)
            If String.IsNullOrEmpty(e.NewValue) Or l Is System.Globalization.CultureInfo.InvariantCulture Then
                d.ClearValue(InputLanguageManager.InputLanguageProperty)
                d.ClearValue(InputLanguageManager.RestoreInputLanguageProperty)
            Else
                d.SetValue(InputLanguageManager.InputLanguageProperty, l)
                d.SetValue(InputLanguageManager.RestoreInputLanguageProperty, True)
                InputLanguageManager.Current.CurrentInputLanguage = l
            End If
        End If
    End Sub

    Public Shared Function FindKeyboardLanguage(ByVal tag As String) As System.Globalization.CultureInfo
        Dim result As System.Globalization.CultureInfo = System.Globalization.CultureInfo.InvariantCulture
        If Not String.IsNullOrEmpty(tag) Then
            For Each c As System.Globalization.CultureInfo In InputLanguageManager.Current.AvailableInputLanguages
                If c.IetfLanguageTag.ToUpper.StartsWith(tag.ToUpper) Then
                    result = c
                End If
                If c.IetfLanguageTag.ToUpper = tag.ToUpper Then
                    Exit For
                End If
            Next
        End If
        Return result
    End Function

     

    This gives the added flexibility of supporting language-only IETF tags, so that you don’t have to know exactly which flavour of the language the target system supports.

    Keeping Track of Different Languages in a FlowDocument

    This is done through a sticky (or attached) behaviour. A Sticky Behaviour is an attached property that registers event handlers on the control it is attached to. In this case, the behaviour will be specialized for RichTextBoxes, because their ability to edit FlowDocuments is the most convenient way to edit structured documents in WPF.

    The Sticky Behaviour is activated by setting the TracksKeyboardLanguage property to true. Whenever the selection changes, this will cause the RichTextBox to check whether there are KeyboardLanguage attributes on the parent element of the current selection, and to activate the appropriate keyboard layout:

    Public Shared ReadOnly TracksKeyboardLanguageProperty As DependencyProperty = DependencyProperty.RegisterAttached("TracksKeyboardLanguage", GetType(Boolean), GetType(Localization), New PropertyMetadata(AddressOf OnTracksKeyboardLanguageChanged))
    Public Shared Function GetTracksKeyboardLanguage(ByVal d As DependencyObject) As Boolean
        Return d.GetValue(TracksKeyboardLanguageProperty)
    End Function
    Public Shared Sub SetTracksKeyboardLanguage(ByVal d As DependencyObject, ByVal value As Boolean)
        d.SetValue(TracksKeyboardLanguageProperty, value)
    End Sub
    Private Shared Sub OnTracksKeyboardLanguageChanged(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
        If TypeOf d Is RichTextBox Then
            Dim b As RichTextBox = d
            If CBool(e.OldValue) Then
                RemoveHandler b.SelectionChanged, AddressOf OnSelectionChanged
            End If
            If CBool(e.NewValue) Then
                AddHandler b.SelectionChanged, AddressOf OnSelectionChanged
            End If
        End If
    End Sub

    Private Shared Sub OnSelectionChanged(ByVal sender As Object, ByVal e As RoutedEventArgs)
        Dim b As RichTextBox = sender
        Dim f As FrameworkContentElement = TryCast(b.Selection.Start.Parent, FrameworkContentElement)
        If f IsNot Nothing Then
            Dim tag As String = GetKeyboardLanguage(f)
            If Not String.IsNullOrEmpty(tag) Then
                If Not InputLanguageManager.Current.CurrentInputLanguage.IetfLanguageTag.ToUpper.StartsWith(tag.ToUpper) Then
                    InputLanguageManager.Current.CurrentInputLanguage = FindKeyboardLanguage(tag)
                End If
            End If
        End If
        e.Handled = False
    End Sub

     

    It is always wise to make these event handlers static, so that they don’t create any references which could keep the control from being freed. Setting e.Handled to false makes sure that the RichTextBox still can accept other handlers for the SelectionChanged event.

    Downloading the Example

    The WPFGluePublished solution on the Downloads page contains a project called KeyboardLanguageExample which demonstrates the use of the KeyboardLanguage and TracksKeyboardLanguage properties. This example assumes that you have German, Arabic and English installed as Input languages on your computer. If you don’t have any additional keyboards installed, you can do so using the Regional and Language Options control panel in Windows.

    Implementing the Sticky Command Design Pattern

    November 12, 2009 2 comments

    The Sticky Command design pattern is one of the patterns in WPFGlue which allow to add custom functionality to out-of-the-box WPF controls. Adding a Sticky Command to a FrameworkElement gives it a certain new behaviour, and makes this behaviour available to the element and all its child elements through a routed command, while the implementation of the element remains separate and independent of the implementation of the behaviour.

    Let’s take an example. A very common need in data oriented applications is a submit command which sends the values of a group of controls to the underlying data store. This command should be disabled when the data is invalid, and it should be possible to connect it to a KeyGesture which allows to call the command by pressing a given key when entering data.

    <GroupBox x:Name="CustomerGroupBox" Header="Customer"
              v:Submit.Command="{StaticResource SubmitCommand}"
              v:Submit.KeyGesture="Enter"> <!—- Content left out for clarity -->
    </GroupBox>

    The Sticky Command is stuck to the GroupBox by setting the Submit.Command Sticky Property. Optionally, one can add a KeyGesture which invokes the command, in this case pressing the Enter key. The SubmitCommand is just a standard RoutedCommand:

    <Window.Resources>
        <RoutedCommand x:Key="SubmitCommand"/>
    </Window.Resources>

    By itself it doesn’t provide any functionality; it’s just kind of an identifier for the behaviour we want to add to the GroupBox.

    Creating a Sticky Property

    A Sticky Property is an attached property that, in addition to storing a value on the target element, does some work in its PropertyChanged handler. In our case, this work consists of creating a CommandBinding and setting it on the target element, or removing the created CommandBinding, respectively.

    Public Class Submit
        Inherits DependencyObject
    
        Public Shared ReadOnly CommandProperty As DependencyProperty = _
                DependencyProperty.RegisterAttached("Command", _
                GetType(RoutedCommand), GetType(Submit), _
                New PropertyMetadata(AddressOf OnCommandChanged))
        Public Shared Function GetCommand(ByVal d As DependencyObject) _
                As RoutedCommand
            Return d.GetValue(CommandProperty)
        End Function
        Public Shared Sub SetCommand(ByVal d As DependencyObject, _
                ByVal value As RoutedCommand)
            d.SetValue(CommandProperty, value)
        End Sub
        Private Shared Sub OnCommandChanged(ByVal d As DependencyObject, _
            ByVal e As DependencyPropertyChangedEventArgs)
            Dim f As FrameworkElement = TryCast(d, FrameworkElement)
            If f IsNot Nothing Then
                If e.OldValue IsNot Nothing Then
                    Detach(f, e.OldValue)
                End If
                If e.NewValue IsNot Nothing Then
                    Attach(f, e.NewValue)
                End If
            End If
        End Sub
    '...
    End Class

    The implementation of OnCommandChanged is quite simple: if the property already has a value, the command should be detached from the target, and if a new value is provided, this value should be attached to it. One might ask why it is necessary to provide a Detach procedure as well. Why not just leave the CommandBinding in place? If the command can be removed by changing setting the value of Submit.Command to Nothing, then the command can be attached and detached through triggers, which opens up a whole new line of uses…

    Attaching and Detaching the CommandBinding

    Private Shared Sub Attach(ByVal d As FrameworkElement, _
                              ByVal command As RoutedCommand)
        d.CommandBindings.Add(New SubmitCommandBinding(command))
        Dim gesture As KeyGesture = GetKeyGesture(d)
        AttachKeyGesture(d, command, gesture)
        If d.BindingGroup Is Nothing Then
            d.BindingGroup = New BindingGroup
        End If
    End Sub
    Private Shared Sub Detach(ByVal d As FrameworkElement, _
                              ByVal command As RoutedCommand)
        For Each b As SubmitCommandBinding In _
                d.CommandBindings.OfType(Of SubmitCommandBinding)()
            d.CommandBindings.Remove(b)
        Next
        DetachKeyGesture(d)
    End Sub

    The Attach procedure creates a new CommandBinding that connects the provided RoutedCommand to its implementation, and adds it to the targets CommandBindings collection.

    The Detach procedure removes the CommandBinding from the collection. In order to be able to find the correct CommandBinding, Attach uses a class derived from CommandBinding, in order to use its type as marker. This way, one doesn’t have to store a reference to the created CommandBinding in order to be able to remove it later. The dummy class is a private nested class inside the Submit class:

    Private Class SubmitCommandBinding
        Inherits CommandBinding
        Public Sub New(ByVal command As RoutedCommand)
            MyBase.New(command, AddressOf OnExecutedSubmit, _
                       AddressOf OnCanExecuteSubmit)
        End Sub
    End Class

    The Command’s Implementation

    The procedures OnExecutedSubmit and OnCanExecuteSubmit handle the RoutedCommand.CanExecute and RoutedCommand.Executed events that are sent out by the CommandBinding. It is useful to separate the code specific to event handling from the code that does the actual work:

    Private Shared Sub OnCanExecuteSubmit(ByVal sender As Object, _
            ByVal e As CanExecuteRoutedEventArgs)
    
        Dim result As Boolean = False
        Dim target As FrameworkElement = TryCast(sender, FrameworkElement)
        If target IsNot Nothing Then
            ' Separate event specific code from domain specific code...
            result = CanExecuteSubmit(target,e.Parameter)
        End If
        e.CanExecute = result
        e.Handled = True
    End Sub
    
    Public Shared Function CanExecuteSubmit(ByVal target As FrameworkElement, _
            ByVal parameter As Object) As Boolean
        Dim result As Boolean = False
        If target IsNot Nothing Then
            result = (target.BindingGroup IsNot Nothing AndAlso Not _
                      System.Windows.Controls.Validation.GetHasError(target))
        End If
        Return result
    End Function
    
    Private Shared Sub OnExecutedSubmit(ByVal sender As Object, _
                                        ByVal e As ExecutedRoutedEventArgs)
        Dim target As FrameworkElement = TryCast(sender, FrameworkElement)
        If target IsNot Nothing Then
            If CanExecuteSubmit(target, e.Parameter) Then
                ExecuteSubmit(target, e.Parameter)
            End If
            e.Handled = True
        End If
    End Sub
    
    Public Shared Sub ExecuteSubmit(ByVal target As FrameworkElement, _
            ByVal parameter As Object)
        target.BindingGroup.UpdateSources()
    End Sub

    Providing a KeyGesture

    In order to be able to specify a KeyGesture for the command on the target, we need to create a second Sticky Property, which is able to add the KeyGesture to the target’s InputBindings collection. The method is similar to the one used with the CommandBinding itself. However, there is one point of note: We cannot be sure of the order in which the attached properties are set on the target. So, we have to make sure that CommandBinding and InputBinding are set up correctly no matter which is specified first. Since the InputBinding depends on the CommandBinding, one could say that Submit.Command is the main Sticky Property, while Submit.KeyGesture is a supporting Sticky property. The rule would then be that the Attach and Detach procedures for the main Sticky property would have to call the Attach procedures for all supporting properties in turn, while the Attach procedures of the supporting properties only attach something if the main Sticky Property has already been set.

    The implementation of the KeyGesture functionality looks like this:

    Public Shared ReadOnly KeyGestureProperty As DependencyProperty = _
            DependencyProperty.RegisterAttached("KeyGesture", _
                        GetType(KeyGesture), GetType(Submit), _
                        New PropertyMetadata(AddressOf OnKeyGestureChanged))
    Public Shared Function GetKeyGesture(ByVal d As DependencyObject) _
            As KeyGesture
        Return d.GetValue(KeyGestureProperty)
    End Function
    Public Shared Sub SetKeyGesture(ByVal d As DependencyObject, _
                                    ByVal value As KeyGesture)
        d.SetValue(KeyGestureProperty, value)
    End Sub
    Private Shared Sub OnKeyGestureChanged(ByVal d As DependencyObject, _
            ByVal e As DependencyPropertyChangedEventArgs)
        Dim f As FrameworkElement = TryCast(d, FrameworkElement)
        If f IsNot Nothing Then
            If e.OldValue IsNot Nothing Then
                DetachKeyGesture(f)
            End If
            If e.NewValue IsNot Nothing Then
                AttachKeyGesture(f, GetCommand(f), e.NewValue)
            End If
        End If
    End Sub
    Private Shared Sub AttachKeyGesture(ByVal d As FrameworkElement, _
                                        ByVal command As RoutedCommand, _
                                        ByVal gesture As KeyGesture)
        If command IsNot Nothing And gesture IsNot Nothing Then
            d.InputBindings.Add(New SubmitKeyBinding(command, gesture))
        End If
    End Sub
    Private Shared Sub DetachKeyGesture(ByVal d As FrameworkElement)
        For Each i As SubmitKeyBinding In _
                d.InputBindings.OfType(Of SubmitKeyBinding)()
            d.InputBindings.Remove(i)
        Next
    End Sub
    
    Private Class SubmitKeyBinding
        Inherits InputBinding
        Public Sub New(ByVal command As RoutedCommand, _
                ByVal gesture As KeyGesture)
            MyBase.New(command, gesture)
        End Sub
    End Class

    Reusability

    Once we have this submit command, we can reuse it as it is, in any project, with any kind of control or data. But what about reusability of the pattern implementation itself?

    The whole Submit class consists of static members, only. This has the advantage of not creating dependent object references with the command bindings, which could interfere with the garbage collection of the page on which the command is used. Unfortunately, shared members cannot be overridden, which means that it is not straight forward to create a common base class for Sticky Commands and derive new implementations from that class. However, the domain specific code and the pattern specific code are quite easy to separate into different procedures, so that it might be an option to use Item Templates or Code Snippets in order to reuse the pattern specific code.

    Conclusion

    The Sticky Command pattern offers a powerful and flexible way of modifying the behaviour of standard controls without changing their implementation. Because it is used through declarative syntax, it can leverage the full power of WPF style, trigger and template mechanisms. In addition to that, a new implementation of the pattern can be created from an existing one with minimal changes.

    Downloads

    Download a complete example project for the Submit StickyCommand here.

    Download an Item Template for Sticky Commands here.