Apply Command InputBindings on styles

This one is a little bit more tricky then the CommandProxy I’ve written before, because the CommandProxy dose not work here.

First you can simply not apply InputBindings from Styles because the property has not setter. You are only able to add bindings to the collection, but there is no way to do this in styles.
Second you can not place there resource for the CommandProxy inside of the style.

To make that work you need an property which you can set in the style. And this is my solution. Create an attached dependency property which set the InputBinding for you.

As example i use the LeftDoubleClick MouseGesture.

public static class MouseCommands
{
    private static void LeftDoubleClickChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
    {
        var control = (Control)sender;

        if(args.NewValue != null && args.NewValue is ICommand)
        {
            var newBinding = new MouseBinding(args.NewValue as ICommand, new MouseGesture(MouseAction.LeftDoubleClick));
            control.InputBindings.Add(newBinding);
        }else
        {
            var oldBinding = control.InputBindings.Cast<InputBinding>().First(b => b.Command.Equals(args.OldValue));
            control.InputBindings.Remove(oldBinding);
        }
    }

    public static readonly DependencyProperty LeftDoubleClickProperty =
        DependencyProperty.RegisterAttached("LeftDoubleClick",
            typeof(ICommand),
            typeof(MouseCommands),
            new UIPropertyMetadata(LeftDoubleClickChanged));

    public static void SetLeftDoubleClick(DependencyObject obj, ICommand value)
    {
        obj.SetValue(LeftDoubleClickProperty, value);
    }

    public static ICommand GetLeftDoubleClick(DependencyObject obj)
    {
        return (ICommand)obj.GetValue(LeftDoubleClickProperty);
    }
}

And then you can apply this over a style. In my example here for an ListBoxItem in its ListBoxContainerStyle.

<Style x:Key="ListBoxItemStyle" TargetType="{x:Type ListBoxItem}">
    <Setter Property="Shared:MouseCommands.LeftDoubleClick" Value="{Binding AddCommand}" />
</Style>

And that it is. Yes you have to create an attached dependency property for each Mouse- or KeyBinding you want to use, but the most time you dose not need all of them.

CommandProxy: Howto databind a ICommand to an InputBinding

When you start using the ViewModel pattern in WPF, some day you stumble upon that it is not possible to databind an command to an MouseBinding or KeyBinding.

So why this is not possible?

The WPF DataBinding’s are heavily based on DependencyPropertys which are only work on objects which inherit from DependencyObject. But the Command property on Mouse- and KeyBinding isnt an DependencyProperty. So DataBinding will not work on them.

The next problem is that the InputBinding class is only derived from DependencyObject and so it has no inheritance context which allow to get access to DataContext and ElementName.

May it is a performance consideration, may it is mistake, finally i dont know why they make this decision.

So how to make the DataBinding work anyway?

My solution is called CommandProxy and it uses a simpified version of Josh Smith Virtual Branch technic.

So here the CommandProxy looks like:

    public class CommandProxy : Freezable, ICommand
    {
        protected override Freezable CreateInstanceCore()
        {
            return new CommandProxy();
        }

        public static readonly DependencyProperty CommandProperty =
            DependencyProperty.Register( "Command",
                typeof(ICommand),
                typeof(CommandProxy),
                new UIPropertyMetadata() );

        public ICommand Command
        {
            get { return (ICommand)GetValue( CommandProperty ); }
            set { SetValue( CommandProperty, value ); }
        }

        public void Execute( object parameter )
        {
            Command.Execute( parameter );
        }

        public bool CanExecute( object parameter )
        {
            return Command != null && Command.CanExecute( parameter );
        }

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

And here is how to use it:

    <Grid Background="LightGreen">

        <Grid.Resources>

            <a:CommandProxy x:Key="TestCommand"
                    Command="{Binding TestCommand}" />

        </Grid.Resources>

        <Grid.InputBindings>

            <MouseBinding Command="{StaticResource TestCommand}" Gesture="LeftClick" />

        </Grid.InputBindings>

        <TextBlock Text="click here" VerticalAlignment="Center" TextAlignment="Center" />

    </Grid>

As the name suggests, all this class dose is to expose a ICommand interface and redirect its methods to the databound command. The inheritance context problem is resolve by inherting from Freezable. You can read more about why Freezable helps here, in Dr. WPFs Blog here.

Download the CommandProxySample Visual Studio 2008 Solution.

Alternativ content propertys in Expression Blend

Look at the Header
Look at the <>Header

Did you ever noticed that there a way in expression blend to directly edit a second content property of a element which is not the default content and without using a resource? Yep, look at the “<> Header”, there could be placed the second content.

WPF per default provides some of this controls. In example MenuItem,HeaderedContentControl,BulletDecorator … So ive started to find out how to create such a property by myself. After some time of searching ive saw only the way to use Reflector to figure out why Expression Blend exposes this properts.

And the answer is not nice. The hardcoded this behavior into Blend for every control which exposes such a property.

I couldnt belive it, there must be a common way to do it, so ive decided to write a feature request to Microsoft Connect for exposing a common way to expose such a property from my custom code (my first report to Microsoft Connect).

And here is it: https://connect.microsoft.com/Expression/feedback/ViewFeedback.aspx?FeedbackID=411558

My expectation was that this would be a long time open, but it was not. It was closed at the same day ive reported it and with the information i want to hear 🙂

Thanks for the feedback- in the next version of Expression Blend we will be adding a new attribute which will allow additional content properties on controls’ Look for ‘AlternateContentPropertyAttribute’ in the next version of the extensibility APIs.

I am looking forward to the next Blend release.

Update: Here is a link how this feature look like in the next Blend version.

In memory FlowDocument to XPS with working DataBinding

It costs me some time and nerves to figure this out, but finally ive got this working.


var flowDocument = (FlowDocument)Application.LoadComponent( new Uri( @"MyFlowDocument.xaml", UriKind.Relative ) );

doc.DataContext = this;

var package = Package.Open( new MemoryStream(), FileMode.Create, FileAccess.ReadWrite );
var packUri = new Uri( "pack://temp.xps" );
PackageStore.RemovePackage( packUri );
PackageStore.AddPackage( packUri, package );

var xpsDocument = new XpsDocument( package, CompressionOption.SuperFast, packUri.ToString() );

var paginator = ((IDocumentPaginatorSource)flowDocument).DocumentPaginator;

new XpsSerializationManager( new XpsPackagingPolicy( xpsDocument ), false )
.SaveAsXaml( paginator );

Viewer.Document = xpsDocument.GetFixedDocumentSequence();</code><strong></strong>

The key part here to get the binding to work is this call:


Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.SystemIdle,
new DispatcherOperationCallback(arg => null ), null);

Ive got this tip from the blog of Mark Nijhof. I dont know why this is need, but i assume that it needs one Dispatcher run to expand the DataBinding.