From 637b3806cb55957a8c1e3e107a1b7a04e12a5ad7 Mon Sep 17 00:00:00 2001 From: Marcel Wagner <marcel.alex.wagner@outlook.com> Date: Fri, 5 Jun 2020 19:40:25 +0200 Subject: [PATCH] Resize tab view items only once the pointer has left the TabViewItem strip (#2569) * Add initial behavior * Hide scroll buttons when they are not needed anymore * Add test * Remove comment * Switch to tabstrip instead of listview for pointer exited event * Resize tabs none the less if last item got removed * Keep buttons visible but disabled, CR feedback * Update behavior again, now aligned with edge * Fix test failure * Move pointer to different UI element in test --- dev/TabView/InteractionTests/TabViewTests.cs | 105 +++++++++++ dev/TabView/TabView.cpp | 169 +++++++++++++----- dev/TabView/TabView.h | 9 +- dev/TabView/TestUI/TabViewPage.xaml | 7 +- dev/TabView/TestUI/TabViewPage.xaml.cs | 8 +- .../TestUI/TabViewTabClosingBehaviorPage.xaml | 44 +++++ .../TabViewTabClosingBehaviorPage.xaml.cs | 72 ++++++++ dev/TabView/TestUI/TabView_TestUI.projitems | 7 + 8 files changed, 374 insertions(+), 47 deletions(-) create mode 100644 dev/TabView/TestUI/TabViewTabClosingBehaviorPage.xaml create mode 100644 dev/TabView/TestUI/TabViewTabClosingBehaviorPage.xaml.cs diff --git a/dev/TabView/InteractionTests/TabViewTests.cs b/dev/TabView/InteractionTests/TabViewTests.cs index 8cb28a8792..2b4d6e2110 100644 --- a/dev/TabView/InteractionTests/TabViewTests.cs +++ b/dev/TabView/InteractionTests/TabViewTests.cs @@ -161,10 +161,14 @@ public void TabSizeAndScrollButtonsTest() // Close a tab to make room. The scroll buttons should disappear: Log.Comment("Closing a tab:"); Button closeButton = FindCloseButton(FindElement.ByName("LongHeaderTab")); + closeButton.MovePointer(0, 0); closeButton.InvokeAndWait(); VerifyElement.NotFound("LongHeaderTab", FindBy.Name); Log.Comment("Scroll buttons should disappear"); + // Leaving tabstrip with this so the tabs update their width + FindElement.ByName<Button>("IsClosableCheckBox").MovePointer(0,0); + Wait.ForIdle(); Verify.IsFalse(AreScrollButtonsVisible(), "Scroll buttons should disappear"); // Make sure the scroll buttons can show up in 'Equal' sizing mode. @@ -647,6 +651,107 @@ public void VerifyTabViewItemHeaderForegroundResource() } } + [TestMethod] + public void VerifySizingBehaviorOnTabCloseComingFromScroll() + { + int pixelTolerance = 10; + + using (var setup = new TestSetupHelper(new[] { "TabView Tests", "TabViewTabClosingBehaviorButton" })) + { + + Log.Comment("Verifying sizing behavior when closing a tab"); + CloseTabAndVerifyWidth("Tab 1", 500, "True;False;"); + + CloseTabAndVerifyWidth("Tab 2", 500, "True;False;"); + + CloseTabAndVerifyWidth("Tab 3", 500, "False;False;"); + + CloseTabAndVerifyWidth("Tab 5", 401, "False;False;"); + + CloseTabAndVerifyWidth("Tab 4", 401, "False;False;"); + + Log.Comment("Leaving the pointer exited area"); + var readTabViewWidthButton = new Button(FindElement.ByName("GetActualWidthButton")); + readTabViewWidthButton.Click(); + Wait.ForIdle(); + + readTabViewWidthButton.Click(); + Wait.ForIdle(); + + Log.Comment("Verify correct TabView width"); + Verify.IsTrue(Math.Abs(GetActualTabViewWidth() - 283) < pixelTolerance); + } + + void CloseTabAndVerifyWidth(string tabName, int expectedValue, string expectedScrollbuttonStates) + { + Log.Comment("Closing tab:" + tabName); + FindCloseButton(FindElement.ByName(tabName)).Click(); + Wait.ForIdle(); + Log.Comment("Verifying TabView width"); + Verify.IsTrue(Math.Abs(GetActualTabViewWidth() - expectedValue) < pixelTolerance); + Verify.AreEqual(expectedScrollbuttonStates, FindElement.ByName("ScrollButtonStatus").GetText()); + + } + + double GetActualTabViewWidth() + { + var tabviewWidth = new TextBlock(FindElement.ByName("TabViewWidth")); + + return Double.Parse(tabviewWidth.GetText()); + } + } + + [TestMethod] + public void VerifySizingBehaviorOnTabCloseComingFromNonScroll() + { + int pixelTolerance = 10; + + using (var setup = new TestSetupHelper(new[] { "TabView Tests", "TabViewTabClosingBehaviorButton" })) + { + + Log.Comment("Verifying sizing behavior when closing a tab"); + CloseTabAndVerifyWidth("Tab 1", 500, "True;False;"); + + CloseTabAndVerifyWidth("Tab 2", 500, "True;False;"); + + CloseTabAndVerifyWidth("Tab 3", 500, "False;False;"); + + var readTabViewWidthButton = new Button(FindElement.ByName("GetActualWidthButton")); + readTabViewWidthButton.Click(); + Wait.ForIdle(); + + CloseTabAndVerifyWidth("Tab 5", 500, "False;False;"); + + CloseTabAndVerifyWidth("Tab 4", 500, "False;False;"); + + Log.Comment("Leaving the pointer exited area"); + + readTabViewWidthButton.Click(); + Wait.ForIdle(); + + Log.Comment("Verify correct TabView width"); + Verify.IsTrue(Math.Abs(GetActualTabViewWidth() - 500) < pixelTolerance); + } + + void CloseTabAndVerifyWidth(string tabName, int expectedValue, string expectedScrollbuttonStates) + { + Log.Comment("Closing tab:" + tabName); + FindCloseButton(FindElement.ByName(tabName)).Click(); + Wait.ForIdle(); + Log.Comment("Verifying TabView width"); + Verify.IsTrue(Math.Abs(GetActualTabViewWidth() - expectedValue) < pixelTolerance); + Verify.AreEqual(expectedScrollbuttonStates, FindElement.ByName("ScrollButtonStatus").GetText()); + + } + + double GetActualTabViewWidth() + { + var tabviewWidth = new TextBlock(FindElement.ByName("TabViewWidth")); + + return Double.Parse(tabviewWidth.GetText()); + } + } + public void PressButtonAndVerifyText(String buttonName, String textBlockName, String expectedText) { Button button = FindElement.ByName<Button>(buttonName); diff --git a/dev/TabView/TabView.cpp b/dev/TabView/TabView.cpp index 3bc3565eb6..f37b6e9f8f 100644 --- a/dev/TabView/TabView.cpp +++ b/dev/TabView/TabView.cpp @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See LICENSE in the project root for license information. #include "pch.h" @@ -80,7 +80,15 @@ void TabView::OnApplyTemplate() m_addButtonColumn.set(GetTemplateChildT<winrt::ColumnDefinition>(L"AddButtonColumn", controlProtected)); m_rightContentColumn.set(GetTemplateChildT<winrt::ColumnDefinition>(L"RightContentColumn", controlProtected)); - m_tabContainerGrid.set(GetTemplateChildT<winrt::Grid>(L"TabContainerGrid", controlProtected)); + if (const auto& containerGrid = GetTemplateChildT<winrt::Grid>(L"TabContainerGrid", controlProtected)) + { + m_tabContainerGrid.set(containerGrid); + m_tabStripPointerExitedRevoker = containerGrid.PointerExited(winrt::auto_revoke, { this,&TabView::OnTabStripPointerExited }); + } + else + { + m_tabContainerGrid.set(nullptr); + } m_shadowReceiver.set(GetTemplateChildT<winrt::Grid>(L"ShadowReceiver", controlProtected)); @@ -341,6 +349,18 @@ void TabView::OnListViewLoaded(const winrt::IInspectable&, const winrt::RoutedEv } } +void TabView::OnTabStripPointerExited(const winrt::IInspectable& sender, const winrt::PointerRoutedEventArgs& args) +{ + if (updateTabWidthOnPointerLeave) + { + auto scopeGuard = gsl::finally([this]() + { + updateTabWidthOnPointerLeave = false; + }); + UpdateTabWidths(); + } +} + void TabView::OnScrollViewerLoaded(const winrt::IInspectable&, const winrt::RoutedEventArgs& args) { if (auto&& scrollViewer = m_scrollViewer.get()) @@ -423,8 +443,12 @@ void TabView::UpdateScrollViewerDecreaseAndIncreaseButtonsViewState() void TabView::OnItemsPresenterSizeChanged(const winrt::IInspectable& sender, const winrt::SizeChangedEventArgs& args) { - UpdateTabWidths(); - UpdateScrollViewerDecreaseAndIncreaseButtonsViewState(); + if (!updateTabWidthOnPointerLeave) + { + // Presenter size didn't change because of item being removed, so update manually + UpdateScrollViewerDecreaseAndIncreaseButtonsViewState(); + UpdateTabWidths(); + } } void TabView::OnItemsChanged(winrt::IInspectable const& item) @@ -434,42 +458,61 @@ void TabView::OnItemsChanged(winrt::IInspectable const& item) m_tabItemsChangedEventSource(*this, args); int numItems = static_cast<int>(TabItems().Size()); - if (args.CollectionChange() == winrt::CollectionChange::ItemRemoved && numItems > 0) + + if (args.CollectionChange() == winrt::CollectionChange::ItemRemoved) { - // SelectedIndex might also already be -1 - auto selectedIndex = SelectedIndex(); - if (selectedIndex == -1 || selectedIndex == static_cast<int32_t>(args.Index())) + updateTabWidthOnPointerLeave = true; + if (numItems > 0) { - // Find the closest tab to select instead. - int startIndex = static_cast<int>(args.Index()); - if (startIndex >= numItems) + // SelectedIndex might also already be -1 + auto selectedIndex = SelectedIndex(); + if (selectedIndex == -1 || selectedIndex == static_cast<int32_t>(args.Index())) { - startIndex = numItems - 1; - } - int index = startIndex; - - do - { - auto nextItem = ContainerFromIndex(index).as<winrt::ListViewItem>(); - - if (nextItem && nextItem.IsEnabled() && nextItem.Visibility() == winrt::Visibility::Visible) + // Find the closest tab to select instead. + int startIndex = static_cast<int>(args.Index()); + if (startIndex >= numItems) { - SelectedItem(TabItems().GetAt(index)); - break; + startIndex = numItems - 1; } + int index = startIndex; - // try the next item - index++; - if (index >= numItems) + do { - index = 0; - } - } while (index != startIndex); + auto nextItem = ContainerFromIndex(index).as<winrt::ListViewItem>(); + + if (nextItem && nextItem.IsEnabled() && nextItem.Visibility() == winrt::Visibility::Visible) + { + SelectedItem(TabItems().GetAt(index)); + break; + } + + // try the next item + index++; + if (index >= numItems) + { + index = 0; + } + } while (index != startIndex); + } + + } + // Last item removed, update sizes + // The index of the last element is "Size() - 1", but in TabItems, it is already removed. + if (TabWidthMode() == winrt::TabViewWidthMode::Equal) + { + updateTabWidthOnPointerLeave = true; + if (args.Index() == TabItems().Size()) + { + UpdateTabWidths(true,false); + } } } + else + { + UpdateTabWidths(); + } } - UpdateTabWidths(); } void TabView::OnListViewSelectionChanged(const winrt::IInspectable& sender, const winrt::SelectionChangedEventArgs& args) @@ -620,6 +663,7 @@ void TabView::RequestCloseTab(winrt::TabViewItem const& container) internalTabViewItem->RaiseRequestClose(*args); } } + UpdateTabWidths(false); } void TabView::OnScrollDecreaseClick(const winrt::IInspectable&, const winrt::RoutedEventArgs&) @@ -649,7 +693,7 @@ winrt::Size TabView::MeasureOverride(winrt::Size const& availableSize) return __super::MeasureOverride(availableSize); } -void TabView::UpdateTabWidths() +void TabView::UpdateTabWidths(bool shouldUpdateWidths,bool fillAllAvailableSpace) { double tabWidth = std::numeric_limits<double>::quiet_NaN(); @@ -685,14 +729,41 @@ void TabView::UpdateTabWidths() { if (TabWidthMode() == winrt::TabViewWidthMode::Equal) { + auto const minTabWidth = unbox_value<double>(SharedHelpers::FindInApplicationResources(c_tabViewItemMinWidthName, box_value(c_tabMinimumWidth))); auto const maxTabWidth = unbox_value<double>(SharedHelpers::FindInApplicationResources(c_tabViewItemMaxWidthName, box_value(c_tabMaximumWidth))); - // Calculate the proportional width of each tab given the width of the ScrollViewer. + // If we should fill all of the available space, use scrollviewer dimensions auto const padding = Padding(); - auto const tabWidthForScroller = (availableWidth - (padding.Left + padding.Right)) / (double)(TabItems().Size()); + if (fillAllAvailableSpace) + { + // Calculate the proportional width of each tab given the width of the ScrollViewer. + auto const tabWidthForScroller = (availableWidth - (padding.Left + padding.Right)) / (double)(TabItems().Size()); + tabWidth = std::clamp(tabWidthForScroller, minTabWidth, maxTabWidth); + } + else + { + double availableTabViewSpace = (tabColumn.ActualWidth() - (padding.Left + padding.Right)); + if (const auto increaseButton = m_scrollIncreaseButton.get()) + { + if (increaseButton.Visibility() == winrt::Visibility::Visible) + { + availableTabViewSpace -= increaseButton.ActualWidth(); + } + } + + if (const auto decreaseButton = m_scrollDecreaseButton.get()) + { + if (decreaseButton.Visibility() == winrt::Visibility::Visible) + { + availableTabViewSpace -= decreaseButton.ActualWidth(); + } + } + + // Use current size to update items to fill the currently occupied space + tabWidth = availableTabViewSpace / (double)(TabItems().Size()); + } - tabWidth = std::clamp(tabWidthForScroller, minTabWidth, maxTabWidth); // Size tab column to needed size tabColumn.MaxWidth(availableWidth); @@ -711,7 +782,15 @@ void TabView::UpdateTabWidths() tabColumn.Width(winrt::GridLengthHelper::FromValueAndType(1.0, winrt::GridUnitType::Auto)); if (auto listview = m_listView.get()) { - winrt::FxScrollViewer::SetHorizontalScrollBarVisibility(listview, winrt::Windows::UI::Xaml::Controls::ScrollBarVisibility::Hidden); + if (shouldUpdateWidths && fillAllAvailableSpace) + { + winrt::FxScrollViewer::SetHorizontalScrollBarVisibility(listview, winrt::Windows::UI::Xaml::Controls::ScrollBarVisibility::Hidden); + } + else + { + m_scrollDecreaseButton.get().IsEnabled(false); + m_scrollIncreaseButton.get().IsEnabled(false); + } } } } @@ -742,18 +821,22 @@ void TabView::UpdateTabWidths() } } - for (auto item : TabItems()) + + if (shouldUpdateWidths || TabWidthMode() != winrt::TabViewWidthMode::Equal) { - // Set the calculated width on each tab. - auto tvi = item.try_as<winrt::TabViewItem>(); - if (!tvi) + for (auto item : TabItems()) { - tvi = ContainerFromItem(item).as<winrt::TabViewItem>(); - } + // Set the calculated width on each tab. + auto tvi = item.try_as<winrt::TabViewItem>(); + if (!tvi) + { + tvi = ContainerFromItem(item).as<winrt::TabViewItem>(); + } - if (tvi) - { - tvi.Width(tabWidth); + if (tvi) + { + tvi.Width(tabWidth); + } } } } diff --git a/dev/TabView/TabView.h b/dev/TabView/TabView.h index 0a81378f19..ffe3b5fde0 100644 --- a/dev/TabView/TabView.h +++ b/dev/TabView/TabView.h @@ -89,7 +89,7 @@ class TabView : // IFrameworkElement void OnApplyTemplate(); - winrt::Size MeasureOverride(winrt::Size const& availableSize); + winrt::Size MeasureOverride(winrt::Size const& availableSize); // IUIElement winrt::AutomationPeer OnCreateAutomationPeer(); @@ -127,6 +127,7 @@ class TabView : void OnItemsPresenterSizeChanged(const winrt::IInspectable& sender, const winrt::SizeChangedEventArgs& args); void OnListViewLoaded(const winrt::IInspectable& sender, const winrt::RoutedEventArgs& args); + void OnTabStripPointerExited(const winrt::IInspectable& sender, const winrt::PointerRoutedEventArgs& args); void OnListViewSelectionChanged(const winrt::IInspectable& sender, const winrt::SelectionChangedEventArgs& args); void OnListViewDragItemsStarting(const winrt::IInspectable& sender, const winrt::DragItemsStartingEventArgs& args); @@ -144,7 +145,7 @@ class TabView : void UpdateSelectedItem(); void UpdateSelectedIndex(); - void UpdateTabWidths(); + void UpdateTabWidths(bool shouldUpdateWidths=true, bool fillAllAvailableSpace=true); void UpdateScrollViewerDecreaseAndIncreaseButtonsViewState(); @@ -152,6 +153,9 @@ class TabView : int GetItemCount(); + bool updateTabWidthOnPointerLeave{ false }; + + winrt::TabViewItem FindTabViewItemFromDragItem(const winrt::IInspectable& item); tracker_ref<winrt::ColumnDefinition> m_leftContentColumn{ this }; @@ -172,6 +176,7 @@ class TabView : tracker_ref<winrt::Grid> m_shadowReceiver{ this }; winrt::ListView::Loaded_revoker m_listViewLoadedRevoker{}; + winrt::ListView::PointerExited_revoker m_tabStripPointerExitedRevoker{}; winrt::Selector::SelectionChanged_revoker m_listViewSelectionChangedRevoker{}; winrt::UIElement::GettingFocus_revoker m_listViewGettingFocusRevoker{}; diff --git a/dev/TabView/TestUI/TabViewPage.xaml b/dev/TabView/TestUI/TabViewPage.xaml index 4a1dc0d9f2..abf9084f67 100644 --- a/dev/TabView/TestUI/TabViewPage.xaml +++ b/dev/TabView/TestUI/TabViewPage.xaml @@ -153,7 +153,12 @@ <StackPanel x:Name="FirstTabContent" AutomationProperties.Name="FirstTabContent"> <Button x:Name="FirstTabButton" AutomationProperties.Name="FirstTabButton" Margin="8" FontSize="20">Home Button</Button> - <Button x:Name="TabViewSizingPageButton" AutomationProperties.Name="TabViewSizingPageButton" Margin="8" Click="TabViewSizingPageButton_Click" FontSize="20">TabView Sizing Page</Button> + <Button x:Name="TabViewSizingPageButton" AutomationProperties.Name="TabViewSizingPageButton" + Margin="8" Click="TabViewSizingPageButton_Click" + FontSize="20">TabView Sizing Page</Button> + <Button x:Name="TabViewTabClosingBehaviorButton" AutomationProperties.Name="TabViewTabClosingBehaviorButton" + Margin="8" Click="TabViewTabClosingBehaviorButton_Click" + FontSize="20">TabView Tab Closing behavior Page</Button> </StackPanel> </controls:TabViewItem> diff --git a/dev/TabView/TestUI/TabViewPage.xaml.cs b/dev/TabView/TestUI/TabViewPage.xaml.cs index 8e0a5f652d..a9861bd8e5 100644 --- a/dev/TabView/TestUI/TabViewPage.xaml.cs +++ b/dev/TabView/TestUI/TabViewPage.xaml.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See LICENSE in the project root for license information. using System; @@ -394,6 +394,12 @@ private void TabViewSizingPageButton_Click(object sender, RoutedEventArgs e) this.Frame.Navigate(typeof(TabViewSizingPage)); } + + private void TabViewTabClosingBehaviorButton_Click(object sender, RoutedEventArgs e) + { + this.Frame.Navigate(typeof(TabViewTabClosingBehaviorPage)); + } + private void ShortLongTextButton_Click(object sender, RoutedEventArgs e) { FirstTab.Header = "s"; diff --git a/dev/TabView/TestUI/TabViewTabClosingBehaviorPage.xaml b/dev/TabView/TestUI/TabViewTabClosingBehaviorPage.xaml new file mode 100644 index 0000000000..f39f3a7f7d --- /dev/null +++ b/dev/TabView/TestUI/TabViewTabClosingBehaviorPage.xaml @@ -0,0 +1,44 @@ +<Page + x:Class="MUXControlsTestApp.TabViewTabClosingBehaviorPage" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:muxc="using:Microsoft.UI.Xaml.Controls" + mc:Ignorable="d" + Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> + <Grid> + <StackPanel Orientation="Horizontal"> + <Grid MaxWidth="500"> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="Auto"/> + <ColumnDefinition Width="*"/> + </Grid.ColumnDefinitions> + <muxc:TabView + MaxWidth="500" + x:Name="Tabs" + TabCloseRequested="TabViewTabCloseRequested" + AddTabButtonClick="AddButtonClick"> + + <muxc:TabViewItem Header="Tab 0" AutomationProperties.Name="Tab 0"/> + <muxc:TabViewItem Header="Tab 1" AutomationProperties.Name="Tab 1"/> + <muxc:TabViewItem Header="Tab 2" AutomationProperties.Name="Tab 2"/> + <muxc:TabViewItem Header="Tab 3" AutomationProperties.Name="Tab 3"/> + <muxc:TabViewItem Header="Tab 4" AutomationProperties.Name="Tab 4"/> + <muxc:TabViewItem Header="Tab 5" AutomationProperties.Name="Tab 5"/> + </muxc:TabView> + </Grid> + <StackPanel> + <TextBlock Text="Actual width"/> + <TextBlock x:Name="TabViewWidth" AutomationProperties.Name="TabViewWidth"/> + <TextBlock Text="Scroll buttons status"/> + <TextBlock x:Name="ScrollButtonStatus" AutomationProperties.Name="ScrollButtonStatus" /> + </StackPanel> + <StackPanel> + <Button AutomationProperties.Name="GetActualWidthButton" + Click="GetActualWidthsButton_Click" + Content="Get actual TabView width"/> + </StackPanel> + </StackPanel> + </Grid> +</Page> diff --git a/dev/TabView/TestUI/TabViewTabClosingBehaviorPage.xaml.cs b/dev/TabView/TestUI/TabViewTabClosingBehaviorPage.xaml.cs new file mode 100644 index 0000000000..dd8b3aa58b --- /dev/null +++ b/dev/TabView/TestUI/TabViewTabClosingBehaviorPage.xaml.cs @@ -0,0 +1,72 @@ +using Microsoft.UI.Xaml.Controls; +using MUXControlsTestApp.Utilities; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices.WindowsRuntime; +using Windows.Foundation; +using Windows.Foundation.Collections; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Controls.Primitives; +using Windows.UI.Xaml.Data; +using Windows.UI.Xaml.Input; +using Windows.UI.Xaml.Media; +using Windows.UI.Xaml.Navigation; + +// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 + +namespace MUXControlsTestApp +{ + /// <summary> + /// An empty page that can be used on its own or navigated to within a Frame. + /// </summary> + public sealed partial class TabViewTabClosingBehaviorPage : Page + { + private int _newTabNumber = 0; + + public TabViewTabClosingBehaviorPage() + { + this.InitializeComponent(); + } + + public void AddButtonClick(object sender, object e) + { + if (Tabs != null) + { + TabViewItem item = new TabViewItem(); + item.Header = "New Tab " + _newTabNumber; + item.Content = item.Header; + + Tabs.TabItems.Add(item); + + _newTabNumber++; + } + } + + private void TabViewTabCloseRequested(object sender, Microsoft.UI.Xaml.Controls.TabViewTabCloseRequestedEventArgs e) + { + Tabs.TabItems.Remove(e.Tab); + + TabViewWidth.Text = Tabs.ActualWidth.ToString(); + + var scrollButtonStateValue = ""; + + var scrollIncreaseButton = VisualTreeUtils.FindVisualChildByName(Tabs, "ScrollIncreaseButton") as RepeatButton; + var scrollDecreaseButton = VisualTreeUtils.FindVisualChildByName(Tabs, "ScrollDecreaseButton") as RepeatButton; + + scrollButtonStateValue += scrollIncreaseButton.IsEnabled + ";"; + scrollButtonStateValue += scrollDecreaseButton.IsEnabled + ";"; + + ScrollButtonStatus.Text = scrollButtonStateValue; + } + + public void GetActualWidthsButton_Click(object sender, RoutedEventArgs e) + { + // This is the smallest width that fits our content without any scrolling. + TabViewWidth.Text = Tabs.ActualWidth.ToString(); + } + + } +} diff --git a/dev/TabView/TestUI/TabView_TestUI.projitems b/dev/TabView/TestUI/TabView_TestUI.projitems index 4824c63692..cc36bc2a09 100644 --- a/dev/TabView/TestUI/TabView_TestUI.projitems +++ b/dev/TabView/TestUI/TabView_TestUI.projitems @@ -18,6 +18,10 @@ <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> </Page> + <Page Include="$(MSBuildThisFileDirectory)TabViewTabClosingBehaviorPage.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> </ItemGroup> <ItemGroup> <Compile Include="$(MSBuildThisFileDirectory)TabViewSizingPage.xaml.cs"> @@ -26,5 +30,8 @@ <Compile Include="$(MSBuildThisFileDirectory)TabViewPage.xaml.cs"> <DependentUpon>TabViewPage.xaml</DependentUpon> </Compile> + <Compile Include="$(MSBuildThisFileDirectory)TabViewTabClosingBehaviorPage.xaml.cs"> + <DependentUpon>TabViewTabClosingBehaviorPage.xaml</DependentUpon> + </Compile> </ItemGroup> </Project> \ No newline at end of file