Skip to content

Commit

Permalink
Hide NavigationViewItem Chevron if Children is empty (#2759)
Browse files Browse the repository at this point in the history
* Hide NavigationViewItem Chevron if Children is empty

Attach a CollectionChanged to ItemsRepeater ItemsViewSource
whenever the MenuItems or MenuItemsSource changes.
Add check to MenuItemsSource count when checking for children.

Fixes #2743

* removed unused args

* add VerifyExpandCollapseChevronVisibility API test

* revoke m_itemsSourceViewCollectionChangedRevoker inside UnhookEventsAndClearFields

* use VisualTreeUtils.FindVisualChildByName and removed own implementation

* add additional test for the MenuItems API

* add visibility check before setting MenuItemsSource as null
  • Loading branch information
MarkIvanDev authored Jul 1, 2020
1 parent 2e05d37 commit 08723fb
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 1 deletion.
10 changes: 9 additions & 1 deletion dev/NavigationView/NavigationViewItem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,16 @@ void NavigationViewItem::UpdateRepeaterItemsSource()
}
return MenuItems().as<winrt::IInspectable>();
}();
m_itemsSourceViewCollectionChangedRevoker.revoke();
repeater.ItemsSource(itemsSource);
m_itemsSourceViewCollectionChangedRevoker = repeater.ItemsSourceView().CollectionChanged(winrt::auto_revoke, { this, &NavigationViewItem::OnItemsSourceViewChanged });
}
}

void NavigationViewItem::OnItemsSourceViewChanged(const winrt::IInspectable& /*sender*/, const winrt::NotifyCollectionChangedEventArgs& /*args*/)
{
UpdateVisualStateForChevron();
}

winrt::UIElement NavigationViewItem::GetSelectionIndicator() const
{
Expand Down Expand Up @@ -468,7 +475,7 @@ void NavigationViewItem::UpdateVisualStateForChevron()

bool NavigationViewItem::HasChildren()
{
return MenuItems().Size() > 0 || MenuItemsSource() != nullptr || HasUnrealizedChildren();
return MenuItems().Size() > 0 || (MenuItemsSource() != nullptr && m_repeater.get().ItemsSourceView().Count() > 0) || HasUnrealizedChildren();
}

bool NavigationViewItem::ShouldShowIcon()
Expand Down Expand Up @@ -919,6 +926,7 @@ void NavigationViewItem::UnhookEventsAndClearFields()
m_repeaterElementPreparedRevoker.revoke();
m_repeaterElementClearingRevoker.revoke();
m_isEnabledChangedRevoker.revoke();
m_itemsSourceViewCollectionChangedRevoker.revoke();

m_rootGrid.set(nullptr);
m_navigationViewItemPresenter.set(nullptr);
Expand Down
2 changes: 2 additions & 0 deletions dev/NavigationView/NavigationViewItem.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ class NavigationViewItem :
bool IsOnTopPrimary() const;

void UpdateRepeaterItemsSource();
void OnItemsSourceViewChanged(const winrt::IInspectable& sender, const winrt::NotifyCollectionChangedEventArgs& args);
void ReparentRepeater();
void OnFlyoutClosing(const winrt::IInspectable& sender, const winrt::FlyoutBaseClosingEventArgs& args);
void UpdateItemIndentation();
Expand All @@ -124,6 +125,7 @@ class NavigationViewItem :

winrt::ItemsRepeater::ElementPrepared_revoker m_repeaterElementPreparedRevoker{};
winrt::ItemsRepeater::ElementClearing_revoker m_repeaterElementClearingRevoker{};
winrt::ItemsSourceView::CollectionChanged_revoker m_itemsSourceViewCollectionChangedRevoker{};

winrt::FlyoutBase::Closing_revoker m_flyoutClosingRevoker{};
winrt::Control::IsEnabledChanged_revoker m_isEnabledChangedRevoker{};
Expand Down
62 changes: 62 additions & 0 deletions dev/NavigationView/NavigationView_ApiTests/NavigationViewTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -790,5 +790,67 @@ public void VerifyNavigationViewItemInFooterDoesNotCrash()
Verify.IsTrue(true);
});
}

[TestMethod]
public void VerifyExpandCollapseChevronVisibility()
{
NavigationView navView = null;
NavigationViewItem parentItem = null;
ObservableCollection<string> children = null;

RunOnUIThread.Execute(() =>
{
navView = new NavigationView();
Content = navView;

children = new ObservableCollection<string>();
parentItem = new NavigationViewItem() { Content = "ParentItem", MenuItemsSource = children };

navView.MenuItems.Add(parentItem);

navView.Width = 1008; // forces the control into Expanded mode so that the menu renders
Content.UpdateLayout();

UIElement chevronUIElement = (UIElement)VisualTreeUtils.FindVisualChildByName(parentItem, "ExpandCollapseChevron");
Verify.IsTrue(chevronUIElement.Visibility == Visibility.Collapsed, "chevron should have been collapsed as NavViewItem has no children");

// Add a child to parentItem through the MenuItemsSource API. This should make the chevron visible.
children.Add("Child 1");
Content.UpdateLayout();

Verify.IsTrue(chevronUIElement.Visibility == Visibility.Visible, "chevron should have been visible as NavViewItem now has children");

// Remove all children of parentItem. This should collapse the chevron
children.Clear();
Content.UpdateLayout();

Verify.IsTrue(chevronUIElement.Visibility == Visibility.Collapsed, "chevron should have been collapsed as NavViewItem no longer has children");

// Add a child to parentItem and set the MenuItemsSource as null. This should collapse the chevron
children.Add("Child 2");
Content.UpdateLayout();

// we are doing this so that when we set MenuItemsSource as null, we can check if the chevron's visibility really changes
Verify.IsTrue(chevronUIElement.Visibility == Visibility.Visible, "chevron should have been visible as NavViewItem now has children");

parentItem.MenuItemsSource = null;
Content.UpdateLayout();

Verify.IsTrue(chevronUIElement.Visibility == Visibility.Collapsed, "chevron should have been collapsed as NavViewItem no longer has children");

// Add a child to parentItem through the MenuItems API. This should make the chevron visible.
parentItem.MenuItems.Add(new NavigationViewItem() { Content = "Child 3" });
Content.UpdateLayout();

Verify.IsTrue(chevronUIElement.Visibility == Visibility.Visible, "chevron should have been visible as NavViewItem now has children");

// Remove all children of parentItem. This should collapse the chevron
parentItem.MenuItems.Clear();
Content.UpdateLayout();

Verify.IsTrue(chevronUIElement.Visibility == Visibility.Collapsed, "chevron should have been collapsed as NavViewItem no longer has children");
});
}

}
}

0 comments on commit 08723fb

Please sign in to comment.