-1

I am writing an app using C++/winrt, on Windows 11, and using the new WinUI 3.0. The app has a TabView control, and each tab represents a document. The TabView control works well, but when you try to delete the tab that is selected... the program crashes. All the other non-selected tabs can be deleted easily. I have tried everything to unselect the selected tab, before deleting it, but nothing works. Has anyone else encountered this issue?

I tried unselecting the TabViewItem that represents the tab, but I can't unselect it.

void MainWindow::TabView_TabCloseRequested(::winrt::Microsoft::UI::Xaml::Controls::TabView const& sender, ::winrt::Microsoft::UI::Xaml::Controls::TabViewTabCloseRequestedEventArgs const& args)
{

    uint32_t indexOf;
    if (sender.TabItems().IndexOf(args.Tab(), indexOf))
    {
        sender.TabItems().RemoveAt(indexOf);
    }
}

Here's the Xaml page...

<!-- Copyright (c) Microsoft Corporation and Contributors. -->
<!-- Licensed under the MIT License. -->

<Window
    x:Class="Vectraset.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Vectraset"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:canvas="using:Microsoft.Graphics.Canvas.UI.Xaml"
    mc:Ignorable="d">

    <RelativePanel>

        <StackPanel x:Name="menu" Orientation="Horizontal" RelativePanel.AlignLeftWithPanel="True" RelativePanel.AlignTopWithPanel="True">
            <MenuBar>
                <MenuBarItem Title="File">
                    <MenuFlyoutItem Text="New"/>
                    <MenuFlyoutItem Text="Open..."/>
                    <MenuFlyoutItem Text="Save"/>
                    <MenuFlyoutItem Text="Exit"/>
                </MenuBarItem>

                <MenuBarItem Title="Edit">
                    <MenuFlyoutItem Text="Undo"/>
                    <MenuFlyoutItem Text="Cut"/>
                    <MenuFlyoutItem Text="Copy"/>
                    <MenuFlyoutItem Text="Paste"/>
                </MenuBarItem>

                <MenuBarItem Title="Help">
                    <MenuFlyoutItem Text="About"/>
                </MenuBarItem>
            </MenuBar>
        </StackPanel>


        <StackPanel x:Name="stack2" Orientation="Vertical"  RelativePanel.AlignLeftWithPanel="True" RelativePanel.Below="menu">
            <TabView x:Name="myTab" SelectionChanged="TabView_SelectionChanged" AddTabButtonClick="TabView_AddButtonClick" TabCloseRequested="TabView_TabCloseRequested" Loaded="TabView_Loaded"/>

            <Canvas x:Name="myStack" Width="2500" Height="1250" HorizontalAlignment="Left" VerticalAlignment="Top">

                <canvas:CanvasControl x:Name="D2D_CanvasControl" Canvas.Left="0" Canvas.Top="0"  Width="2500" Height="1250" HorizontalAlignment="Right" VerticalAlignment="Bottom" Draw="CanvasControl_Draw" ClearColor="CornflowerBlue">
                </canvas:CanvasControl>

                <local:PanelPart x:Name="myPanelPart" Canvas.Left="100" Canvas.Top="100" PointerPressed="PanelPart_PointerPressed" PointerReleased="PanelPart_PointerReleased" PointerMoved="PanelPart_PointerMoved" Width="75" Height="200" Background="Blue" Label="PanelPart"/>

            </Canvas>
        
        </StackPanel>

        <AppBar x:Name="bottomAppBar" Padding="0,0,0,0" MinWidth="100" RelativePanel.AlignLeftWithPanel="True" RelativePanel.AlignRightWithPanel="True" RelativePanel.AlignBottomWithPanel="True" AppBar.IsSticky="True">
            <StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
                <AppBarButton Icon="Add" Label="Add Part" Click="AddPartButton_Click"/>
                <AppBarButton AutomationProperties.Name="Sample Button"
                      AutomationProperties.AutomationId="SampleAppBarButton"
                      Click="AppBarButton_Click"/>
            </StackPanel>
        </AppBar>
    </RelativePanel>

</Window>

Here is the code I've been using to add the TabViewItem...

    // CPP
void MainWindow::TabView_AddButtonClick(::winrt::Microsoft::UI::Xaml::Controls::TabView const& sender, ::winrt::Windows::Foundation::IInspectable const& e)
{
    myTab().TabItems().Append(CreateNewTab(L"Default Title"));
}

Microsoft::UI::Xaml::Controls::TabViewItem MainWindow::CreateNewTab(hstring title)
{
    TabViewItem newItem;
    newItem.Header(box_value(title));
    return newItem;
}
Andrew
  • 174
  • 1
  • 6
  • Can you post code how you are deleting the selected tab and the non-selected tabs? – Andrew KeepCoding Feb 03 '23 at 02:07
  • The problem seems to be inside your ``TabViewItem``, not the ``TabView`` itself. You should try the same thing but with no ``TabViewItem`` contents. – Andrew KeepCoding Feb 03 '23 at 22:10
  • Hi Andrew, yes, I've tried that. In fact, I've made the TabView control completely empty on app startup. I can then add TabViewItems by clicking the control's ADD BUTTON. It initially populates the new tabs in an unselected state. It is only when there is user mouse/pointer activity that any of the tabs get a new default selected state. The control decides this. I think I might have to handle the TabCloseRequested event inside the TabViewItem, in addition to within TabView. I'm not sure. It is as if an attempt is made to use the TabViewItem object after it is deleted. – Andrew Feb 06 '23 at 10:55
  • Tried the code without `canvas:CanvasControl` and `local:PanelPart`. Since we do not know how you added the Tabview Item, I just write some very simple code to test. It works correctly without crash. Would you like to share the code about how to add a `TabViewItem`? – Roy Li - MSFT Feb 09 '23 at 08:05
  • Hi Roy, I've added the code for adding TabViewItem. (see above) Also, I have deleted the CanvasControl and PanelPart, and I get the same problem. – Andrew Feb 09 '23 at 14:33
  • 1
    I created a new project to test the code you posted. But it works correctly. The app will not crash when trying to delete the selected `TabViewItem`. Also, it works well even after I delete all the `TabViewItem`. Could you please reproduce this issue in a blank project and then share the project with us? – Roy Li - MSFT Feb 10 '23 at 06:58
  • I did the same thing and you are correct. I then went over my code again and realized that I was referencing a nullptr result in the TabView_SelectionChanged event handler without checking it before hand. It was my error. I am sorry to have wasted your time. Thank you very much for your insight and guidance. – Andrew Feb 10 '23 at 13:46
  • @Andrew Glad to hear that you've soled the issue! – Roy Li - MSFT Feb 13 '23 at 03:05

1 Answers1

0

Here is a simple TabCloseRequested for your reference.

<TabView x:Name="myTabView"   TabCloseRequested="TabView_TabCloseRequested" ...>

void MainWindow::TabView_TabCloseRequested(winrt::Microsoft::UI::Xaml::Controls::TabView const& sender, winrt::Microsoft::UI::Xaml::Controls::TabViewTabCloseRequestedEventArgs const& args)
{
     uint32_t indexOf;
     if (sender.TabItems().IndexOf(args.Item(), indexOf))
     {
          sender.TabItems().RemoveAt(indexOf); 
     }
}
Junjie Zhu - MSFT
  • 2,086
  • 1
  • 2
  • 6
  • Hi, thanks for replying! I copy-and-pasted your code into my app and I get exactly the same problem. My original code was very much the same as your code. – Andrew Feb 03 '23 at 12:19
  • An answer must, at a minimum, identify the issue and explain how the proposed solution solves it. This doesn't even attempt to identify the issue. – IInspectable Feb 03 '23 at 13:22