There is a simple Page (MainPage.xaml)
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Button x:Name="Button" Content="Button"/>
</Page>
and the Page class is as follow
struct MainPage : PageT<MainPage>
{
inline static uint32_t SEQ = 0;
void Dump(FrameworkElement fwk)
{
printf("= %ws\n",get_class_name(fwk).data());
if(fwk.Parent())
Dump(fwk.Parent().as<FrameworkElement>());
}
MainPage()
{
try
{
Application::LoadComponent(*this,Uri(L"ms-appx:///MainPage.xaml"));
FindName(L"Button").as<UIElement>().LosingFocus([&](IInspectable sender, LosingFocusEventArgs const& args){
printf("%03d Button::LosingFocus\n",SEQ++);
if (args.NewFocusedElement())
{
printf(" %ws %ws\n",
get_class_name(args.OldFocusedElement()).data(),
get_class_name(args.NewFocusedElement()).data());
Dump(args.NewFocusedElement().as<FrameworkElement>());
}
else if (args.OldFocusedElement())
printf(" %ws null\n",
get_class_name(args.OldFocusedElement()).data());
else
printf(" null null\n");
});
}
catch(hresult_error e)
{
printf("MainPage 0x%x %ws\n",int32_t(e.code()),e.message().data());
}
}
hstring GetRuntimeClassName() const override
{
return L"MainPage";
}
};
When the Button is losing focus the output is as follow
000 Button::LosingFocus
Windows.UI.Xaml.Controls.Button Windows.UI.Xaml.Controls.ScrollViewer
= Windows.UI.Xaml.Controls.ScrollViewer
It seems UWP is trying to refocus to a ScrollViewer which I find nowhere for it. Is it a synthesized one? Many thanks!
Where does the ScrollViewer come from?
During the testing, it only occurs there is on other control could be focused, and the ScrollViewer
should be the visual container that use to render control, And you could find the Button with visual tree helper from the ScrollViewer
. And you could use the following code to find the root parent of Button
is ScrollViewer.
public static DependencyObject FindParent(DependencyObject dp)
{
DependencyObject parent = null;
DependencyObject currParent;
currParent = VisualTreeHelper.GetParent(dp);
do
{
parent = currParent;
// find the next parent
currParent = VisualTreeHelper.GetParent(currParent);
} while (currParent != null);
return (parent);
}
Usage
var parent = FindParent(button);