Click here to Skip to main content
15,435,432 members
Articles / Desktop Programming / XAML
Posted 27 Jan 2012


19 bookmarked

Attached Command for Windows 8 Metro Style in C#

Rate me:
Please Sign up or sign in to vote.
5.00/5 (4 votes)
27 Jan 2012Ms-PL2 min read
Attached Command for Windows 8 Metro Style in C#


Windows 8 Developer Preview and Blend 5 Developer Preview edtion does not support the EventToCommand behaviour yet (MVVM Light Toolkit is available for Metro: but Blend behaviors not). And many developers want to implement the event to command in its MVVM pattern. So we need the Attached Command for Metro (Similar with the AttachedCommand in WPF).

Design the code

Well, let's start.

Usually, in MVVM pattern, we like to declare the value properties and the Commands in the ViewModel, which use the DataBinding on the View. And that can do the "Data Drives UI" job. But let us check the Metro Style App. Although it use the XAML, and WinRT compoenets, it still can use MVVM pattern as its architecture. Metro still supports DataBinding and yes we still can let "Data" drive the "Metro UI".

However, it is easy to implement the properties and commands in ViewModel, but not easy to assign one UI Control event to one Command. In WPF, we could use the Blend SDK behaviour to assign one event to a command, or I usually recommend to design one AttachedCommand, like this did: . But just checking the MVVM Light Toolkit for Metro, it cannot provide the EventToCommand behaviour amd the Blend 5 Developer Preview version does not provide the behaviour. So we just need to design one AttachedCommand for Metro.

In out AttachedCommand class, we should declare two attached properties, Command and RoutedEvent property.

/// <summary>
/// Command attached property
/// </summary>
public static readonly DependencyProperty CommandProperty =
    "Object",  // should be "Object" instead of "ICommand" interface, resolve the null reference exception
    typeof(AttachedCommand).FullName, new PropertyMetadata(DependencyProperty.UnsetValue));

public static ICommand GetCommand(DependencyObject d)
    return (ICommand)d.GetValue(CommandProperty);
public static void SetCommand(DependencyObject d, ICommand value)
    d.SetValue(CommandProperty, value);

/// <summary>
/// RoutedEvent property
/// </summary>
public static readonly DependencyProperty RoutedEventProperty =
    new PropertyMetadata(String.Empty, new PropertyChangedCallback(OnRoutedEventChanged)));

public static String GetRoutedEvent(DependencyObject d)
    return (String)d.GetValue(RoutedEventProperty);
public static void SetRoutedEvent(DependencyObject d, String value)
    d.SetValue(RoutedEventProperty, value);

We should register the Attached Property in Metro via the string of the type (similar with the Silverlight solution), and for Interface, we should use "Object" instead of. And not sure if it will be resolved in next Windows 8 version, but for interface, it will throw the NullReferenceException.

Below is the property changed callback for RoutedEvent property:

    private static void OnRoutedEventChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        String routedEvent = (String)e.NewValue;
        if (!String.IsNullOrEmpty(routedEvent))
            EventHooker eventHooker = new EventHooker();
            eventHooker.AttachedCommandObject = d;
            EventInfo eventInfo = GetEventInfo(d.GetType(), routedEvent);
            if (eventInfo != null)
                eventInfo.AddEventHandler(d, eventHooker.GetEventHandler(eventInfo));

We need the EventInfo by reflecting the Metro DependecyObject. But in Metro, the reflection just can list the members which are declared in the current type directly. It cannot list all members inherits from the base type. So We should use one method to search the Event Member from its base types:

/// <summary>
/// Search the EventInfo from the type and its base types
/// </summary>
/// <param name="type"></param>
/// <param name="eventName"></param>
/// <returns></returns> <returns />
private static EventInfo GetEventInfo(Type type, string eventName)
    EventInfo eventInfo = null;
    eventInfo = type.GetTypeInfo().GetDeclaredEvent(eventName);
    if (eventInfo == null)
        Type baseType = type.GetTypeInfo().BaseType;
        if (baseType != null)
            return GetEventInfo(type.GetTypeInfo().BaseType, eventName);
            return eventInfo;
    return eventInfo;

When the specific event is fired on the control, we should return the event handler. So there is an EventHooker that can return one "OnEventRaised" method, and execute the command in it:

internal sealed class EventHooker
    public DependencyObject AttachedCommandObject { get; set; }

    public Delegate GetEventHandler(EventInfo eventInfo)
        Delegate del = null;
        if (eventInfo == null)
            throw new ArgumentNullException("eventInfo");

        if (eventInfo.EventHandlerType == null)
            throw new ArgumentNullException("eventInfo.EventHandlerType");

        if (del == null)
            del = this.GetType().GetTypeInfo().GetDeclaredMethod("OnEventRaised").CreateDelegate(eventInfo.EventHandlerType, this);

        return del;

    private void OnEventRaised(object sender, object e)  // the second parameter in Windows.UI.Xaml.EventHandler is Object
        ICommand command = (ICommand)(sender as DependencyObject).GetValue(AttachedCommand.CommandProperty);

        if (command != null)

How to Use

We should add one DelegateCommand or RelayCommand (ICommand) for Metro, which can help us to return the ICommand in the ViewModel. And we could bind this ICommand property on the AttachedCommand.Command property. Below is one DelegateCommand for Metro. And MVVM Light Toolkit provides the RelayCommand available for Metro also.

public class DelegateCommand : ICommand
    private readonly Predicate<object> _canExecute;
    private readonly Action<object> _execute;

    public event Windows.UI.Xaml.EventHandler CanExecuteChanged;

    public DelegateCommand(Action<object> execute)
        : this(execute, null)

    public DelegateCommand(Action<object> execute,
                   Predicate<object> canExecute)
        _execute = execute;
        _canExecute = canExecute;

    public bool CanExecute(object parameter)
        if (_canExecute == null)
            return true;

        return _canExecute(parameter);

    public void Execute(object parameter)

    public void RaiseCanExecuteChanged()
        if (CanExecuteChanged != null)
            CanExecuteChanged(this, null);

Please note, WinRT EventHandler is different with the System.EventHandler. And Windows.UI.Xaml.EventHandler has two object parameters, the second one is not EventArgs.

Then in the View, we just could set the AttachedCommand in any controls in Metro:

<Button Content="Test Button"
                local:AttachedCommand.RoutedEvent="PointerEntered" local:AttachedCommand.Command="{Binding TestCommand}"/>



This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)

Written By
China China
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

QuestionGetting error Pin
Farhan Ghumra5-Mar-13 22:35
professionalFarhan Ghumra5-Mar-13 22:35 
QuestionICommand Pin
tulp24-Jun-12 23:49
Membertulp24-Jun-12 23:49 
QuestionDoes this work with any event? Pin
Member 9745413-Apr-12 6:53
MemberMember 9745413-Apr-12 6:53 
QuestionSome concern about Attached Command Pin
hunglh0101121-Feb-12 22:37
Memberhunglh0101121-Feb-12 22:37 

I'm a newbie in this field, so please tell me how to hook more than one event ?
For example, If I want to add a command to got focus event and text changed event, How to do this?

Special thanks Smile | :)

modified 22-Feb-12 5:23am.

AnswerRe: Some concern about Attached Command Pin
maiken7716-May-12 3:21
Membermaiken7716-May-12 3:21 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.