c# - 在 WPF 中拖放 TabItem?

标签 c# wpf

所以我发现这回答了问题: Is it possible to rearrange tab items in tab control in wpf?

使用该线程中的信息,我将其全部设置在我的应用程序中:

<TabControl x:Name="tabControl">
    <TabControl.Resources>
        <Style TargetType="TabItem">
            <Setter Property="AllowDrop" Value="True"/>
            <EventSetter Event="PreviewMouseMove" Handler="TabItem_Drag"/>
            <EventSetter Event="Drop" Handler="TabItem_Drop"/>
        </Style>
    </TabControl.Resources>
</TabControl>

代码:

private void TabItem_Drag(object sender, MouseEventArgs e)
{
    var tabItem = e.Source as TabItem;

    if (tabItem == null)
        return;

    if (Mouse.PrimaryDevice.LeftButton == MouseButtonState.Pressed)
        DragDrop.DoDragDrop(tabItem, tabItem, DragDropEffects.All);
}
private void TabItem_Drop(object sender, DragEventArgs e)
{
    var tabItemTarget = e.Source as TabItem;
    var tabItemSource = e.Data.GetData(typeof(TabItem)) as TabItem;

    if (!tabItemTarget.Equals(tabItemSource))
    {
        int sourceIndex = tabControl.Items.IndexOf(tabItemSource);
        int targetIndex = tabControl.Items.IndexOf(tabItemTarget);

        tabControl.Items.Remove(tabItemSource);
        tabControl.Items.Insert(targetIndex, tabItemSource);

        tabControl.Items.Remove(tabItemTarget);
        tabControl.Items.Insert(sourceIndex, tabItemTarget);

        tabControl.SelectedIndex = targetIndex;
    }
}

问题是,当我放下选项卡时,我收到以下错误

    if (!tabItemTarget.Equals(tabItemSource))

An exception of type 'System.NullReferenceException' occurred in Scoreboard Assistant.exe but was not handled in user code

Additional information: Object reference not set to an instance of an object.

当我单击“继续”时,出现以下错误

        DragDrop.DoDragDrop(tabItem, tabItem, DragDropEffects.All);

An unhandled exception of type 'System.NullReferenceException' occurred in PresentationCore.dll

Additional information: Object reference not set to an instance of an object.

然后程序就死掉了。我做错了什么?

* 编辑*

好的,我知道问题是什么了;我只需要帮助修复它。如果选项卡项目按如下方式创建,则它可以正常工作:

<TabItem Header="TabItem"/>

但是,我的选项卡创建如下:

<TabItem>
    <TabItem.Header>
        <StackPanel Orientation="Horizontal">
            <Image Source="images/text.png" />
            <TextBlock Text="Text"/>
        </StackPanel>
    </TabItem.Header>
</TabItem>

如您所见,我使用堆栈面板在选项卡标题中显示一个图标。问题似乎是,当我拖放面板时,它不是将 e.Source 读取为 tabitem,而是读取 tabitem 的 stackpanel 内的文本 block 。我该如何解决这个问题?

最佳答案

由于 TabItem header 的可视化树可能相当复杂,因此您无法保证放置目标将是 TabItem 实例(这就是代码中发生的情况) )。

但是你可以通过探索可视化树找到TabItem:

private TabItem GetTargetTabItem(object originalSource)
{
    var current = originalSource as DependencyObject;            

    while (current != null)
    {
        var tabItem = current as TabItem;
        if (tabItem != null)
        {
            return tabItem;
        }

        current = VisualTreeHelper.GetParent(current);
    }

    return null;
}

private void TabItem_Drop(object sender, DragEventArgs e)
{
    var tabItemTarget = GetTargetTabItem(e.OriginalSource);
    if (tabItemTarget != null)
    {
        var tabItemSource = (TabItem)e.Data.GetData(typeof(TabItem));
        if (tabItemTarget != tabItemSource)
        {
            // the rest of your code
        }
    }
}

关于c# - 在 WPF 中拖放 TabItem?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26174695/

相关文章:

c# - 获取 Dictionary 的第一个成员,然后获取其余的成员

wpf - Microsoft 的 WPF/Silverlight 图表在 .NET 4.0 中去了哪里?

c# - 如何计算 WPF 中客户区的偏移量?

c# - 从 XAML 中删除重复的 DataTrigger 代码

c# - 如何使用脚本更改 Unity UI 中的占位符文本?

C# - WPF - 添加图标后的项目大小(从资源加载图标或从项目 EXE 中提取)

c# - 有没有在解决方案的基础上#define CONSTANT?

c# - Datagrid 中的 NumericUpDown

wpf - 传递给命令 WPF 的多个参数

c# - 在 WPF LineSeries DataPoint 上添加事件