ダイアログ ボックスの概要

通常、スタンドアロン アプリケーションにはメイン ウィンドウがあり、データを視覚的に表示し、データを対話的に操作する機能を公開するために使用されます。たとえば、ワード プロセッサ アプリケーションは、ドキュメントを視覚的に表示し、ドキュメントを対話的に操作するためのファイル管理機能やファイル編集機能を公開します。

非常に単純なアプリケーションを除き、通常のアプリケーションのライフサイクルの過程で、メイン ウィンドウは、ユーザーへの情報の表示、ユーザーからの情報の収集、またはこれらの両方を行うためのセカンダリ ウィンドウを表示する場合があります。セカンダリ ウィンドウは、ダイアログ ボックスと呼ばれ、モーダルおよびモードレスの 2 種類があります**。

モーダル ダイアログ ボックスは、タスクを完了するために必要な追加情報をユーザーに要求するために表示され、一般にそのダイアログ ボックスが開いている間は、ユーザーが別のウィンドウをアクティブにすることはできません**。たとえば、ユーザーがワード プロセッサでドキュメントを開く場合、開くファイルの名前を指定するためのダイアログ ボックスが表示されます。ユーザーが名前を指定するまではドキュメントを開くことができないため、このダイアログ ボックスは、ファイル名を指定してダイアログ ボックスを受け入れるか、(通常は [キャンセル] ボタンをクリックして) ダイアログ ボックスをキャンセルするかの二者択一をユーザーに求めます。

一方、モードレス ダイアログ ボックスでは、このダイアログ ボックスが開いている間、ユーザーが他のウィンドウをアクティブにすることができます**。たとえば、ユーザーがドキュメント内で特定の単語の出現箇所を検索する場合、メイン ウィンドウ上で、検索対象の単語の入力を求めるダイアログ ボックスが開きます。ただし、単語の検索中でもユーザーがドキュメントを編集することは可能なため、このダイアログ ボックスはモーダルである必要はありません。通常、モードレス ダイアログ ボックスは、[閉じる] ボタンをクリックすることで閉じられます****。

Windows Presentation Foundation (WPF) では、メッセージ ボックス、コモン ダイアログ ボックス、およびカスタム ダイアログ ボックスなど、複数の種類のダイアログ ボックスを作成できます。ここでは、それぞれのダイアログ ボックスの種類について説明します。各種類に対応するサンプルについては、「ダイアログ ボックスのサンプル」を参照してください。

このトピックには次のセクションが含まれています。

  • メッセージ ボックス
  • コモン ダイアログ ボックス
  • カスタム ダイアログ ボックス
  • 関連トピック

メッセージ ボックス

メッセージ ボックスは、情報を表示し、ユーザーに判断を求めるために使用できる単純なダイアログ ボックスです。情報を表示したうえで、ユーザーからの応答を求めるメッセージ ボックスを次の図に示します。

Word Processor dialog box

メッセージ ボックスを作成するには、MessageBox クラスを使用します。MessageBox を使用すると、次のコードを使用して、メッセージ ボックスのテキスト、タイトル、アイコン、およびボタンを構成できます。

// Configure the message box
string messageBoxText = "This document needs to be saved ... .";
string caption = "Word Processor";
MessageBoxButton button = MessageBoxButton.YesNoCancel;
MessageBoxImage icon = MessageBoxImage.Warning;

メッセージ ボックスを表示するには、static Show メソッドを呼び出します。

// Display message box
MessageBox.Show(messageBoxText, caption, button, icon);

ユーザーがクリックしたボタンを検出し、それに応じて対応するためには、メッセージ ボックスの結果を取得して処理します。

// Display message box
MessageBoxResult messageBoxResult = MessageBox.Show(messageBoxText, caption, button, icon);
// Process message box results
switch (messageBoxResult)
{
    case MessageBoxResult.Yes: // Save document and exit
        SaveDocument();
        break;
    case MessageBoxResult.No: // Exit without saving
        break;
    case MessageBoxResult.Cancel: // Don't exit
        e.Cancel = true;
        break;
}

MessageBox の重要な機能の 1 つは、部分信頼で実行されている XAML ブラウザ アプリケーション (XBAP) で表示できることです (「Windows Presentation Foundation のセキュリティ」を参照してください)。

メッセージ ボックスの使用の詳細については、MessageBox、「MessageBox のサンプル」または「ダイアログ ボックスのサンプル」を参照してください。

コモン ダイアログ ボックス

メッセージ ボックスは情報を表示し、ユーザーの判断を求めるうえで有用ですが、ほとんどのダイアログ ボックスでは通常、どのボタンがクリックされたかという情報にとどまらず、さらに多くの情報をユーザーから得る必要があります。

Windows は、ファイルを開く、保存する、印刷するためのダイアログ ボックスなど、すべてのアプリケーションに共通の各種のダイアログ ボックスを実装しています。これらは、すべてのアプリケーションで使用できるため、コモン ダイアログ ボックスと呼ばれます。つまり、コモン ダイアログ ボックスは、複数のアプリケーション間で一貫したユーザー エクスペリエンスを実現するうえで役立ちます。

Windows Presentation Foundation (WPF) では、ファイルを開く、保存する、印刷するためのコモン ダイアログ ボックスがマネージ クラスとしてカプセル化されており、これらをスタンドアロン アプリケーションで使用できます。ここでは、各ダイアログ ボックスについて簡単に説明します。

ファイルを開くダイアログ ボックス

ファイルを開くダイアログ ボックス (次の図を参照) は、ユーザーが開くファイルの名前を取得するために、ファイルを開く機能によって使用されます。

Open dialog box

ファイルを開くコモン ダイアログ ボックスは OpenFileDialog クラスとして実装されます。この種類のダイアログ ボックスを作成、構成、および表示し、結果を処理する方法を次のコード例に示します。

void OpenDocument()
{
    // Configure open file dialog box
    OpenFileDialog dlg = new OpenFileDialog();
    dlg.FileName = "Document"; // Default file name
    dlg.DefaultExt = ".wpf"; // Default file extension
    dlg.Filter = "Word Processor Files (.wpf)|*.wpf"; // Filter files by extension

    // Show open file dialog box
    Nullable<bool> result = dlg.ShowDialog();

    // Process open file dialog box results
    if (result == true)
    {
        // Open document
        string filename = dlg.FileName;
    }
}

ファイルを開くダイアログ ボックスの詳細については、Microsoft.Win32.OpenFileDialog を参照してください。

OpenFileDialog は、部分信頼で実行されているアプリケーションで安全にファイル名を取得するために使用できます (「Windows Presentation Foundation のセキュリティ」を参照してください)。具体的な方法については、「XBAP からの安全なファイルのアップロードのサンプル」を参照してください。

ファイルの保存ダイアログ ボックス

ファイルの保存ダイアログ ボックス (次の図を参照) は、ユーザーが保存するファイルの名前を取得するために、ファイルの保存機能によって使用されます。

Save As dialog box

ファイルの保存コモン ダイアログ ボックスは SaveFileDialog クラスとして実装されます。この種類のダイアログ ボックスを作成、構成、および表示し、結果を処理する方法を次のコード例に示します。

void SaveDocument()
{
    // Configure save file dialog box
    SaveFileDialog dlg = new SaveFileDialog();
    dlg.FileName = "Document"; // Default file name
    dlg.DefaultExt = ".wpf"; // Default file extension
    dlg.Filter = "Word Processor Files (.wpf)|*.wpf"; // Filter files by extension

    // Show save file dialog box
    Nullable<bool> result = dlg.ShowDialog();

    // Process save file dialog box results
    if (result == true)
    {
        // Save document
        string filename = dlg.FileName;
    }
}

ファイルの保存ダイアログ ボックスの詳細については、Microsoft.Win32.SaveFileDialog を参照してください。

印刷ダイアログ ボックス

印刷ダイアログ ボックス (次の図を参照) は、ユーザーがファイルの印刷に使用するプリンタを選択および構成するために、印刷機能によって使用されます。

Print dialog box

印刷コモン ダイアログ ボックスは PrintDialog クラスとして実装されます。この種類のダイアログ ボックスを作成、構成、および表示する方法を次のコード例に示します。

void PrintDocument()
{
    // Configure printer dialog box
    PrintDialog dlg = new PrintDialog();
    dlg.PageRangeSelection = PageRangeSelection.AllPages;
    dlg.UserPageRangeEnabled = true;

    // Show save file dialog box
    Nullable<bool> result = dlg.ShowDialog();

    // Process save file dialog box results
    if (result == true)
    {
        // Print document
    }
}

印刷ダイアログ ボックスの詳細については、System.Windows.Controls.PrintDialog を参照してください。WPF での印刷の詳細については、「印刷の概要」を参照してください。

カスタム ダイアログ ボックス

メッセージ ボックスよりも複雑で、コモン ダイアログ ボックスとして用意されていないダイアログ ボックスが必要な場合は、独自のダイアログ ボックスを作成する必要があります。WPF では、Window を使用して、モーダル ダイアログ ボックスとモードレス ダイアログ ボックスの両方を作成できます。

モーダル カスタム ダイアログ ボックスの作成

次の図に示されている MarginsDialogBox のようなモーダル ダイアログ ボックスには、特定の表示要件と動作があります。

Margins dialog box

ここでは、それらの要件および動作と、ダイアログ ボックスの実装の基本的な要素について説明します。

モーダル ダイアログ ボックスの構成

一般的なダイアログ ボックスのユーザー インターフェイスには、次のようなキーとなる動作がいくつかあります。

  • ユーザーがダイアログ ボックスを閉じ、処理を続行するためにクリックする Button ([OK])。このボタンは、IsDefault プロパティを true に設定する必要があります。これにより、ユーザーが Enter キーを押してダイアログ ボックスを受け入れることができるようになります。

  • ユーザーがダイアログ ボックスを閉じ、機能をキャンセルするためにクリックする Button ([キャンセル])。このボタンは、IsCancel プロパティを true に設定する必要があります。これにより、ユーザーが Esc キーを押してダイアログ ボックスをキャンセルできるようになります。

  • タイトル バーの閉じるボタンの表示。

  • アイコンの表示。

  • 最小化ボタン、最大化ボタン、および元のサイズに戻すボタンの表示。

  • ダイアログ ボックスを最小化、最大化、元に戻す、および閉じるためのシステム メニューの表示。

  • ダイアログ ボックスを開いたウィンドウの上および中央で開く。

  • ダイアログ ボックスは可能な場合はサイズを変更できる必要があり、ダイアログ ボックスが小さくなりすぎないように、および使用しやすい既定のサイズを提供するために、既定のサイズと最小サイズの両方をそれぞれ設定しておく必要があります。

  • 通常、ダイアログ ボックスにはタスク バー ボタンはありません。

ダイアログ ボックスのサンプル」の Margin ダイアログ ボックスのように、Window を使用してダイアログ ボックスを作成および構成できます。

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="MarginsDialogBox"
    xmlns:local="clr-namespace:DialogBoxSample"
    Title="Margins"
    Height="190" Width="300"
    MinHeight="190" MinWidth="300"
    ResizeMode="CanResizeWithGrip"
    ShowInTaskbar="False"
    WindowStartupLocation="CenterOwner" 
    FocusManager.FocusedElement="{Binding ElementName=leftMarginTextBox}">

  <Grid>

    <!-- Grid column and row definitions -->

    <Grid.Resources>
      <!-- Grid column and row definitions -->
      ...
    </Grid.Resources>

    <!-- Grid column and row definitions -->
    <Grid.ColumnDefinitions>
      <!-- Column definitions -->
      ...
    </Grid.ColumnDefinitions>

    <Grid.RowDefinitions>
      <!-- Row definitions -->
      ...
    </Grid.RowDefinitions>

    <!-- Left Margin -->
    <Label Grid.Column="0" Grid.Row="0">Left Margin:</Label>
    <TextBox Name="leftMarginTextBox" Grid.Column="1" Grid.Row="0">
    </TextBox>

    <!-- Top Margin -->
    <Label Grid.Column="0" Grid.Row="1">Top Margin:</Label>
    <TextBox Name="topMarginTextBox" Grid.Column="1" Grid.Row="1">
    </TextBox>

    <!-- Right Margin -->
    <Label Grid.Column="0" Grid.Row="2">Right Margin:</Label>
    <TextBox Name="rightMarginTextBox" Grid.Column="1" Grid.Row="2">
    </TextBox>

    <!-- Bottom Margin -->
    <Label Grid.Column="0" Grid.Row="3">Bottom Margin:</Label>
    <TextBox Name="bottomMarginTextBox" Grid.Column="1" Grid.Row="3">
    </TextBox>

    <!-- Accept or Cancel -->
    <StackPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="4">
      <Button Name="okButton" IsDefault="True">OK</Button>
      <Button Name="cancelButton" IsCancel="True">Cancel</Button>
    </StackPanel>

  </Grid >
</Window>

ダイアログ ボックスに関するユーザー エクスペリエンスは、メニュー バーにも及びます。ある機能がユーザー情報を収集するダイアログ ボックスを表示する場合、その機能を公開するメニュー項目には、次に示すようにヘッダーに省略記号が表示されます。

<Window ... >
  ...
    <MenuItem 
      Name="formatMarginsMenuItem" 
      Header="_Margins..." 
      Click="formatMarginsMenuItem_Click" />
  ...
</Window>

[バージョン情報] ダイアログ ボックスなど、情報のみを表示するダイアログ ボックスが開く場合、対応するメニュー項目に省略記号は不要です。

モーダル ダイアログ ボックスを開く

ダイアログ ボックスを表示するメニュー項目をユーザーが選択したときは、メッセージ ボックスおよびコモン ダイアログ ボックスの場合と同様に、そのダイアログ ボックスをインスタンス化および構成し、開く必要があります。

ダイアログ ボックスをインスタンス化する方法を次のコード例に示します。

public partial class MainWindow : Window
{
    ...
    void formatMarginsMenuItem_Click(object sender, RoutedEventArgs e)
    {
        // Instantiate the dialog box
        MarginsDialogBox dlg = new MarginsDialogBox();
    }
    ...
}

次に、ダイアログ ボックスを使用前に構成する必要があります。

public partial class MainWindow : Window
{
    ...
    void formatMarginsMenuItem_Click(object sender, RoutedEventArgs e)
    {
        // Instantiate the dialog box
        MarginsDialogBox dlg = new MarginsDialogBox();

        // Configure the dialog box
        dlg.Owner = this;
        dlg.DocumentMargin = this.documentTextBox.Margin;
    }
    ...
}

ここでは、このコードはダイアログ ボックスに既定の情報を渡しています。また、System.Windows.Window.Owner プロパティに、ダイアログ ボックスを表示しているウィンドウへの参照も設定しています。通常、すべてのダイアログ ボックスに共通する、ウィンドウの状態関連の動作を提供するには、必ずダイアログ ボックスの所有者を設定する必要があります (「Windows Presentation Foundation のウィンドウの概要」を参照してください)。

メモメモ :

ダイアログ ボックスでユーザー インターフェイス (UI) オートメーションをサポートするには、所有者を指定する必要があります (「UI オートメーションの概要」を参照してください)。

ダイアログ ボックスの構成が終わると、表示準備が整います。モーダル ダイアログ ボックスは、ShowDialog メソッドを呼び出すことによって表示されます。

public partial class MainWindow : Window
{
    ...
    void formatMarginsMenuItem_Click(object sender, RoutedEventArgs e)
    {
        // Instantiate the dialog box
        MarginsDialogBox dlg = new MarginsDialogBox();

        // Configure the dialog box
        dlg.Owner = this;
        dlg.DocumentMargin = this.documentTextBox.Margin;

        // Open the dialog box modally
        dlg.ShowDialog();

    }
    ...
}

ShowDialog はダイアログ ボックスをモーダル状態で開きます。その後、ユーザーはデータを入力してから、ダイアログ ボックスを受け入れるかキャンセルすることができます。

ユーザー指定のデータの検証

ダイアログ ボックスが開き、ユーザーがデータを入力する際、ダイアログ ボックスは、次の 3 つの理由から、ユーザーが入力しているデータが有効であることを確認する必要があります。

  • セキュリティ上の観点から、すべての入力を検証する必要があります。

  • アプリケーションの観点では、データを検証することで、誤入力データがコードで処理され、その結果例外がスローされる可能性を排除できます。

  • ユーザー エクペリエンスの観点では、入力データの中で間違っていたものを表示することによって、ユーザーにとっても役立ちます。

WPF でバインドされたコントロールを検証するには、検証規則を作成し、その規則を該当するバインディングに関連付ける必要があります。

検証規則は、ValidationRule から派生するカスタム クラスです。バインドされた値が double であり、指定した範囲内にあることを確認する MarginValidationRule を次の例に示します。

using System.Windows.Controls;
public class MarginValidationRule : ValidationRule
{
    double minMargin;
    double maxMargin;

    public double MinMargin
    {
        get { return this.minMargin; }
        set { this.minMargin = value; }
    }

    public double MaxMargin
    {
        get { return this.maxMargin; }
        set { this.maxMargin = value; }
    }

    public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
    {
        double margin;

        // Is a number?
        if (!double.TryParse((string)value, out margin))
        {
            return new ValidationResult(false, "Not a number.");
        }

        // Is in range?
        if ((margin < this.minMargin) || (margin > this.maxMargin ))
        {
            string msg = string.Format("Margin must be between {0} and {1}.", this.minMargin, this.maxMargin);
            return new ValidationResult(false, msg);
        }

        // Number is valid
        return new ValidationResult(true, null);
    }
}

バインドされた値を検証するには、前のコードに示すように、Validate をオーバーライドし、適切な ValidationResult を返します。

バインドされたコントロールに検証規則を関連付けるには、次のマークアップを使用します。

<Window ... >
    ...
    <!-- Left Margin -->
    <Label Grid.Column="0" Grid.Row="0">Left Margin:</Label>
    <TextBox Name="leftMarginTextBox" Grid.Column="1" Grid.Row="0">
      <TextBox.Text>
        <Binding Path="Left" UpdateSourceTrigger="PropertyChanged">
          <Binding.ValidationRules>
            <local:MarginValidationRule MinMargin="0" MaxMargin="10" />
          </Binding.ValidationRules>
        </Binding>
      </TextBox.Text>
    </TextBox>
    ...
</Window>

WPF は、バインドされたコントロールにデータが入力されると、このバインディングを自動的に適用し、既定では無効なコントロールの周りに赤い境界線を表示します。これを次の図に示します。

Invalid left margin

WPF では、有効なデータが入力されるまでユーザーを無効なコントロールに縛り付けることはありません。この動作はダイアログ ボックスに適しています。ユーザーは、入力したデータが有効かどうかに関係なく、ダイアログ ボックス内のコントロール群を自由に移動できる必要があります。ただし、これは、ユーザーが無効なデータを入力して [OK] ボタンを押すことができることを意味します。このため、ダイアログ ボックスが受け入れられる前に、コードですべてのコントロールを検証し、無効なデータを防ぐ必要があります。これは、[OK] ボタンの Click イベント ハンドラで行います。

public partial class MarginsDialogBox : Window
{
    ...
    void okButton_Click(object sender, RoutedEventArgs e)
    {
        // Don't accept the dialog box if there is invalid data
        if (!IsValid(this)) return;
        ...
    }
    ...
    // Validate all dependency objects in a window
    bool IsValid(DependencyObject node)
    {
        // Check if dependency object was passed
        if (node != null)
        {
            // Check if dependency object is valid.
            // NOTE: Validation.GetHasError works for controls that have validation rules attached 
            bool isValid = !Validation.GetHasError(node);
            if (!isValid)
            {
                // If the dependency object is invalid, and it can receive the focus,
                // set the focus
                if (node is IInputElement) Keyboard.Focus((IInputElement)node);
                return false;
            }
        }

        // If this dependency object is valid, check all child dependency objects
        foreach (object subnode in LogicalTreeHelper.GetChildren(node))
        {
            if (subnode is DependencyObject)
            {   
                // If a child dependency object is invalid, return false immediately,
                // otherwise keep checking
                if (IsValid((DependencyObject)subnode) == false) return false;
            }
        }

        // All dependency objects are valid
        return true;
    }
}

このコードは、ウィンドウ上のすべての依存関係オブジェクトを列挙します。無効なオブジェクトがある場合は (GetHasError によって返される値で判断)、無効なコントロールがフォーカスを取得し、IsValid が false を返し、ウィンドウが無効と見なされます。

ダイアログ ボックスが有効である場合は、安全に閉じ、制御を返すことができます。この場合は、まずダイアログの結果を設定します。

モーダル ダイアログ ボックスの結果の設定

ShowDialog を使用してダイアログ ボックスを開くのは、基本的にはメソッド呼び出しと似ています。呼び出し元コード内のコードは、ShowDialog から制御が返されるまで待機します。ShowDialog から制御が返されると、呼び出し元コードは、まずユーザーがダイアログ ボックスを受け入れたかキャンセルしたかを判断する必要があります。これによって、ダイアログ ボックスによって収集されたデータが適用されるかどうかが決定されます。ダイアログ ボックスは、ユーザーがそのダイアログ ボックスを受け入れたかキャンセルしたかを報告するために、ダイアログ ボックスの結果の値を返す必要があります。

ダイアログ ボックスが受け入れられた場合は、ダイアログ ボックスの結果として true を返す必要があります。これは [OK] ボタンがクリックされたときに DialogResult プロパティを設定することによって行います。

<Window ... >
    ...
    <!-- Accept or Cancel -->
    <StackPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="4">
      <Button Name="okButton" Click="okButton_Click" IsDefault="True">OK</Button>
      ...
    </StackPanel>
  </Grid >
</Window>
public partial class MarginsDialogBox : Window
{
    ...
    void okButton_Click(object sender, RoutedEventArgs e)
    {
        // Dialog box accepted
        this.DialogResult = true;
    }
    ...
}

DialogResult プロパティを設定すると、ウィンドウが自動的に閉じられるため、Close を明示的に呼び出す手間を省くことができます。

キャンセルされたダイアログ ボックスの結果は false にする必要があります。

<Window ... >
    ...
    <!-- Accept or Cancel -->
    <StackPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="4">
      ...
      <Button Name="cancelButton" Click="cancelButton_Click" IsCancel="True">Cancel</Button>
    </StackPanel>
  </Grid >
</Window>
public partial class MarginsDialogBox : Window
{
    ...
    void cancelButton_Click(object sender, RoutedEventArgs e)
    {
        // Dialog box canceled
        this.DialogResult = false;
    }
    ...
}

ただし、IsCancel プロパティが true に設定されているボタンがあり、ユーザーがそのボタンまたは Esc キーを押した場合は、DialogResult が自動的に false に設定されます。次のコードは、Click イベント ハンドラを使用せずに、前のコードと同じ効果を実現します。

<Window ... >
    ...
    <!-- Accept or Cancel -->
    <StackPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="4">
      ...
      <Button Name="cancelButton" IsCancel="True">Cancel</Button>
    </StackPanel>
  </Grid >
</Window>

ダイアログ ボックスは、ユーザーがタイトル バーの閉じるボタンを押すか、システム メニューの [閉じる] メニュー項目を選択すると、結果として自動的に true を返します。

モーダル ダイアログ ボックスから返されたデータの処理

DialogResult がダイアログ ボックスによって設定されると、呼び出し元コード側で、ShowDialog メソッドから制御が返されたときに、DialogResult プロパティを調べてそのダイアログ ボックスの結果を取得できます。

public partial class MainWindow : Window
{
    ...
    void formatMarginsMenuItem_Click(object sender, RoutedEventArgs e)
    {
        // Instantiate the dialog box
        MarginsDialogBox dlg = new MarginsDialogBox();

        // Configure the dialog box
        dlg.Owner = this;
        dlg.DocumentMargin = this.documentTextBox.Margin;

        // Open the dialog box modally 
        dlg.ShowDialog();

        // Process data entered by user if dialog box is accepted
        if (dlg.DialogResult == true)
        {
            // Update fonts
            this.documentTextBox.Margin = dlg.DocumentMargin;
        }
    }
    ...
}

ユーザーがダイアログ ボックスを受け入れた場合、呼び出し元のコードは、ダイアログ ボックスにユーザーが入力した値の取得および処理を開始します。

メモメモ :

ShowDialog から制御が返された後は、ダイアログ ボックスを再度開くことはできません。代わりに、新しいインスタンスを作成する必要があります。

ユーザーがダイアログ ボックスをキャンセルした場合は、呼び出し元のコードで、ユーザーが入力したデータを処理しないようにする必要があります。

モードレス カスタム ダイアログ ボックスの作成

次の図に示されている FindDialogBox のようなモードレス ダイアログ ボックスは、基本的な外観はモーダル ダイアログ ボックスと同じです。

Find dialog box

ただし、以下のトピックで説明するように、動作は若干異なります。

モードレス ダイアログ ボックスを開く

モードレス ダイアログ ボックスは Show メソッドを呼び出すことによって開かれます。

void editFindMenuItem_Click(object sender, RoutedEventArgs e)
{
    // Instantiate the dialog box
    FindDialogBox dlg = new FindDialogBox(this.documentTextBox.Text);

    // Open the dialog box modally
    dlg.Show();
}

ShowDialog を使用してダイアログ ボックスを開く場合とは異なり、Show はすぐに制御を返します。このため、呼び出し元のウィンドウは、モードレス ダイアログ ボックスが閉じられるタイミングを判別できません。したがって、ダイアログ ボックスの結果を確認したり、ダイアログ ボックスからデータを取得してさらに処理したりするタイミングも認識できません。ダイアログ ボックスは、呼び出し元のウィンドウにデータを返して処理を託すために、別の方法を用意する必要があります。

モードレス ダイアログ ボックスから返されたデータの処理

この例では、FindDialogBox は、頻度を特に指定せずに検索されているテキストに応じて、1 つ以上の検索結果をメイン ウィンドウに返す場合があります。モーダル ダイアログ ボックスと同様に、モードレス ダイアログ ボックスはプロパティを使用して結果を返すことができます。ただし、ダイアログ ボックスを所有しているウィンドウで、これらのプロパティを確認するタイミングを認識できる必要があります。これを実現する方法の 1 つは、ダイアログ ボックスにイベントを実装し、テキストが検出されるたびにダイアログ ボックスがこのイベントを発生させることです。FindDialogBox は、この目的で TextFoundEvent を実装しています。これには、まずデリゲートが必要です。

public delegate void TextFoundEventHandler(object sender, EventArgs e);

TextFoundEventHandler デリゲートを使用して、次のように FindDialogBoxTextFoundEvent を実装します。

public partial class FindDialogBox : Window
{
    ...
    public event TextFoundEventHandler TextFound;
    ...
    protected virtual void OnTextFound()
    {
        TextFoundEventHandler textFound = this.TextFound;
        if (textFound != null) textFound(this, EventArgs.Empty);
    }
}

これにより、検索結果が見つかったときに、このイベントを発生させることができます。

public partial class FindDialogBox : Window
{
    ...
    void findButton_Click(object sender, RoutedEventArgs e) {
        ...
        // Text found
        this.index = match.Index;
        this.length = match.Length;
        OnTextFound();
        ...
    }
    ...
}

次に、オーナー ウィンドウはこのイベントを登録し、処理する必要があります。

public partial class MainWindow : Window
{
    ...
    void dlg_TextFound(object sender, EventArgs e)
    {
        // Get the find dialog box that raised the event
        FindDialogBox dlg = (FindDialogBox)sender;

        // Get find results and select found text
        this.documentTextBox.Select(dlg.Index, dlg.Length);
        this.documentTextBox.Focus();
    }
}

モードレス ダイアログ ボックスを閉じる

DialogResult を設定する必要はないため、モードレス ダイアログ ボックスは、システムに用意されている次のような機能を使用して閉じることができます。

  • タイトル バーの閉じるボタンのクリック。

  • Alt + F4 キーの押し下げ。

  • システム メニューの [閉じる] の選択。

または、[キャンセル] ボタンがクリックされたときに、コードによって Close を呼び出すことができます。

public partial class FindDialogBox : Window
{
    ...
    void cancelButton_Click(object sender, RoutedEventArgs e)
    {
        // Close dialog box
        this.Close();
    }
}

参照

概念

ポップアップの概要

その他の技術情報

ダイアログ ボックスのサンプル
ウィザードのサンプル
ColorPicker カスタム コントロールのサンプル
フォント ダイアログ ボックスのデモ