Search code examples
c#wpfdrag-and-droptabitem

Dragging over a dragablz:TabablzControl tab to bring it to front


I would like to implement a DragEnter-Event for each TabItem of my dragablz:TabablzControl. Tabs should be automatically selected when dragging a file over it.

I found two topics on stackoverflow that seem to be similar to my question:

Unfortunately these solutions doesn't work for TabablzControl from Dragablz.

<dragablz:TabablzControl Name="TC_FooBar" FixedHeaderCount="3">
      <TabItem Header="FIRST">
            <!-- <ContentOfFirstTabItem/> -->
      </TabItem>
      <TabItem Header="SECOND">
            <!-- <ContentOfSecondTabItem/> -->
      </TabItem>
      <TabItem Header="THIRD">
            <!-- <ContentOfThirdTabItem/> -->
      </TabItem>
</dragablz:TabablzControl>

What I have tried so far:

  • Implementing DragEnter und PreviewDragEnter events for each TabItem and for the TabablzControl itself.
  • Setting AllowDrop="True" for TabablzControl and each TabItem.

Everytime the e.Source is equal to the content of the currently selected tab. I'm not able to identify the correct TabItem. Any ideas?


Solution

  • This is pretty easy.

    You've already prepared the correct setup:

    <dragablz:TabablzControl DragEnter="TabControl_OnDragEnter" AllowDrop="True">
        <TabItem Header="FIRST"/>
        <TabItem Header="SECOND"/>
        <TabItem Header="THIRD"/>
    </dragablz:TabablzControl>
    

    AllowDrop is true and there's a DragEnter routed event handler. Note that this is a bubbling event, but you also could use the tunneling PreviewDragEnter version.

    The magic will happen in the event handler. We need the OriginalSource property. However, this will be some Visual that represents a TabItem, not the TabItem itself! You should read about WPF's styling and templating features to get more info about it. All we need is to get from that representing Visual to the actual TabItem. We can do it by walking up the visual tree until we find the item:

    private void TabControl_OnDragEnter(object sender, DragEventArgs e)
    {
        // Just a sanity check - we need a Visual here
        if (!(e.OriginalSource is Visual v))
        {
            return;
        }
    
        // DragablzItems will represent our TabItems, so we search for those
        var item = GetParentOfType<DragablzItem>(v);
    
        // DragablzItem.Content should contain our original TabItem
        if (item != null && item.Content is TabItem ti)
        {
            ti.IsSelected = true;
        }
    }
    

    And the helper GetParentOfType method could look like this:

    static T GetParentOfType<T>(Visual visual) where T : Visual
    {
        DependencyObject parent = visual;
        do
        {
            parent = VisualTreeHelper.GetParent(parent);
        } while (parent != null && !(parent is T));
    
        return parent as T;
    }