Search code examples
wpfcontextmenuattached-properties

How to bind ContextMenu that has Command to the attached property?


I have an external control named DockSite. When displayed ContextMenu from the DockSite control, the MenuOpening event handler is called.

I wanted to add my ContextMenu to the default ContextMenu when the MenuOpening event is called and I created the attached property as below to extend the behavior of the DockSite.

    public static ContextMenu GetAddDocumentMenu(DependencyObject obj)
    {
        return (ContextMenu)obj.GetValue(AddDocumentMenuProperty);
    }

    public static void SetAddDocumentMenu(DependencyObject obj, ContextMenu value)
    {
        obj.SetValue(AddDocumentMenuProperty, value);
    }

    // Using a DependencyProperty as the backing store for AddDocumentMenu.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty AddDocumentMenuProperty =
        DependencyProperty.RegisterAttached("AddDocumentMenu", typeof(ContextMenu), typeof(DockSiteHook), new PropertyMetadata(new ContextMenu(), OnDocumentMenuChanged));

    private static void OnDocumentMenuChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        var dockSite = (sender as DockSite);
        if (dockSite == null) return;

        ContextMenu on = (ContextMenu)e.NewValue;
        if (on is null) dockSite.MenuOpening -= DockSite_MenuOpening;
        else dockSite.MenuOpening += DockSite_MenuOpening;
    }

    private static void DockSite_MenuOpening(object sender, DockingMenuEventArgs e)
    {
        e.Menu.Items.Add(DockSiteHook.GetAddDocumentMenu(sender as DockSite));
    }

I used the code above in my MainWindow as below.

<docking:DockSite Grid.Row="1" x:Name="dockSite">

    <ap:DockSiteHook.AddDocumentMenu>
        <ContextMenu>
            <MenuItem Command="{Binding TestCommand}"/>
        </ContextMenu>
    </ap:DockSiteHook.AddDocumentMenu>

<docking:DockSite/>

But the Visual Studio throws an error as below image.

enter image description here

enter image description here

The error message is "It can't bind the default value for AddDocumentMenu to the specific thread".

I want to bind the ContextMenu to the specific attached property.

Could someone tell me why fired the error above? and how to solve this problem?

Thanks for reading.


Solution

  • Set the default value to null (or default(ContextMenu)):

    public static readonly DependencyProperty AddDocumentMenuProperty = 
        DependencyProperty.RegisterAttached("AddDocumentMenu", typeof(ContextMenu), 
            typeof(DockSiteHook), new PropertyMetadata(null, OnDocumentMenuChanged));