在WPF中拖放选项卡项

本文关键字:选项 拖放 WPF | 更新日期: 2023-09-27 18:25:22

所以我找到了答案:是否可以在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))

记分牌Assistant.exe中发生类型为"System.NullReferenceException"的异常,但未在用户代码中处理

附加信息:对象引用未设置为对象的实例。

当我点击继续时,我在上得到以下错误

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

PresentationCore.dll 中发生类型为"System.NullReferenceException"的未处理异常

附加信息:对象引用未设置为对象的实例。

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

*编辑*

好吧,我弄清楚问题出在哪里了;我只需要帮助修复它。如果选项卡项目按如下方式创建,它会非常好地工作:

<TabItem Header="TabItem"/>

然而,我的选项卡创建如下:

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

正如您所看到的,我正在使用stackpanel在选项卡标题中有一个图标。问题似乎是,当我拖放面板时,e.Source不是作为选项卡项读取的,而是读取选项卡项堆栈面板中的文本块。我该怎么解决这个问题?

在WPF中拖放选项卡项

由于TabItem标头的可视化树可能相当复杂,因此不能保证该丢弃目标将是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
        }
    }
}