buttonuwpflyout

UWP: why does FlyoutBase.ShowAttachedFlyout fail for Button


I have a Button declared in XAML with a Button.Flyout nested element. I'm catching the button click and then wish to show the flyout. But I get an error:

ShowAttached was called on an element without an attached FlyoutBase.

Here's the XAML:

      <Button ... Click="onMoreClicked">
        <Image Source="..." />
        <Button.Flyout > 
         ...
        </Button.Flyout>
      </Button>

And, here's my handler:

public void onMoreClicked (object sender, RoutedEventArgs e)
{
  Log.L("LP OnMoreClicked");
  Button element = sender as Button;
  FlyoutBase flyout = element.Flyout as FlyoutBase;
  FlyoutBase.ShowAttachedFlyout(element);
}

When stepping in the debugger, element and flyout are defined, i.e. not null. Yet, ShowAttachedFlyout fails.

EDIT

For clarity, using the answer from @AryaDing-MSFT, here is my working solution:

<Button ... Click="onMoreClicked">
  <Image Source="..." />
  <FlyoutBase.AttachedFlyout> 
   ...
  </FlyoutBase.AttachedFlyout>
</Button>

Handler:

public void onMoreClicked (object sender, RoutedEventArgs e)
{
  Button button = sender as Button;
  ... do stuff ...
  FlyoutBase.ShowAttachedFlyout(button);
}

Solution

  • This issue is caused by not using FlyoutBase.AttachedFlyout to attach property, FlyoutBase.ShowAttachedFlyout and FlyoutBase.AttachedFlyout need to be used together.

    Derive from official document, if the control doesn't have a flyout property, you can use the FlyoutBase.AttachedFlyout attached property instead. When you do this, you also need to call the FlyoutBase.ShowAttachedFlyout method to show the flyout.

    So you can refer to the code like following.

    XAML:

    <Button Click="onMoreClicked">
        <FlyoutBase.AttachedFlyout>
              <Flyout>
                 <TextBlock Text="This is a flyout!"/>
              </Flyout>
        </FlyoutBase.AttachedFlyout>             
    </Button>
    

    Code behind:

    private void onMoreClicked(object sender, RoutedEventArgs e)
        {
            FrameworkElement element = sender as FrameworkElement;
            FlyoutBase.ShowAttachedFlyout(element);
        }
    

    Because the button has a flyout attribute, you can also write directly like following.

    <Button>
         <Button.Flyout >
             <Flyout>
                <TextBlock Text="This is a flyout!"/>
              </Flyout>
          </Button.Flyout>
    </Button>