Popup

ポップアップは、アプリ内の他の UI の上にコンテンツを表示します。 Microsoft.UI.Xaml.Controls.Primitives クラスは、 名前空間にある、そのコンテンツ用の汎用コンテナーです。 既定のビジュアル テンプレートがないため、コンテンツ、外観、およびそれを開閉するロジックを指定します。

Popup は低レベルの構成要素です。 WinUI には、ポップアップ、ダイアログ、ティーチング ヒント、ツールヒントなど、一般的な種類の一時的な UI のコントロールも用意されています。 これらのコントロールには、独自のスタイル設定、配置、および閉じる動作が含まれます。

開いているポップアップの横に

これは適切なコントロールですか?

より上位レベルのコントロールがシナリオに適している場合は、Popup を使用しないでください。 代わりに、次のコントロールを使用してください:

Scenario 状態
ユーザーがその外側をクリックしたときに閉じる UI で、アイテムに関連する情報を表示したり、入力を収集したりします。 Flyout
コマンドまたはオプションの一覧を表示します。 MenuFlyout
質問をしたり、続行する前にユーザーが応答する必要がある情報を表示したりします。 ContentDialog
新しい機能または重要な機能を、特定の要素を対象にする場合もしない場合も示します。 TeachingTip
ユーザーが要素の上にマウス ポインターを置くか、フォーカスを移動したときに、要素の簡単な説明を表示します。 ツールヒント

UI の上に浮動するカスタム コンテンツが必要で、これらのコントロールがニーズを満たしていない場合は、 Popup を使用します。 たとえば、自分でスタイルを設定して配置するオーバーレイとしてポップアップを使用できます。

ポップアップはモーダルではないので、ユーザーは背後にある UI を引き続き操作できます。 続行する前にユーザーが応答する必要がある場合は、 ContentDialog を使用します。

Recommendations

  • ポップアップ コンテンツに背景、境界線、丸い角を付けて、背後の UI から目立つようにします。 WinUI 3 ギャラリーのサンプルでは、 AcrylicBackgroundFillColorDefaultBrush、 SurfaceStrokeColorDefaultBrush、および OverlayCornerRadius リソースを使用します。 詳細については、Acrylic material と Popups の ThemeShadow を参照してください。
  • 簡易非表示を有効にしない場合は、ポップアップを閉じるボタンまたは別のコントロールを含めます。
  • ポップアップ コンテンツを簡潔に保ち、1 つのタスクに絞ります。

ポップアップを作成する

WinUI 3 ギャラリー アイコン WinUI 3 ギャラリー アプリには、WinUI コントロールと機能の対話型の例が含まれています。 Microsoft Store からアプリを取得するか、GitHub でソース コードを参照します。

ポップアップは、Child として設定した 1 つの要素をホストします。 通常、子要素はパネルまたはポップアップ コンテンツを定義する UserControl です。 ポップアップを表示するには、IsOpen を true に設定してください。 非表示にするには、 IsOpen を false に設定します。

この例は、WinUI 3 ギャラリーサンプルに基づいています。 ポップアップを開くボタンの横にポップアップを宣言し、ポップアップコンテンツにはポップアップを閉じるボタンが含まれます。

<Grid HorizontalAlignment="Left" VerticalAlignment="Top">
    <Button Content="Show popup" Click="ShowPopupClicked" />
    <Popup x:Name="StandardPopup" HorizontalOffset="200" VerticalOffset="0">
        <Grid MinWidth="240"
              Padding="16"
              Background="{ThemeResource AcrylicBackgroundFillColorDefaultBrush}"
              BorderBrush="{ThemeResource SurfaceStrokeColorDefaultBrush}"
              BorderThickness="1"
              CornerRadius="{StaticResource OverlayCornerRadius}">
            <StackPanel Spacing="8">
                <TextBlock FontSize="16" Text="Simple popup" />
                <Button Content="Close" Click="ClosePopupClicked" />
            </StackPanel>
        </Grid>
    </Popup>
</Grid>
// Opens the popup if it isn't already open.
private void ShowPopupClicked(object sender, RoutedEventArgs e)
{
    if (!StandardPopup.IsOpen)
    {
        StandardPopup.IsOpen = true;
    }
}

// Closes the popup when the user clicks the Close button inside it.
private void ClosePopupClicked(object sender, RoutedEventArgs e)
{
    if (StandardPopup.IsOpen)
    {
        StandardPopup.IsOpen = false;
    }
}

コードでポップアップを作成する

ビジュアル ツリーに追加せずに、コードでポップアップを作成することもできます。 XAML で宣言するか、ビジュアル ツリーのパネルに追加するポップアップは、その親要素から XamlRoot を取得します。 親を持たないポップアップには親がないため、開く前に XamlRoot プロパティを設定する必要があります。

private Popup? _popup;

private void ShowPopupFromCodeClicked(object sender, RoutedEventArgs e)
{
    _popup ??= new Popup
    {
        // PopupContent is a UserControl in your app that defines the popup content.
        Child = new PopupContent(),
        IsLightDismissEnabled = true,

        // Required because this popup isn't in the visual tree. Use the XamlRoot
        // of an element that's already loaded, such as the button that was clicked.
        XamlRoot = ((UIElement)sender).XamlRoot
    };

    _popup.IsOpen = true;
}

Important

WinUI 3 では、親要素も XamlRoot もないポップアップを開くと失敗します。 要素の XamlRoot は、要素がライブ ビジュアル ツリーに追加されるまで null のため、ページ コンストラクターではなく、既に読み込まれている要素から値を取得します。 Window クラスでは、this.Content.XamlRootを使用できます。 詳細については、ContentDialog、および Popup を参照してください。

Note

ビジュアル ツリーにないポップアップは、タッチ キーボードが表示されるときにそれ自体の位置が変更されないため、キーボードに隠れることがあります。 ポップアップにテキスト入力コントロール ( TextBoxなど) が含まれている場合は、XAML でポップアップを宣言するか、ビジュアル ツリーのパネルに追加します。

ライト ディスミスでポップアップを閉じる

既定では、コードで IsOpen を false に設定するまで、ポップアップは開いたままです。 IsLightDismissEnabled をtrueに設定して、ユーザーがポップアップの外側をクリックまたはタップしたとき、または Esc キーを押したときにポップアップを閉じます。 この動作はlight dismissと呼ばれます。

既定では、ライト ディスミス ポップアップの外側の領域は暗く表示されません。 暗くするには、 LightDismissOverlayMode を On に設定します。 IsLightDismissEnabledがfalseされている場合、このプロパティは無効です。

<Popup x:Name="LightDismissPopup"
       IsLightDismissEnabled="True"
       LightDismissOverlayMode="On">
    <Border Padding="16"
            Background="{ThemeResource AcrylicBackgroundFillColorDefaultBrush}"
            BorderBrush="{ThemeResource SurfaceStrokeColorDefaultBrush}"
            BorderThickness="1"
            CornerRadius="{StaticResource OverlayCornerRadius}">
        <TextBlock Text="Click outside this popup or press Esc to close it." />
    </Border>
</Popup>

ポップアップを配置する

ポップアップを配置するには、オフセットを使用するか、別の要素を基準にして配置します。

オフセットを使用する

HorizontalOffset と VerticalOffset は、ポップアップの位置をピクセル単位で設定します。 オフセットの基準となるポイントは、ポップアップに親があるかどうかによって異なります。

  • ビジュアル ツリー内のポップアップは、親のレイアウト内の自身の位置からオフセットされます。 たとえば、垂直方向の StackPanelでは、その位置はポップアップの前にある要素の下にあります。 最初の 例では、ポップアップはボタンと単一セルの Grid を共有するため、Gridの左上隅から右に 200 ピクセルの位置に表示されます。
  • コードで作成する親を持たないポップアップは、XAML ルートの左上隅 (通常はアプリ ウィンドウのコンテンツ領域) からオフセットされます。

要素の横にポップアップを配置する

特定の要素の横にポップアップを表示するには、PlacementTargetをその要素に設定します。 次に、DesiredPlacement を Auto の値 ( 以外、たとえば Bottom や RightEdgeAlignedTop など) に設定します。

ポップアップが開くと、フレームワークはターゲット要素を基準にして配置します。 ポップアップが優先位置に収まらない場合、フレームワークはポップアップをターゲットの反対側に移動します。 HorizontalOffset と VerticalOffset は引き続き適用され、ポップアップを計算された位置からずらします。

ActualPlacement は、ポップアップが表示される場所を報告します。 ActualPlacementChanged イベントは、ポップアップが開いている間にその値が変更されたときに発生します。

<StackPanel Spacing="8">
    <Button x:Name="DetailsButton" Content="Show details" Click="ShowDetailsClicked" />
    <TextBlock x:Name="PlacementStatus" />
    <Popup x:Name="DetailsPopup"
           PlacementTarget="{x:Bind DetailsButton}"
           DesiredPlacement="BottomEdgeAlignedLeft"
           IsLightDismissEnabled="True"
           ActualPlacementChanged="DetailsPopup_ActualPlacementChanged">
        <Border Padding="16"
                Background="{ThemeResource AcrylicBackgroundFillColorDefaultBrush}"
                BorderBrush="{ThemeResource SurfaceStrokeColorDefaultBrush}"
                BorderThickness="1"
                CornerRadius="{StaticResource OverlayCornerRadius}">
            <TextBlock Text="This popup appears below the button when there's room." />
        </Border>
    </Popup>
</StackPanel>
private void ShowDetailsClicked(object sender, RoutedEventArgs e)
{
    DetailsPopup.IsOpen = true;
}

private void DetailsPopup_ActualPlacementChanged(object sender, object e)
{
    // ActualPlacement differs from DesiredPlacement when the popup
    // doesn't fit in the preferred position.
    PlacementStatus.Text = $"Actual placement: {DetailsPopup.ActualPlacement}";
}

アプリ ウィンドウの外側にポップアップを表示する

既定では、ポップアップは XAML ルートの境界 (通常はアプリ ウィンドウのコンテンツ領域) に制限されます。 Windows アプリ SDK 1.4 以降では、ShouldConstrainToRootBounds を false に設定して、ポップアップがウィンドウの外に広がることができます。 たとえば、ポップアップが小さなウィンドウよりも大きい場合にこれを行うことができます。

ポップアップを初めて開く前に、 ShouldConstrainToRootBounds を設定します。 ポップアップを開いた後は変更できません。

<Popup x:Name="UnconstrainedPopup" ShouldConstrainToRootBounds="False">
    <!-- Popup content -->
</Popup>

ポップアップをアニメーション化する

ポップアップ コンテンツが表示されたときにアニメーション化するには、ChildTransitions コレクションにトランジションを追加します。 PopupThemeTransition は、ツールヒントのように表示されるポップイン UI などのアニメーションを提供します。

<Popup x:Name="AnimatedPopup" IsLightDismissEnabled="True">
    <Popup.ChildTransitions>
        <TransitionCollection>
            <PopupThemeTransition />
        </TransitionCollection>
    </Popup.ChildTransitions>
    <Border Padding="16"
            Background="{ThemeResource AcrylicBackgroundFillColorDefaultBrush}"
            BorderBrush="{ThemeResource SurfaceStrokeColorDefaultBrush}"
            BorderThickness="1"
            CornerRadius="{StaticResource OverlayCornerRadius}">
        <TextBlock Text="This content animates when the popup opens." />
    </Border>
</Popup>

代わりに、ストーリーボードの表示と非表示のアニメーションを制御するには、 PopInThemeAnimation と PopOutThemeAnimationを使用します。 詳細については、ポップアップの表示/非表示を参照してください。

ポップアップが開いたり閉じたりしたときに応答する

Opened イベントは、IsOpen が true に設定されたときに発生します。 Closed イベントは、IsOpen が false に設定されている場合に発生します(ポップアップがライト ディスミスによって閉じる場合を含む)。 ポップアップがどのように閉じても実行する必要がある処理には、Closed を使用します。 たとえば、WinUI 3 ギャラリーのサンプルでは、Closed を使用して、ポップアップが開いている間は無効になっている設定を再び有効にします。

どちらのイベントも EventHandler<object>を使用するため、ハンドラーは object sender 引数と object イベント引数を受け取ります。

<StackPanel Spacing="8">
    <TextBlock x:Name="StatusText" />
    <Popup x:Name="StatusPopup"
           IsLightDismissEnabled="True"
           Opened="StatusPopup_Opened"
           Closed="StatusPopup_Closed">
        <!-- Popup content -->
    </Popup>
</StackPanel>
private void StatusPopup_Opened(object sender, object e)
{
    StatusText.Text = "The popup is open.";
}

private void StatusPopup_Closed(object sender, object e)
{
    // Closed occurs for every close, including light dismiss.
    StatusText.Text = "The popup is closed.";
}

キーボード、フォーカス、アクセシビリティ

  • ライト ディスミスを有効にすると、ポップアップを開くとフォーカスが移動し、ポップアップを閉じると、前にフォーカスがあった要素にフォーカスが戻ります。 ユーザーは Esc キーを押してポップアップを閉じることもできます。
  • ライト ディスミスが有効になっていない場合、ポップアップは開いたときにフォーカスを移動しません。 ポップアップを開いた後、ポップアップ内の要素にフォーカスを移動し、キーボード ユーザーがアクセスできる 閉じる ボタンを含め、閉じた後にポップアップを開いた要素にフォーカスを戻します。
  • ポップアップでは、 KeyDown や PointerPressedなどのルーティング イベントは発生しません。 これらのイベントを処理するには、代わりにハンドラーをポップアップの子要素にアタッチします。
  • ポップアップ内の各対話型要素にアクセス可能な名前があることを確認します。 詳細については、「 キーボードアクセシビリティ 」および「 基本的なアクセシビリティ情報を公開する 」を参照してください。