Jf Beaulac
Jf Beaulac

Reputation: 5246

CommandBinding in DataTemplate within a ResourceDictionary, handlers not assigned correctly

I have a ResourceDictionary, which contains a DataTemplate. Within this DataTemplate's Resources I am declaring a CommandBindingCollection. My ResourceDictionary has a codebehind file in which I declare the handlers for Executed/CanExecute.

The issue I have is that when I retreive my CommandBindingCollection from the ResourceDictionary, the Executed/CanExecute handlers are not assigned. Using the debugger I can see that the handlers are null. Why is that and how can I fix it?

ResourceDictionary XAML:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="Test"
                    x:Class="Test.MyResourceDictionary">

    <DataTemplate x:Key="Template"
                  x:Name="Template">
        <DataTemplate.Resources>
            <CommandBindingCollection x:Key="CommandBindings">
                <CommandBinding Command="local:TestCommands.Test"
                        Executed="testExecuted" 
                        CanExecute="testCanExecute" />
            </CommandBindingCollection>
        </DataTemplate.Resources>

        <!-- More stuff here -->

    </DataTemplate>
<ResourceDictionary/>

ResourceDictionary codebehind:

public partial class MyResourceDictionary: ResourceDictionary
{
    public MyResourceDictionary() 
    { 
        InitializeComponent(); 
    } 

    private void testExecuted(object sender, ExecutedRoutedEventArgs e)
    {

    }

    private void testCanExecute(object sender, CanExecuteRoutedEventArgs e)
    {

    }
}

Update

I am using this with AvalonDock, which uses DataTemplateSelector to apply the DataTemplate.

Here is how I load the Template:

public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
    if (item is TestViewModel)
    {
        ResourceDictionary res = Application.LoadComponent(new Uri("/MyResourceDictionary.xaml", UriKind.Relative)) as ResourceDictionary;
        DataTemplate template = res["Template"] as DataTemplate;
        if(template != null)
        {
            CommandBindingCollection commandBindings = 
                template.Resources["CommandBindings"] as CommandBindingCollection;

            if(commandBindings != null)
            {
                foreach(var binding in commandBindings)
                {
                     // add commandbinding to the container control
                     // here, using the debugger i can see that the handlers for the commandbinding
                     // are always null (private variables that I can only see using debugger)
                }
            }
            return template;
        }
    }
    return base.SelectTemplate(item, container);
}

If I move the CommandBindingCollection directly into the ResourceDictionary and access it this way:

CommandBindingCollection commandBindings = 
            res["CommandBindings"] as CommandBindingCollection;

Then the handlers are correctly set. I'm wondering why it can't set the event handler's delegates when I declare it within the DataTemplate's Resources.

Upvotes: 1

Views: 1806

Answers (1)

Jf Beaulac
Jf Beaulac

Reputation: 5246

My problem was related to a bug in the .NET framework, which seems fixed in 4.5.

There is a hotfix for the problem on 4.0: http://support.microsoft.com/kb/2464222

In my case, applying the hotfix solved the issue. My guess is that somewhere in the CommandBindingCollection XAML parser, the exception is handled silently.

Upvotes: 1

Related Questions