flyte
flyte

Reputation: 1322

Flyout's "Light Dismissal" Causing 2 Taps to be Required to Open Next Flyout

I have two buttons that show Flyouts when clicked. I am displaying them the same way as demonstrated in the XAML UI Basics sample:

private void ButtonTapped(object sender, TappedRoutedEventArgs e)
{
    FrameworkElement element = sender as FrameworkElement;
    if (element != null)
    {               
        FlyoutBase.ShowAttachedFlyout(element);
    }
}

My problem is that if Button 1's flyout is open, the next tap on the screen closes the flyout. This is fine, but if the next tap happens to be on Button 2, I want the button's tap event to be fired and open its flyout. Instead, the button doesn't register a tap at all and closes Button 1's flyout.

This results in needing to tap two times - one to dismiss the Button 1's flyout, and a second to show Button 2's flyout.

In other words:

Current Flow:

  1. Tap Button 1
  2. Button 1's Flyout is opened
  3. Tap Button 2
  4. Button 1's flyout is closed, (Button 2, nor Page registers the tap)
  5. Tap Button 2
  6. Now Button 2's flyout is opened

What I'm Looking For:

  1. Tap Button 1
  2. Button 1's Flyout is opened
  3. Tap Button 2
  4. Button 1's flyout is closed, Button 2's flyout opens.

How can I do this? I've tried intercepting the Tapped event for the page, but when the flyout is open, it seems to intercept the Tapped event so it can be used for the Flyout's light dismissal

Would overriding the style of the Flyout, or the FlyoutPresenterStyle help me here? Or perhaps opening the Flyout in a more MVVM-ish way which would allow me for finer control on how the Flyout is opened/closed?

I'm not sure how to get around this!

Upvotes: 3

Views: 972

Answers (1)

edjoker
edjoker

Reputation: 167

Here is something I found on Microsoft documents:

When dismissing with a tap, this gesture is typically absorbed and not passed on to the UI underneath. For example, if there’s a button visible behind an open flyout, the user’s first tap dismisses the flyout but does not activate this button. Pressing the button requires a second tap.

You can change this behaviour by designating the button as an input pass-through element for the flyout. The flyout will close as a result of the light dismiss actions described above and will also pass the tap event to its designated OverlayInputPassThroughElement. Consider adopting this behaviour to speed up user interactions on functionally similar items. If your app has a favourites collection and each item in the collection includes an attached flyout, it's reasonable to expect that users may want to interact with multiple flyouts in rapid succession.

[!NOTE] Be careful not to designate an overlay input pass-through element which results in a destructive action. Users have become habituated to discreet light dismiss actions which do not activate primary UI. Close, Delete or similarly destructive buttons should not activate on light dismiss to avoid the unexpected and disruptive behaviour. In the following example, all three buttons inside FavoritesBar will be activated on the first tap.

<Page>
<Page.Resources>
    <Flyout x:Name="TravelFlyout" x:Key="TravelFlyout"
            OverlayInputPassThroughElement="{x:Bind FavoritesBar}">
        <StackPanel>
            <HyperlinkButton Content="Washington Trails Association"/>
            <HyperlinkButton Content="Washington Cascades - Go Northwest! A Travel Guide"/>  
        </StackPanel>
    </Flyout>
</Page.Resources>

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <StackPanel x:Name="FavoritesBar" Orientation="Horizontal">
        <HyperlinkButton x:Name="PageLinkBtn">Bing</HyperlinkButton>  
        <Button x:Name="Folder1" Content="Travel" Flyout="{StaticResource TravelFlyout}"/>
        <Button x:Name="Folder2" Content="Entertainment" Click="Folder2_Click"/>
    </StackPanel>
    <ScrollViewer Grid.Row="1">
        <WebView x:Name="WebContent"/>
    </ScrollViewer>
</Grid>

private void Folder2_Click(object sender, RoutedEventArgs e){
 Flyout flyout = new Flyout();
 flyout.OverlayInputPassThroughElement = FavoritesBar;

 flyout.ShowAt(sender as FrameworkElement);}

Upvotes: 3

Related Questions