在WPF中,是否可以重新排列选项卡控件中的选项卡项目?

14

在运行时重新排列选项卡控件中的选项卡项目是否可能?例如,我有3个关于汽车的选项卡和4个关于房屋的选项卡。我想使用拖放功能重新排列它们。这是可能的还是不可想象的?

我这里有一个 XAML 的选项卡控件。

<TabControl x:Name="tc" Visibility="Collapsed" GotFocus="Focus" AllowDrop="True" >
            </TabControl>

标签项将在运行时添加。感谢您的帮助!

2个回答

28

我在MSDN论坛中找到了解决方案。

这是链接:

拖放选项卡项

以下为解决方案:

C# 解决方案

WPF 代码:

<TabControl>
    <TabControl.Resources>
        <Style TargetType="TabItem">
            <Setter Property="AllowDrop" Value="True"/>
                <EventSetter Event="PreviewMouseMove" Handler="TabItem_PreviewMouseMove"/>
                <EventSetter Event="Drop" Handler="TabItem_Drop"/>
        </Style>
    </TabControl.Resources>

    <TabItem Header="Tabitem 1"/>
    <TabItem Header="Tabitem 2"/>
    <TabItem Header="Tabitem 3"/>
    <TabItem Header="Tabitem 4"/>
    <TabItem Header="Tabitem 5"/>
</TabControl>

C#代码后台:

private void TabItem_PreviewMouseMove(object sender, MouseEventArgs e)
{
    if (!(e.Source is TabItem tabItem))
    {
        return;
    }

    if (Mouse.PrimaryDevice.LeftButton == MouseButtonState.Pressed)
    {
        DragDrop.DoDragDrop(tabItem, tabItem, DragDropEffects.All);
    }
}

private void TabItem_Drop(object sender, DragEventArgs e)
{
    if (e.Source is TabItem tabItemTarget &&
        e.Data.GetData(typeof(TabItem)) is TabItem tabItemSource &&
        !tabItemTarget.Equals(tabItemSource) &&
        tabItemTarget.Parent is TabControl tabControl)
    {
        int targetIndex = tabControl.Items.IndexOf(tabItemTarget);

        tabControl.Items.Remove(tabItemSource);
        tabControl.Items.Insert(targetIndex, tabItemSource);
        tabItemSource.IsSelected = true;
    }
}

这意味着当我点击我的文本框时,它会给我一个错误。我无法通过鼠标单击来聚焦到我的文本框上。当我点击任何界面元素时,它都会出现错误。 - Firdavs Kurbonov
1
当我使用MVVM模式中的绑定方式添加项目时,当我执行var tabControl = tabItemTarget.Parent as TabControl时,我会得到“tabControl为空”的错误提示。请问在我的情况下应该如何解决? - Nomesh Gajare
我遇到了与Nomesh相同的错误...当我尝试删除元素时,我在if (!tabItemTarget.Equals(tabItemSource))处收到了错误信息"对象引用未设置为对象的实例。" - Jason Axelrod
在这种情况下,您需要在VisualTree上找到父级。 tabItemTarget.FindVisualParent<TabControl>() - Ketobomb
3
好的解决方案!另外建议:如果你想重新排序而不是切换标签页,请取消注释最后两行。另外,如果你实现了一个关闭按钮,请检查!(e.OriginalSource is Button) - bytecode77
显示剩余5条评论

0

当我尝试实现这个解决方案时,放置事件会触发两次(移动选项卡,然后立即将它们移回)。我不得不添加一个整数来跟踪上一个选项卡目标索引。我的解决方案是使用VB.NET编写的。

'additional variable
Dim lastTabTargetIndex As Integer = Nothing

Private Sub tc1_PreviewMouseMove(sender As Object, e As MouseEventArgs) Handles tc1.PreviewMouseMove

    Dim Tabi = TryCast(e.Source, TabItem)

    If Tabi Is Nothing Then
        Exit Sub
    Else
        If Mouse.PrimaryDevice.LeftButton = MouseButtonState.Pressed Then
            DragDrop.DoDragDrop(Tabi, Tabi, DragDropEffects.All)
        End If
    End If
End Sub

Private Sub tc1_Drop(sender As Object, e As DragEventArgs) Handles tc1.Drop

    Dim tabItemTarget = TryCast(e.Source, TabItem)
    Dim tabItemSource = TryCast(e.Data.GetData(GetType(TabItem)), TabItem)

    If Not tabItemTarget.Equals(tabItemSource) Then
        Dim tabControl = TryCast(tabItemTarget.Parent, TabControl)
        Dim sourceIndex As Integer = tabControl.Items.IndexOf(tabItemSource)
        Dim targetIndex As Integer = tabControl.Items.IndexOf(tabItemTarget)

        'had to use this extra statement
        If sourceIndex <> lastTabTargetIndex Then
            'assign lastTabTargetIndex here
            lastTabTargetIndex = targetIndex
            tabControl.Items.Remove(tabItemSource)
            tabControl.Items.Insert(targetIndex, tabItemSource)
            tabControl.Items.Remove(tabItemTarget)
            tabControl.Items.Insert(sourceIndex, tabItemTarget)
        End If

    End If
End Sub

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接