Skip to content

Commit

Permalink
Automation Peer fix for Hierarchical NavigationView (#2627)
Browse files Browse the repository at this point in the history
* fixed left nav uia

* updated top nav

* added test

* cleanup

* fixed level reporting

* addressed comments
  • Loading branch information
ojhad authored and ranjeshj committed Jul 7, 2020
1 parent a2a1970 commit 6aa3549
Show file tree
Hide file tree
Showing 4 changed files with 1,727 additions and 79 deletions.
4 changes: 2 additions & 2 deletions dev/NavigationView/NavigationView.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ class NavigationView :
// Used in AutomationPeer
winrt::ItemsRepeater LeftNavRepeater();
winrt::NavigationViewItem GetSelectedContainer();
winrt::ItemsRepeater GetParentItemsRepeaterForContainer(const winrt::NavigationViewItemBase& nvib);
winrt::IndexPath GetIndexPathForContainer(const winrt::NavigationViewItemBase& nvib);

// Hierarchical related functions
void Expand(const winrt::NavigationViewItem& item);
Expand All @@ -107,7 +109,6 @@ class NavigationView :
int GetIndexFromItem(const winrt::ItemsRepeater& ir, const winrt::IInspectable& data);
static winrt::IInspectable GetItemFromIndex(const winrt::ItemsRepeater& ir, int index);
winrt::IndexPath GetIndexPathOfItem(const winrt::IInspectable& data);
winrt::IndexPath GetIndexPathForContainer(const winrt::NavigationViewItemBase& nvib);
winrt::UIElement GetContainerForIndex(int index);
winrt::NavigationViewItemBase GetContainerForIndexPath(const winrt::IndexPath& ip);
winrt::NavigationViewItemBase GetContainerForIndexPath(const winrt::UIElement& firstContainer, const winrt::IndexPath& ip);
Expand All @@ -118,7 +119,6 @@ class NavigationView :
winrt::IndexPath SearchEntireTreeForIndexPath(const winrt::NavigationViewItem& parentContainer, const winrt::IInspectable& data, const winrt::IndexPath& ip);

winrt::ItemsRepeater GetChildRepeaterForIndexPath(const winrt::IndexPath& ip);
winrt::ItemsRepeater GetParentItemsRepeaterForContainer(const winrt::NavigationViewItemBase& nvib);
winrt::NavigationViewItem GetParentNavigationViewItemForContainer(const winrt::NavigationViewItemBase& nvib);
bool IsContainerTheSelectedItemInTheSelectionModel(const winrt::NavigationViewItemBase& nvib);
bool IsContainerInOverflow(const winrt::NavigationViewItemBase& nvib);
Expand Down
168 changes: 92 additions & 76 deletions dev/NavigationView/NavigationViewItemAutomationPeer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "NavigationView.h"
#include "NavigationViewItemBase.h"
#include "SharedHelpers.h"
#include "NavigationViewHelper.h"


#include "NavigationViewItemAutomationPeer.properties.cpp"
Expand Down Expand Up @@ -88,12 +89,7 @@ int32_t NavigationViewItemAutomationPeer::GetPositionInSetCore()

if (IsOnTopNavigation())
{
if (auto navigationView = GetParentNavigationView())
{
auto topDataProvider = winrt::get_self<NavigationView>(navigationView)->GetTopDataProvider();
positionInSet = GetPositionOrSetCountInTopNavHelper(IsOnTopNavigationOverflow()
? topDataProvider.GetOverflowItems() : topDataProvider.GetPrimaryItems(), AutomationOutput::Position);
}
positionInSet = GetPositionOrSetCountInTopNavHelper(AutomationOutput::Position);
}
else
{
Expand All @@ -114,13 +110,7 @@ int32_t NavigationViewItemAutomationPeer::GetSizeOfSetCore()

if (IsOnTopNavigation())
{
if (auto navview = GetParentNavigationView())
{
auto topNavDataProvider = winrt::get_self<NavigationView>(navview)->GetTopDataProvider();
sizeOfSet = GetPositionOrSetCountInTopNavHelper(IsOnTopNavigationOverflow()
? topNavDataProvider.GetOverflowItems() : topNavDataProvider.GetPrimaryItems(), AutomationOutput::Size);

}
sizeOfSet = GetPositionOrSetCountInTopNavHelper(AutomationOutput::Size);
}
else
{
Expand All @@ -132,13 +122,26 @@ int32_t NavigationViewItemAutomationPeer::GetSizeOfSetCore()

int32_t NavigationViewItemAutomationPeer::GetLevelCore()
{
int32_t level = 0;
if (winrt::NavigationViewItemBase navigationViewItem = Owner().try_as<winrt::NavigationViewItemBase>())
if (winrt::NavigationViewItemBase nvib = Owner().try_as<winrt::NavigationViewItemBase>())
{
return winrt::get_self<NavigationViewItemBase>(navigationViewItem)->Depth();
auto const nvibImpl = winrt::get_self<NavigationViewItemBase>(nvib);
if (nvibImpl->IsTopLevelItem())
{
return 1;
}
else
{
if (auto const navView = GetParentNavigationView())
{
if (auto const indexPath = winrt::get_self<NavigationView>(navView)->GetIndexPathForContainer(nvib))
{
return indexPath.GetSize();
}
}
}
}

return level;
return 0;
}

void NavigationViewItemAutomationPeer::Invoke()
Expand Down Expand Up @@ -279,6 +282,19 @@ NavigationViewRepeaterPosition NavigationViewItemAutomationPeer::GetNavigationVi
return NavigationViewRepeaterPosition::LeftNav;
}

winrt::ItemsRepeater NavigationViewItemAutomationPeer::GetParentRepeater()
{
if (auto const navview = GetParentNavigationView())
{
if (winrt::NavigationViewItemBase navigationViewItem = Owner().try_as<winrt::NavigationViewItemBase>())
{
return winrt::get_self<NavigationView>(navview)->GetParentItemsRepeaterForContainer(navigationViewItem);
}
}
return nullptr;
}


// Get either the position or the size of the set for this particular item in the case of left nav.
// We go through all the items and then we determine if the listviewitem from the left listview can be a navigation view item header
// or a navigation view item. If it's the former, we just reset the count. If it's the latter, we increment the counter.
Expand All @@ -287,54 +303,51 @@ int32_t NavigationViewItemAutomationPeer::GetPositionOrSetCountInLeftNavHelper(A
{
int returnValue = 0;

if (auto const navview = GetParentNavigationView())
if (auto const repeater = GetParentRepeater())
{
if (auto const repeater = winrt::get_self<NavigationView>(navview)->LeftNavRepeater())
if (auto const parent = Navigate(winrt::AutomationNavigationDirection::Parent).try_as<winrt::AutomationPeer>())
{
if (auto const parent = Navigate(winrt::AutomationNavigationDirection::Parent).try_as<winrt::AutomationPeer>())
if (auto const children = parent.GetChildren())
{
if (auto const children = parent.GetChildren())
{
int index = 0;
bool itemFound = false;
int index = 0;
bool itemFound = false;

for (auto const& child : children)
for (auto const& child : children)
{
if (auto dependencyObject = repeater.TryGetElement(index))
{
if (auto dependencyObject = repeater.TryGetElement(index))
if (dependencyObject.try_as<winrt::NavigationViewItemHeader>())
{
if (dependencyObject.try_as<winrt::NavigationViewItemHeader>())
if (automationOutput == AutomationOutput::Size && itemFound)
{
if (automationOutput == AutomationOutput::Size && itemFound)
{
break;
}
else
{
returnValue = 0;
}
break;
}
else if (auto navviewItem = dependencyObject.try_as<winrt::NavigationViewItem>())
else
{
if (navviewItem.Visibility() == winrt::Visibility::Visible)
{
returnValue++;
returnValue = 0;
}
}
else if (auto navviewItem = dependencyObject.try_as<winrt::NavigationViewItem>())
{
if (navviewItem.Visibility() == winrt::Visibility::Visible)
{
returnValue++;

if (winrt::FrameworkElementAutomationPeer::FromElement(navviewItem) == static_cast<winrt::NavigationViewItemAutomationPeer>(*this))
if (winrt::FrameworkElementAutomationPeer::FromElement(navviewItem) == static_cast<winrt::NavigationViewItemAutomationPeer>(*this))
{
if (automationOutput == AutomationOutput::Position)
{
break;
}
else
{
if (automationOutput == AutomationOutput::Position)
{
break;
}
else
{
itemFound = true;
}
itemFound = true;
}
}
}
}
index++;
}
index++;
}
}
}
Expand All @@ -347,49 +360,52 @@ int32_t NavigationViewItemAutomationPeer::GetPositionOrSetCountInLeftNavHelper(A
// Basically, we do the same here as GetPositionOrSetCountInLeftNavHelper without dealing with the listview directly, because
// TopDataProvider provcides two methods: GetOverflowItems() and GetPrimaryItems(), so we can break the loop (in case of position) by
// comparing the value of the FrameworkElementAutomationPeer we can get from the item we're iterating through to this object.
int32_t NavigationViewItemAutomationPeer::GetPositionOrSetCountInTopNavHelper(winrt::IVector<winrt::IInspectable> navigationViewElements, AutomationOutput automationOutput)
int32_t NavigationViewItemAutomationPeer::GetPositionOrSetCountInTopNavHelper(AutomationOutput automationOutput)
{
int32_t returnValue = 0;
bool itemFound = false;

if (auto const navview = GetParentNavigationView())
if (auto const parentRepeater = GetParentRepeater())
{
bool itemFound = false;

for (auto const& child : navigationViewElements)
if (auto const itemsSourceView = parentRepeater.ItemsSourceView())
{
if (auto const childAsNavViewItem = navview.ContainerFromMenuItem(child))
auto numberOfElements = itemsSourceView.Count();

for (int32_t i = 0; i < numberOfElements; i++)
{
if (child.try_as<winrt::NavigationViewItemHeader>())
if (auto child = parentRepeater.TryGetElement(i))
{
if (automationOutput == AutomationOutput::Size && itemFound)
{
break;
}
else
if (child.try_as<winrt::NavigationViewItemHeader>())
{
returnValue = 0;
if (automationOutput == AutomationOutput::Size && itemFound)
{
break;
}
else
{
returnValue = 0;
}
}
}
else if (auto const navviewitem = childAsNavViewItem.try_as<winrt::NavigationViewItem>())
{
if (navviewitem.Visibility() == winrt::Visibility::Visible)
else if (auto const navviewitem = child.try_as<winrt::NavigationViewItem>())
{
returnValue++;

if (winrt::FrameworkElementAutomationPeer::FromElement(navviewitem) == static_cast<winrt::NavigationViewItemAutomationPeer>(*this))
if (navviewitem.Visibility() == winrt::Visibility::Visible)
{
if (automationOutput == AutomationOutput::Position)
{
break;
}
else
returnValue++;

if (winrt::FrameworkElementAutomationPeer::FromElement(navviewitem) == static_cast<winrt::NavigationViewItemAutomationPeer>(*this))
{
itemFound = true;
if (automationOutput == AutomationOutput::Position)
{
break;
}
else
{
itemFound = true;
}
}
}
}
}

}
}
}
Expand Down
3 changes: 2 additions & 1 deletion dev/NavigationView/NavigationViewItemAutomationPeer.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,14 @@ class NavigationViewItemAutomationPeer :
};

winrt::NavigationView GetParentNavigationView();
winrt::ItemsRepeater GetParentRepeater();
bool IsOnTopNavigation();
bool IsOnTopNavigationOverflow();
bool IsSettingsItem();
NavigationViewRepeaterPosition GetNavigationViewRepeaterPosition();
int32_t GetNavigationViewItemCountInPrimaryList();
int32_t GetNavigationViewItemCountInTopNav();
int32_t GetPositionOrSetCountInLeftNavHelper(AutomationOutput automationOutput);
int32_t GetPositionOrSetCountInTopNavHelper(winrt::IVector<winrt::IInspectable> navigationViewElements, AutomationOutput automationOutput);
int32_t GetPositionOrSetCountInTopNavHelper(AutomationOutput automationOutput);
void ChangeSelection(bool isSelected);
};
Loading

0 comments on commit 6aa3549

Please sign in to comment.