Archive

Posts Tagged ‘Sticky Property’

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…

Advertisements

CSS Class Equivalent in WPF

November 30, 2009 1 comment

In the small hours of this morning, I had an idea about how to create a stylesheet for FlowDocuments that behaves similar to CSS. What’s the difference between CSS classes and WPF styles? Well, CSS classes are not necessarily specific to a certain element type, and they can be combined on the styled element, while WPF Styles are specific to the element type, and each element can have exactly one Style (in addition to the default style, which fills in wherever the element style doesn’t provide a value). Also, if you want to combine Styles in WPF, you have to do it in the Style definition using BasedOn, which I find quite inflexible, and which drives one crazy if one has to support a lot of independent permutations.

So, what was the idea? The first one was that CSS classes should not be implemented as Styles, but as Triggers inside styles, which are selected whenever a certain attached property has the fitting value. So, in order to support different classes of TextBlocks, one would do this:

<Style TargetType="TextBlock" >
    <Style.Triggers>
        <Trigger Property="t:MultiStyle.Selector" Value="italic">
            <Setter Property="FontStyle" Value="Italic"/>
        </Trigger>
        <Trigger Property="t:MultiStyle.Selector" Value="red">
            <Setter Property="Foreground" Value="Red"/>
        </Trigger>
        <Trigger Property="t:MultiStyle.Selector" Value="bold">
            <Setter Property="FontWeight" Value="Bold"/>
            <Setter Property="FontStyle" Value="Normal"/>
        </Trigger>
    </Style.Triggers>
</Style>

 

The second idea was to use a special type for the attached property. The StyleSelector class tokenizes its String value, and returns “equal” on a comparison with another string or StyleSelector if the other object contains one of the tokens that are defined:

Public Class MultiStyle
    Inherits DependencyObject

    Public Shared ReadOnly SelectorProperty As DependencyProperty = DependencyProperty.RegisterAttached("Selector", GetType(StyleSelector), GetType(MultiStyle))
    Public Shared Function GetSelector(ByVal d As DependencyObject) As StyleSelector
        Return d.GetValue(SelectorProperty)
    End Function
    Public Shared Sub SetSelector(ByVal d As DependencyObject, ByVal value As StyleSelector)
        d.SetValue(SelectorProperty, value)
    End Sub

End Class

<System.ComponentModel.TypeConverter(GetType(StyleSelectorConverter))> _
Public Class StyleSelector
    Implements IEquatable(Of StyleSelector), IEquatable(Of String)

    Public Sub New(ByVal value As String)
        _Value = value
    End Sub

    Private _Value As String
    Public Property Value() As String
        Get
            Return _Value
        End Get
        Set(ByVal value As String)
            _Value = value
        End Set
    End Property

    Public Overrides Function Equals(ByVal obj As Object) As Boolean
        If TypeOf obj Is StyleSelector Then
            Return Equals1(obj)
        End If
        If TypeOf obj Is String Then
            Return Equals2(obj)
        End If
        Return MyBase.Equals(obj)
    End Function

    Public Function Equals1(ByVal other As StyleSelector) As Boolean Implements System.IEquatable(Of StyleSelector).Equals
        If other IsNot Nothing And _Value IsNot Nothing Then
            Dim myValue() As String = _Value.Split(" "c)
            Dim otherValue() As String = other.Value.Split(" "c)
            Dim result As Boolean = False
            Dim i As Integer = 0
            Do While i < otherValue.Length And Not result
                result = myValue.Contains(otherValue(i))
                i += 1
            Loop
            Return result
        Else
            Return MyBase.Equals(other)
        End If
    End Function

    Public Function Equals2(ByVal other As String) As Boolean Implements System.IEquatable(Of String).Equals
        If other IsNot Nothing And _Value IsNot Nothing Then
            Dim myValue() As String = _Value.Split(" "c)
            Return myValue.Contains(other)
        Else
            Return MyBase.Equals(other)
        End If
    End Function
End Class

Public Class StyleSelectorConverter
    Inherits System.ComponentModel.TypeConverter

    Public Overrides Function CanConvertFrom(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal sourceType As System.Type) As Boolean
        Return (sourceType Is GetType(String))
    End Function

    Public Overrides Function CanConvertTo(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal destinationType As System.Type) As Boolean
        Return (destinationType Is GetType(String))
    End Function

    Public Overrides Function ConvertFrom(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal culture As System.Globalization.CultureInfo, ByVal value As Object) As Object
        Dim result As StyleSelector = Nothing
        If TypeOf value Is String Then
            result = New StyleSelector(value)
        End If
        Return result
    End Function

    Public Overrides Function ConvertTo(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal culture As System.Globalization.CultureInfo, ByVal value As Object, ByVal destinationType As System.Type) As Object
        Dim result As Object = Nothing
        If TypeOf value Is StyleSelector Then
            result = DirectCast(value, StyleSelector).Value
        End If
        Return result
    End Function
End Class

The only thing that remains to do is to implement the TypeConverter that allows to use StyleSelector as an attribute value in XAML, and to define the attached property.

Applications

Since I couldn’t go back to sleep, I tried it out immediately. You can download the VB solution here. (you will have to remove the .doc extension from the zip file; wordpress.com doesn’t allow zip files directly.)

However, when I was done, the idea didn’t seem so brilliant anymore as when I woke up. There are limitations of course. The trick works only with property setters. If you want to use triggers, they will be the same for all classes. What can you do with this what you can’t do with styles? The last thing that I came up with is that one could write a style sheet editor that creates styles with identical class definitions for different types of controls, so that you can use the same set of property values for different elements, as in CSS. However, you’d have to have this editor, otherwise it would be to much work to keep the class definitions equal to each other. And, of course, one can combine multiple classes on the same element, for what it’s worth…

PS: What happens if two classes provide different values for the same property and are both set on the same element? Because triggers are executed in the order they appear in the Style definition, the class that is defined last wins and overwrites the value of its sibling…

Categories: Uncategorized Tags: , , ,

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.

WPFGlue Patterns

November 5, 2009 4 comments

Let’s recapitulate the design requirements for WPFGlue components:

  • You shall not duplicate functionality that is already in the WPF framework.
  • You shall not mess with WPF’s correct function, like keeping objects from being freed and the like evil practices.
  • You shall not require code behind.
  • You shall not demand sub-classing controls.
  • You shall not demand interface implementations from your business objects (unless the interfaces are part of WPF itself), nor common base classes, nor any other construct that commits the developer to a strong coupling between your glue and his code.

The following design patterns have proved suitable for development under these constraints:

Sticky Properties (a.k.a. Attached Properties)

Attached properties can be used to extend the state of any element in WPF. They can be used in XAML, and neither the framework-supplied controls nor the business object model need to know them. So, they are suitable for WPFGlue.

Built-in examples for attached properties are the Canvas.Left and Canvas.Top properties, which the WPF Canvas uses to store the positions of its child elements.

Sticky Behaviours (a.k.a. Attached Behaviours)

Attached behaviours are a special kind of attached properties that register event handlers on the elements they are attached to. The event handlers provide additional functionality to the elements which is triggered through the elements standard events, while the implementation of the event handlers is contained in the class that defines the attached property.

A built-in example for a sticky behaviour is the SpellCheck.IsEnabled property, which adds the functionality of spell checking to controls based on TextBoxBase.

Josh Smith writes about attached behaviours in this article; Attached behaviours are introduced and defined by Nikhil Kothari here.

Sticky CommandBindings

Work like sticky behaviours, with the difference that they don’t handle events, but standard routed commands. Attaching a sticky CommandBinding to a WPF FrameworkElement means that this element will be able to handle the command, without having to change the original implementation of the element. A sticky CommandBinding should add / remove the CommandBindings when the value of an attached property changes.

Pete O’Hanlon gives an almost perfect example of this pattern here. Almost perfect because he uses a class CommandBinding instead of the CommandBindings collection, but this might be justified on his case since he expects the command to be used by many elements per page.

Sticky ViewModels (a.k.a. Mini-ViewModels)

Sticky ViewModels are ViewModels that don’t wrap a business object, but attach themselves to it and expose a specialized, reusable bit of functionality through their own properties and commands. Typically, a sticky ViewModel wouldn’t be the DataContext of a FrameworkElement, but it would be attached to the element as a sticky property and use the FrameworkElement’s DataContext to find the model it is supposed to work on. Controls inside the scope of the FrameworkElement would then bind to properties of the sticky ViewModel in order to benefit from it.

Quite often jobs like this are done through converters (Converters are classes that implement the IValueConverter interface). However, I view this as converter abuse. A converter is not intended for anything but type conversions, translating data between different data types and string presentations. If the intention of the solution is rather to achieve some more complex interaction between the View and the Model, I’d recommend a sticky ViewModel instead. Usually these cases are discovered by feeling the need to pass more information into the conversion routines than is readily available…

While Mini-ViewModel seems to imply that the functionality of such a class would normally be quite limited, I could imagine whole page ViewModels using this technique.

Colin Eberhardt describes the Mini-ViewModel pattern here and gives a nice example.

ViewModelKits

A ViewModelKit would be a class or set of related classes that can be instantiated and configured as XAML resources, and then be used as ViewModels through referencing the resource.

A built-in example for a ViewModelKit would be the CollectionViewSource class, which can be used to configure views of business object collections.

Sticky Markup (a.k.a. Custom Markup Extensions)

Custom markup extensions are classes derived from System.Windows.Markup.MarkupExtension, which can be used in XAML attributes using the markup extension syntax, like {Binding value}. Writing custom markup extensions is not documented very well in the WPF documentation, and I use them sparingly. They need to be initialized in place, i.e. where they are used in XAML. This limits their “stickiness” to situations where the information they need to do their job is either very simple or can be discovered from the built-in application framework. For example, I found them useful for accessing localized resources, application settings, or the current UI language.