防止 Flyout 动态打开

Posted

技术标签:

【中文标题】防止 Flyout 动态打开【英文标题】:Prevent Flyout opening dynamically 【发布时间】:2017-07-06 13:51:09 【问题描述】:

我正在使用 AppBarButton,并且基于一个条件,我想在 AppBarButton 单击时执行直接命令或显示浮出控件以进行额外输入,问题是如果浮出控件在 appbar 按钮中,则在单击按钮时它总是会打开。

我有什么方法可以决定在哪里打开 Flyout。

 <AppBarButton x:Uid="Accept" Label="Accept"
                      ToolTipService.ToolTip="Binding Label, RelativeSource=RelativeSource Mode=Self"
                      Icon="Accept"
                      Command="Binding AcceptAppBarCommand" 
                      behaviors:AppBarButtonBehavior.AllowFocusOnInteraction="True">
            <AppBarButton.Flyout>
                <Flyout Placement="Bottom" >
                    <StackPanel Width="200">
                        <PasswordBox Header="Enter password:"
                                     Password="Binding Path=Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged"/>
                        <Button Margin="0 5 0 0" Content="Accept"
                                Command="Binding AcceptCommand">
                        </Button>
                    </StackPanel>
                </Flyout>
            </AppBarButton.Flyout>
        </AppBarButton>

【问题讨论】:

【参考方案1】:

通常,如果控件派生自 Button 类,则会自动显示浮出控件:

当用户单击按钮时,附加到按钮的弹出按钮会自动打开。您无需处理任何事件即可打开弹出窗口。

如果您将弹出窗口添加到 Flyout 属性,通常会发生这种情况。如果您不这样做,则通过 FlyoutBase 附加弹出窗口或将其添加到资源中:

<AppBarButton x:Uid="Accept" Label="Accept"
              ToolTipService.ToolTip="Binding Label, RelativeSource=RelativeSource Mode=Self"
              Icon="Accept"
              Command="Binding AcceptAppBarCommand"
              Click="AppBarButton_Click"> <!-- for sample -->
    <FlyoutBase.AttachedFlyout>
        <Flyout Placement="Bottom" x:Key="myFlyout" >
            <StackPanel Width="200">
                <PasswordBox Header="Enter password:"
                             Password="Binding Path=Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged"/>
                <Button Margin="0 5 0 0" Content="Accept"
                        Command="Binding AcceptCommand">
                </Button>
            </StackPanel>
        </Flyout>
    </FlyoutBase.AttachedFlyout>
</AppBarButton>

并在需要时显示:

private void AppBarButton_Click(object sender, RoutedEventArgs e)

    // in command, click or anywhere else (in that change move to suitable resources)
    FlyoutBase.ShowAttachedFlyout(sender as FrameworkElement);

如果您正在寻找有关构建帮助器类/方法以使其对 MVVM 更友好的更多信息,请查看 at Macrominevra blog post、Depechie's post 和 Shawn Kendrot's。

【讨论】:

这个 Ans 可以工作,但它通过背后的代码解决问题,而不是通过 MVVM 模式。 @RahulSonone 甚至 MVVM 也需要一些代码。看看你的答案 - 你确定这是因为样式更改,我想它已经死了隐藏弹出(边框)的内容 - 然后它根本没有被显示。我已经编辑了答案并添加了一些链接,在 MVVM 的情况下您可能会发现它们很有用。 marcominerva.wordpress.com/2015/01/15/… 不错,我可以使用它,但目前风格对我来说还不错。【参考方案2】:

我通过风格找到了一种解决方法。

在资源中创建样式

<Page.Resources>

    <Style TargetType="FlyoutPresenter" x:Key="_hiddenFlyoutStyle">
        <Setter Property="Background" Value="Transparent" />
        <Setter Property="BorderBrush" Value="Transparent" />
        <Setter Property="BorderThickness" Value="0" />
        <Setter Property="Padding" Value="0" />
    </Style>

    <Style TargetType="Border" x:Key="_flyoutBorderStyle">
        <Setter Property="Background" Value="ThemeResource SystemControlBackgroundChromeMediumLowBrush"/>
        <Setter Property="BorderBrush" Value="ThemeResource SystemControlForegroundChromeHighBrush"/>
        <Setter Property="BorderThickness" Value="ThemeResource FlyoutBorderThemeThickness"/>
        <Setter Property="Padding" Value="ThemeResource FlyoutContentThemePadding"/>
        <Setter Property="MinWidth" Value="ThemeResource FlyoutThemeMinWidth"/>
        <Setter Property="MaxWidth" Value="ThemeResource FlyoutThemeMaxWidth"/>
        <Setter Property="MinHeight" Value="ThemeResource FlyoutThemeMinHeight"/>
        <Setter Property="MaxHeight" Value="ThemeResource FlyoutThemeMaxHeight"/>
        <Setter Property="ScrollViewer.HorizontalScrollMode" Value="Auto"/>
        <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
        <Setter Property="ScrollViewer.VerticalScrollMode" Value="Auto"/>
        <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
    </Style>
</Page.Resources>

将样式应用于浮出控件和边框。

<AppBarButton x:Uid="Accept" Label="Accept"
                      ToolTipService.ToolTip="Binding Label, RelativeSource=RelativeSource Mode=Self"
                      Icon="Accept"
                      Command="Binding AcceptAppBarCommand" 
                      behaviors:AppBarButtonBehavior.AllowFocusOnInteraction="True">
            <AppBarButton.Flyout>
                <Flyout Placement="Bottom" FlyoutPresenterStyle="StaticResource _hiddenFlyoutStyle">
                    <Border Visibility="Binding DisplayFlyout, Converter=StaticResource BooleanToVisibilityConverter" 
                            Style="StaticResource _flyoutBorderStyle">
                        <StackPanel Width="200">
                            <PasswordBox Header="Enter password:"
                                     Password="Binding Path=Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged"/>
                            <Button Margin="0 5 0 0" Content="Accept"
                                Command="Binding AcceptCommand">
                            </Button>
                        </StackPanel>
                    </Border>
                </Flyout>
            </AppBarButton.Flyout>
        </AppBarButton>

DisplayFlyout 是 viewmodel 中的 bool 属性,用于决定何时显示弹出窗口。

【讨论】:

marcominerva.wordpress.com/2015/01/15/…,这个也不错,附属性的帮助下。

以上是关于防止 Flyout 动态打开的主要内容,如果未能解决你的问题,请参考以下文章

从 Flyout XAML 内的按钮访问 Flyout

UWP Flyout浮动控件

从 UWP 中的自定义 ToolTip 和自定义 Flyout 类取消订阅事件

如何在 UWP 中结合 Flyout 和 MenuFlyout?

如何在WPF中使用Flyout?

切换到其他应用时不会触发 UWP Flyout 的关闭事件