Tool tab vs. title bar

Docking/MDI for WPF Forum

Posted 10 years ago by David Sherwood
Version: 10.1.0522
Avatar
I notice that if you drag a tool window tab, only that window moves. But if you drag the container title bar, the whole tabbed group moves. I would like to support this distinction in my context menu. How can I tell which has been selected? In the ContextMenu event, the OrignalSource is always the container and sender is always the DockSite.

Comments (4)

Posted 10 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi David,

The ToolWindowContainer includes a SelectedToolWindow, which should be the window you want to float.


Actipro Software Support

Posted 10 years ago by David Sherwood
Avatar
I want to do all of the windows in the container if the title bar's context menu is selected but only the one window if the tab's context menu is selected. Thats the way your drag feature works.
Posted 10 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi David,

I see, we are actually duplicating Visual Studio's behavior. But you could certainly alter the behavior to meet your needs. You can use the following code to target the commands to the ToolWindowContainer when the titlebar is showing the context menu:
/// <summary>
/// Occurs when the <c>DockSite.WindowContextMenu</c> event occurs.
/// </summary>
/// <param name="sender">The sender of the event.</param>
/// <param name="e">A <see cref="DockingWindowContextMenuEventArgs"/> that contains the event data.</param>
private void OnDockSiteWindowContextMenu(object sender, DockingWindowContextMenuEventArgs e) {
    if (e.Window != null && !e.Window.IsMouseOver) {
        ToolWindowContainer container = e.OriginalSource as ToolWindowContainer;
        if (container != null) {
            foreach (object obj in e.ContextMenu.Items) {
                MenuItem item = obj as MenuItem;
                if (item != null && (item.Command == DockingCommands.MakeFloating || item.Command == DockingCommands.MakeDocked))
                    item.CommandTarget = container;
            }
        }
    }
}
Then you would need to register class handlers for those commands when they target ToolWindowContainer, as this isn't handled by default, like so:
public static class MyToolWindowCommandHandler {

    private static bool isRegistered = false;

    /////////////////////////////////////////////////////////////////////////////////////////////////////
    // PUBLIC PROCEDURES
    /////////////////////////////////////////////////////////////////////////////////////////////////////

    /// <summary>
    /// Registers custom command handlers for the <c>ToolWindowContainer</c> class.
    /// </summary>
    public static void Register() {
        if (isRegistered)
            return;

        // Register class command bindings
        isRegistered = true;
        CommandManager.RegisterClassCommandBinding(typeof(ToolWindowContainer), new CommandBinding(DockingCommands.MakeFloating, new ExecutedRoutedEventHandler(OnMakeFloatingCommandExecuted), new CanExecuteRoutedEventHandler(OnMakeFloatingCommandCanExecute)));
        CommandManager.RegisterClassCommandBinding(typeof(ToolWindowContainer), new CommandBinding(DockingCommands.MakeDocked, new ExecutedRoutedEventHandler(OnMakeDockedCommandExecuted), new CanExecuteRoutedEventHandler(OnMakeDockedCommandCanExecute)));
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////////
    // COMMAND HANDLERS
    /////////////////////////////////////////////////////////////////////////////////////////////////////

    /// <summary>
    /// Occurs when the <see cref="RoutedCommand"/> needs to determine whether it can execute.
    /// </summary>
    /// <param name="sender">The sender of the event.</param>
    /// <param name="e">A <see cref="CanExecuteRoutedEventArgs"/> that contains the event data.</param>
    private static void OnMakeDockedCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) {
        ToolWindowContainer container = (ToolWindowContainer)sender;
        e.CanExecute = container.CanDock;
    }

    /// <summary>
    /// Occurs when the <see cref="RoutedCommand"/> is executed.
    /// </summary>
    /// <param name="sender">The sender of the event.</param>
    /// <param name="e">An <see cref="ExecutedRoutedEventArgs"/> that contains the event data.</param>
    private static void OnMakeDockedCommandExecuted(object sender, ExecutedRoutedEventArgs e) {
        ToolWindowContainer container = (ToolWindowContainer)sender;
        container.Dock();
    }

    /// <summary>
    /// Occurs when the <see cref="RoutedCommand"/> needs to determine whether it can execute.
    /// </summary>
    /// <param name="sender">The sender of the event.</param>
    /// <param name="e">A <see cref="CanExecuteRoutedEventArgs"/> that contains the event data.</param>
    private static void OnMakeFloatingCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) {
        ToolWindowContainer container = (ToolWindowContainer)sender;
        e.CanExecute = container.CanRaft;
    }

    /// <summary>
    /// Occurs when the <see cref="RoutedCommand"/> is executed.
    /// </summary>
    /// <param name="sender">The sender of the event.</param>
    /// <param name="e">An <see cref="ExecutedRoutedEventArgs"/> that contains the event data.</param>
    private static void OnMakeFloatingCommandExecuted(object sender, ExecutedRoutedEventArgs e) {
        ToolWindowContainer container = (ToolWindowContainer)sender;
        container.Float();
    }
}
I've added a TODO item to see about adding this command handling support by default.


Actipro Software Support

Posted 10 years ago by David Sherwood
Avatar
It was "e.Window.IsMouseOver" that I couldn't figure out. Thanks for the help.
The latest build of this product (v2019.1 build 0683) was released 1 month ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.