Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix issue with TabPaneFooter Width/MinWidth not being respected #3531

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion dev/Generated/TabView.properties.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ void TabViewProperties::EnsureProperties()
winrt::name_of<winrt::TabView>(),
false /* isAttached */,
ValueHelper<winrt::IInspectable>::BoxedDefaultValue(),
nullptr);
winrt::PropertyChangedCallback(&OnTabStripFooterPropertyChanged));
}
if (!s_TabStripFooterTemplateProperty)
{
Expand Down Expand Up @@ -302,6 +302,14 @@ void TabViewProperties::OnTabItemsSourcePropertyChanged(
winrt::get_self<TabView>(owner)->OnTabItemsSourcePropertyChanged(args);
}

void TabViewProperties::OnTabStripFooterPropertyChanged(
winrt::DependencyObject const& sender,
winrt::DependencyPropertyChangedEventArgs const& args)
{
auto owner = sender.as<winrt::TabView>();
winrt::get_self<TabView>(owner)->OnTabStripFooterPropertyChanged(args);
}

void TabViewProperties::OnTabWidthModePropertyChanged(
winrt::DependencyObject const& sender,
winrt::DependencyPropertyChangedEventArgs const& args)
Expand Down
4 changes: 4 additions & 0 deletions dev/Generated/TabView.properties.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,10 @@ class TabViewProperties
winrt::DependencyObject const& sender,
winrt::DependencyPropertyChangedEventArgs const& args);

static void OnTabStripFooterPropertyChanged(
winrt::DependencyObject const& sender,
winrt::DependencyPropertyChangedEventArgs const& args);

static void OnTabWidthModePropertyChanged(
winrt::DependencyObject const& sender,
winrt::DependencyPropertyChangedEventArgs const& args);
Expand Down
2 changes: 1 addition & 1 deletion dev/NavigationView/NavigationView.cpp
Original file line number Diff line number Diff line change
@@ -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"
Expand Down
52 changes: 51 additions & 1 deletion dev/TabView/APITests/TabViewTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,57 @@ static ISelectionItemProvider GetProviderFromTVI(TabViewItem item)
}

[TestMethod]
public void VerifyTabViewWithoutTabsDoesNotCrash()
public void VerifyPaneFooterSizingRespected()
{
foreach (var property in new DependencyProperty[] { FrameworkElement.MinWidthProperty, FrameworkElement.WidthProperty })
{
TabView tabView = null;
Grid paneFooter = null;
RunOnUIThread.Execute(() =>
{
paneFooter = new Grid();
tabView = new TabView();

var container = new Grid() {
MaxWidth = 600
};
container.Children.Add(tabView);

tabView.TabItems.Add(new TabViewItem());
tabView.TabItems.Add(new TabViewItem());
tabView.TabItems.Add(new TabViewItem());
tabView.TabItems.Add(new TabViewItem());

tabView.TabStripFooter = paneFooter;
tabView.UpdateLayout();
tabView.HorizontalAlignment = HorizontalAlignment.Stretch;
tabView.Width = 600;

container.UpdateLayout();
Content = container;
paneFooter.UpdateLayout();
});

IdleSynchronizer.Wait();

RunOnUIThread.Execute(() =>
{
Verify.IsTrue(Math.Abs(600 - tabView.ActualWidth) < 1);
paneFooter.SetValue(property, 300);
});
IdleSynchronizer.Wait();

RunOnUIThread.Execute(() =>
{
var footerPresenter = VisualTreeHelper.GetParent(paneFooter) as FrameworkElement;
Verify.IsTrue(Math.Abs(300 - footerPresenter.ActualWidth) < 1);
});
}
}



private void VerifyTabViewWithoutTabsDoesNotCrash()
{
RunOnUIThread.Execute(() =>
{
Expand Down
55 changes: 53 additions & 2 deletions dev/TabView/TabView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,16 @@ TabView::TabView()
}
}

TabView::~TabView()
{
UnhookEventsAndClearFields();
if (const auto footer = TabStripFooter().try_as<winrt::FrameworkElement>())
{
m_footerMinWidthProperyChangedRevoker.revoke();
m_footerWidthProperyChangedRevoker.revoke();
}
}

void TabView::OnApplyTemplate()
{
UnhookEventsAndClearFields();
Expand Down Expand Up @@ -340,6 +350,20 @@ void TabView::OnSelectedItemPropertyChanged(const winrt::DependencyPropertyChang
UpdateSelectedItem();
}

void TabView::OnTabStripFooterPropertyChanged(const winrt::DependencyPropertyChangedEventArgs& args)
{
if (const auto oldFooter = args.OldValue().try_as<winrt::FrameworkElement>())
{
m_footerMinWidthProperyChangedRevoker.revoke();
m_footerWidthProperyChangedRevoker.revoke();
}
if (const auto newFooter = args.NewValue().try_as<winrt::FrameworkElement>())
{
m_footerMinWidthProperyChangedRevoker = RegisterPropertyChanged(newFooter,winrt::FrameworkElement::MinWidthProperty(), { this,&TabView::OnFooterSizeChanged });
m_footerWidthProperyChangedRevoker = RegisterPropertyChanged(newFooter,winrt::FrameworkElement::WidthProperty(), { this,&TabView::OnFooterSizeChanged });
}
}

void TabView::OnTabItemsSourcePropertyChanged(const winrt::DependencyPropertyChangedEventArgs&)
{
UpdateListViewItemContainerTransitions();
Expand Down Expand Up @@ -718,6 +742,11 @@ void TabView::BringSelectedTabIntoView()
}
}

void TabView::OnFooterSizeChanged(const winrt::DependencyObject& /*sender*/, const winrt::DependencyProperty& args)
{
UpdateTabWidths();
}

void TabView::OnItemsChanged(winrt::IInspectable const& item)
{
if (auto args = item.as<winrt::IVectorChangedEventArgs>())
Expand Down Expand Up @@ -1067,8 +1096,30 @@ void TabView::UpdateTabWidths(bool shouldUpdateWidths, bool fillAllAvailableSpac
if (auto&& rightContentPresenter = m_rightContentPresenter.get())
{
const winrt::Size rightContentSize = rightContentPresenter.DesiredSize();
rightContentColumn.MinWidth(rightContentSize.Width);
widthTaken += rightContentSize.Width;

if (const auto tabStripFooter = TabStripFooter().try_as<winrt::FrameworkElement>())
{
const auto minWidth = tabStripFooter.MinWidth();
const auto width = tabStripFooter.Width();
const auto footerWidth = [this, width, minWidth, rightContentSize]() {
if (minWidth < width)
{
return rightContentSize.Width < width ? width : rightContentSize.Width;
}
else
{
return rightContentSize.Width < minWidth ? minWidth : rightContentSize.Width;
}
}();

rightContentColumn.MinWidth(footerWidth);
widthTaken += footerWidth;
}
else
{
rightContentColumn.MinWidth(rightContentSize.Width);
widthTaken += rightContentSize.Width;
}
}
}

Expand Down
7 changes: 7 additions & 0 deletions dev/TabView/TabView.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ class TabView :

public:
TabView();
~TabView();

// IFrameworkElement
void OnApplyTemplate();
Expand All @@ -112,6 +113,7 @@ class TabView :
void OnTabWidthModePropertyChanged(const winrt::DependencyPropertyChangedEventArgs& args);
void OnSelectedIndexPropertyChanged(const winrt::DependencyPropertyChangedEventArgs& args);
void OnSelectedItemPropertyChanged(const winrt::DependencyPropertyChangedEventArgs& args);
void OnTabStripFooterPropertyChanged(const winrt::DependencyPropertyChangedEventArgs& args);

void OnItemsChanged(winrt::IInspectable const& item);
void UpdateTabContent();
Expand All @@ -135,6 +137,8 @@ class TabView :
void OnScrollViewerViewChanged(winrt::IInspectable const& sender, winrt::ScrollViewerViewChangedEventArgs const& args);
void OnItemsPresenterSizeChanged(const winrt::IInspectable& sender, const winrt::SizeChangedEventArgs& args);

void OnFooterSizeChanged(const winrt::DependencyObject& /*sender*/, const winrt::DependencyProperty& args);

void OnListViewLoaded(const winrt::IInspectable& sender, const winrt::RoutedEventArgs& args);
void OnTabStripPointerExited(const winrt::IInspectable& sender, const winrt::PointerRoutedEventArgs& args);
void OnTabStripPointerEntered(const winrt::IInspectable& sender, const winrt::PointerRoutedEventArgs& args);
Expand Down Expand Up @@ -197,6 +201,9 @@ class TabView :

tracker_ref<winrt::Grid> m_shadowReceiver{ this };

PropertyChanged_revoker m_footerMinWidthProperyChangedRevoker{};
PropertyChanged_revoker m_footerWidthProperyChangedRevoker{};

winrt::ListView::Loaded_revoker m_listViewLoadedRevoker{};
winrt::ListView::PointerExited_revoker m_tabStripPointerExitedRevoker{};
winrt::ListView::PointerEntered_revoker m_tabStripPointerEnteredRevoker{};
Expand Down
3 changes: 2 additions & 1 deletion dev/TabView/TabView.idl
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,11 @@ unsealed runtimeclass TabView : Windows.UI.Xaml.Controls.Control
[MUX_DEFAULT_VALUE("winrt::TabViewCloseButtonOverlayMode::Auto")]
[MUX_PROPERTY_CHANGED_CALLBACK(TRUE)]
TabViewCloseButtonOverlayMode CloseButtonOverlayMode{ get; set; };

Object TabStripHeader{ get; set; };
Windows.UI.Xaml.DataTemplate TabStripHeaderTemplate{ get; set; };

[MUX_PROPERTY_CHANGED_CALLBACK(TRUE)]
Object TabStripFooter{ get; set; };
Windows.UI.Xaml.DataTemplate TabStripFooterTemplate{ get; set; };

Expand Down
31 changes: 31 additions & 0 deletions dev/TabView/TestUI/TabViewAppwindowPage.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<!-- Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. See LICENSE in the project root for license information. -->
<Page
x:Class="MUXControlsTestApp.TabViewAppwindowPage"
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 HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<muxc:TabView x:Name="Tabs"
VerticalAlignment="Stretch"
AddTabButtonClick="Tabs_AddTabButtonClick"
TabCloseRequested="Tabs_TabCloseRequested"
AllowDropTabs="True"
CanDragTabs="True"
CanReorderTabs="True"
TabDroppedOutside="Tabs_TabDroppedOutside"
TabStripDragOver="Tabs_TabStripDragOver"
TabStripDrop="Tabs_TabStripDrop"
TabDragStarting="Tabs_TabDragStarting" >

<muxc:TabView.TabStripHeader>
<Grid x:Name="ShellTitlebarInset" Background="Transparent" />
</muxc:TabView.TabStripHeader>
<muxc:TabView.TabStripFooter>
<Grid x:Name="CustomDragRegion" Background="Transparent" />
</muxc:TabView.TabStripFooter>
</muxc:TabView>
</Grid>
</Page>
Loading
Loading