MSDN : http://msdn2.microsoft.com/en-us/library/aa969773.aspx

Dialog Boxes Overview

일반적으로 독립 애플리케이션은 시각적인 데이터 및 데이터와 상호작용하기 위한 기능을 노출하는 메인 윈도를 가집니다. 예를 들어 워드 프로세서 애플리케이션은 문서를 시각화하고, 파일 관리 및 문서와 상호작용하기 위한 편집 기능을 노출합니다.

단순하지 않은 애플리케이션의 일반적인 라이프 사이클의 한 부분으로 메인 윈도는 사용자에게서 정보를 수집하거나 표시하기 위해 하나 이상의 이차적인 윈도를 사용자에게 보여줄 것입니다. 이차적인 윈도는 다이얼로그 박스(dialog boxes, ※역주 : 일반적으로 대화 상자라고 하지만 다이얼로그 박스로 그대로 사용하였습니다.)라고 알려져 있고, 모덜(modal)과 모덜리스(modeless)의 두가지 종류가 있습니다.

모덜 다이얼로그 박스는 사용자에게 작업을 완료하기 위해 필요한 추가적인 정보를 보여주거나 보통 그것이 열려 있는 동안 다른 윈도의 활성화를 막기 위해 사용됩니다. 예를 들어 사용자가 워드 프로세서에서 문서를 열고 싶다면, 애플리케이션은 사용자가 열기를 원하는 파일의 이름을 물을 것입니다. 사용자가 이름을 제공해주기 전까지는 문서를 열 수 없기 때문에 다이얼로그 박스는 사용자가 이름을 입력하여 다이얼로그 박스를 확인(accept)하거나 보통 Cancel 버튼을 눌러 다이얼로그 박스를 취소하기를 기다려야 합니다.

한편, 모덜리스 다이얼로그 박스는 그것이 열려있는 동안 다른 윈도의 활성화를 막지 않습니다. 예를 들어 사용자가 문서내에서 부분적인 단어의 존재를 찾고 싶을 때 메인 윈도는 사용자가 찾고 있는 단어를 묻는 다이얼로그 박스를 열 것입니다. 그러나, 단어를 찾는 것은 문서 편집을 막지 않으므로 모덜이 되어야 할 필요가 없습니다. 모덜리스 다이얼로그 박스는 보통 Close 버튼을 클릭하여 닫습니다.

WPF는 메시지 박스, 커먼(common) 다이얼로그 박스 및 사용자 정의 다이얼로그 박스와 같은 몇 가지 다이얼로그 박스의 종류를 만들 수 있게 해줍니다. 이 토픽은 각각에 대해 다루며, Dialog Box Sample은 해당 예제를 제공합니다.

이 토픽은 다음과 같은 섹션을 담고 있습니다.

메시지 박스

메시지 박스는 정보를 보여주거나 사용자가 결정을 할 수 있도록 하기 위해 사용되는 간단한 다이얼로그 박스입니다. 다음 그림은 정보를 표시하고 사용자로부터 응답을 유도하는 메시지 박스를 나타냅니다.
사용자 삽입 이미지

메시지 박스를 만들기 위해,
MessageBox 클래스를 사용합니다. MessageBox는 다음과 같은 코드를 사용하여 메시지 박스 내용, 제목, 아이콘 및 버튼들을 설정할 수 있게합니다.

C#
// 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 메소드를 호출해야 합니다.

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

사용자가 클릭한 버튼을 검출하고 그에 맞는 응답을 하기 위해, 다음과 같이 메시지 박스의 결과를 받고 처리할 수 있습니다.

C#
// 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의 기능은 부분적으로 신뢰(partial trust)된 상태에서 동작하는 XAML 브라우저 애플리케이션(XBAPs)에서도 보여줄 수 있다는 것입니다(WPF Security를 참고).

메시지 박스 사용에 관한 더 자세한 정보는 MessageBox, MessageBox Sample 또는 Dialog Box Sample에서 찾을 수 있습니다.

커먼 다이얼로그 박스

메시지 박스가 유용한 정보를 보여주고 사용자에게 선택을 제공하는 동안, 대부분의 다이얼로그 박스는 일반적으로 어떤 버튼이 눌렸는가 보다는 더 자세한 정보를 사용자로부터 수집할 필요가 있습니다.

윈도는 파일 열기, 파일 저장하기 및 인쇄하기와 같이 모든 애플리케이션에서 공통적인 다양한 다이얼로그 박스를 구현합니다. 이것은 모든 애플리케이션이 사용하므로 커먼 다이얼로그 박스로 알려져 있습니다. 따라서, 이것은 애플리케이션 간의 일관성 있는 사용자 경험을 제공하는데 도움이 됩니다.

WPF는 독립 애플리케이션에서 사용할 수 있도록 관리된 클래스로 공통 파일 열기, 파일 저장 및 인쇄 다이얼로그 박스를 캡슐화합니다. 이 토픽은 각각의 개관을 제공합니다.

파일 열기 다이얼로그
다음 그림에서 보여주는 것과 같은 파일 열기 다이얼로그 박스는 파일 열기 기능에서 사용자가 열기를 원하는 파일명을 얻기 위해 사용됩니다.
사용자 삽입 이미지

공통 파일 열기 다이얼로그 박스는 OpenFileDialog 클래스로 구현되고, 다음 코드는 어떻게 생성, 설정 및 보여주고, 어떻게 결과를 처리하는지를 보여줍니다.

C#
void OpenDocument()
{
    // 파일 열기 다이얼로그 박스를 설정
    OpenFileDialog dlg = new OpenFileDialog();
    dlg.FileName = "Document"; // 기본 파일명
    dlg.DefaultExt = ".wpf"; // 기본 확장자
    dlg.Filter = "Word Processor Files (.wpf)|*.wpf"; // 확장 파일 필터

    // 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는 부분적으로 신뢰되어 동작중인 애플리케이션에서 파일명을 안전하게 얻는데 사용할 수 있습니다(WPF Security를 참고). 예제는 Safe File Upload from an XBAP Sample을 참고합니다.

파일 저장 다이얼로그 박스
다음 그림에서 보여주는 것과 같은 파일 저장 다이얼로그 박스는 파일 저장 기능에서 사용자가 저장을 원하는 파일명을 얻기 위해 사용됩니다.
사용자 삽입 이미지

공통 파일 저장 다이얼로그 박스는 SaveFileDialog 클래스로 구현되고, 다음 코드는 어떻게 생성, 설정 및 보여주고, 어떻게 결과를 처리하는지를 보여줍니다.

C#
void SaveDocument()
{
    // 파일 저장 다이얼로그 박스 설정
    SaveFileDialog dlg = new SaveFileDialog();
    dlg.FileName = "Document"; // 기본 파일명
    dlg.DefaultExt = ".wpf"; // 기본 파일 확장자
    dlg.Filter = "Word Processor Files (.wpf)|*.wpf"; // 확장 파일 필터

    // 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를 참고합니다.

인쇄 다이얼로그 박스
다음 그림에서 보여주는 것과 같은 인쇄 다이얼로그 박스는 인쇄 기능에서 사용자가 출력을 원하는 파일에 대한 프린터 선택 및 설정을 위해 사용됩니다.
사용자 삽입 이미지

공통 인쇄 다이얼로그 박스는 PrintDialog 클래스로 구현되고, 다음 코드는 어떻게 생성, 설정 및 보여주는지를 보여줍니다.

C#
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에서 인쇄하기에 관한 자세한 논의는 Printing Overview를 참고합니다.

사용자 정의 다이얼로그 박스

메시지 박스보다 복잡하고, 커먼 다이얼로그 박스에 의해 지원되지 않는 다이얼로그 박스가 필요할 때, 직접 다이얼로그 박스를 만들 필요가 있습니다. WPF는 모덜과 모덜리스 다이얼로그 박스 모두 Window를 사용하여 만들 수 있게 합니다.

모덜 사용자 정의 다이얼로그 박스 만들기
MarginsDialogBox와 같은 모덜 다이얼로그 박스는 시각적인 요구사항과 동작의 세트를 가진 다음 그림에서 보여주고 있습니다.
사용자 삽입 이미지

이 토픽은 이를 설명하고 다이얼로그 박스 구현의 기본 구성요소를 제시합니다.

모덜 다이얼로그 박스 설정하기
전형적인 다이얼로그 박스를 위한 사용자 인터페이스는 다음과 같은 몇 가지 주요 동작을 가집니다.
  • 사용자가 다이얼로그 박스를 닫고 처리를 계속하기 위해(OK) 클릭할 Button. 이 버튼은 또한 자신의 IsDefault 속성을 true로 설정하기 위해 필요합니다. 이것은 사용자가 ENTER 키를 눌러 다이얼로그 박스를 확인(accept)할 수 있게 합니다.
  • 사용자가 다이얼로그 박스를 닫고 취소하는 기능을 위해(Cancel) 클릭할 Button. 이 버튼은 자신의 IsCancel 속성을 true로 설정하기 위해 필요합니다. 이것은 사용자가 ESC 키를 눌러 다이얼로그 박스를 취소할 수 있게 합니다.
  • 타이틀바에 Close 버튼 보여주기.
  • Icon 보여주기.
  • 최소화, 최대화 및 이전 크기로 버튼 보여주기.
  • 다이얼로그 박스의 시스템 메뉴에 최소화, 최대화, 이전 크기로 및 닫기 버튼 보여주기.
  • 다이얼로그 박스를 연 윈도의 한가운데에 열기.
  • 다이얼로그 박스는 너무 작게 되는 것을 막기 위해 가능하다면 크기 조절이 가능해야하며, 사용자에게 유용한 기본 크기를 제공하기 위해 기본적인 크기와 최소 크기를 각각 설정할 필요가 있습니다.
Dialog Box Sample에서와 같이 Margin 다이얼로그 박스 같은 Window를 사용한 설정을 가진 다이얼로그 박스를 만들 수 있습니다.

XAML
<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>

다이얼로그 박스를 위한 사용자 경험은 또한 메뉴바로 확장됩니다. (※역주 : 이 문장은 의미를 잘 모르겠습니다. When a function that shows a dialog box to collect user information, the menu item that exposes that function will have an ellipses in its header, as shown here: )
(※역주 : 원문에는 C#이라고 나와있지만 XAML 코드입니다.)

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

About 다이얼로그 박스처럼, 오직 정보만을 표시하는 다이얼로그 박스가 열렸을 때, 이에 대응하는 메뉴 아이템은 타원을 필요로하지 않습니다.

모덜 다이얼로그 박스 열기
사용자가 다이얼로그 박스를 보여주기 위해 메뉴 아이템을 선택하였을 때, 다이얼로그 박스는 다른 메시지 박스와 커먼 다이얼로그 박스처럼 인스턴스화 되고, 설정되고, 열려야 합니다.

다음 코드는 어떻게 다이얼로그 박스를 인스턴스화 하는지 보여줍니다.

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

다음으로, 다이얼로그 박스는 사용되기 전에 설정될 필요가 있습니다.

C#
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 속성을 다이얼로그 박스를 보여주는 윈도의 레퍼런스로 설정합니다. 일반적으로, 모든 다이얼로그 박스를 위한 공통적인 윈도 상태-관련(state-related) 동작(behavior)를 제공하기 위해 항상 다이얼로그 박스의 소유자를 설정해야 합니다(WPF Windows Overview 참고).

노트:
반드시 다이얼로그 박스를 위한 유저 인터페이스(UI) 자동화를 지원하는 소유자를 제공해야 합니다(UI Automation Overview 참고).

일단 다이얼로그 박스가 설정되면, 그것은 보여줄 준비가 된 것입니다. 모덜 다이얼로그 박스는 다음과 같이 ShowDialog 메소드를 호출하여 보여지게 됩니다.

C#
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는 다이얼로그 박스를 모덜로 열고, 그 후 사용자는 다이얼로그 박스를 확인(accept)하거나 취소(cancel)하기 전까지 데이터를 입력합니다.

사용자 제공 데이터 유효성 검사
일단 다이얼로그 박스가 열리고 사용자가 데이터를 입력하면, 다이얼로그 박스는 다음과 같은 세가지 이유로 사용자의 입력이 유효한지 여부를 확인할 책임이 있습니다.
  • 보안상의 관점에서, 모든 입력은 유효해야 합니다.
  • 애플리케이션의 관점에서, 데이터 유효성 검사는 잠재적으로 예외를 던질 수 있는 코드에 의한 처리로부터 잘못된 자료를 방지합니다.
  • 사용자 경험의 관점에서, 다이얼로그 박스는 어떤 데이터가 잘못 입력되었는지를 보여줌으로서 사용자를 도울 수 있습니다.
WPF에서 바운드된 컨트롤을 유효화하기 위해, 유효성 규칙(validation rule)을 만들고 그것을 바인딩과 연결시킬 필요가 있습니다.

유효성 규칙은 ValidationRule을 상속하는 사용자 정의 클래스입니다. 다음 예제는 바운드 값이 double이고 지정된 범위내에 있는지를 검사하는 MarginValidationRule을 보여줍니다.

C#
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를 반환해야 합니다.

유효성 규칙을 바운드 컨트롤과 연결하기 위해, 다음과 같은 마크업을 사용합니다.

XAML
<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는 데이터가 바운드 컨트롤로 입력되었을 때 자동으로 이 바인딩을 승인하고, 기본적으로 유효하지 않은 컨트롤 주위에 붉은 테두리를 보여줍니다. 이것은 다음 그림과 같습니다.
사용자 삽입 이미지

WPF는 사용자가 유효한 데이터를 입력할 때까지 유효하지 않은 컨트롤을 제한하지 않습니다. 이것은 사용자가 다이얼로그 박스에서 데이터가 유효하든 그렇지 않든 간에 자유롭게 컨트롤들을 이동할 수 있으므로 다이얼로그 박스를 위해 좋은 동작입니다. 그러나, 이것은 사용자가 유효하지 않은 데이터를 입력하고 OK 버튼을 누를 수 있다는 것을 의미합니다. 이런 이유로, 코드는 또한 유효하지 않은 데이터에 대한 보호를 위하여, 다이얼로그 박스가 승인되기 전에 모든 컨트롤을 유효화할 필요가 있습니다. 이것은 OK 버튼의 Click 이벤트 핸들러에서 할 수 있습니다.

C#
public partial class MarginsDialogBox : Window
{
    ...
    void okButton_Click(object sender, RoutedEventArgs e)
    {
        // 유효하지 않은 데이터가 있을 경우 다이얼로그 박스를 승인하지 말 것.
        if (!IsValid(this)) return;
        ...
    }
    ...
    // 윈도에 있는 모든 의존성있는 객체의 유효성 확인.
    bool IsValid(DependencyObject node)
    {
        // 객체가 있는지 확인.
        if (node != null)
        {
            // 객체가 유효한지 확인.
            // NOTE: Validation.GetHasError는 유효성 규칙이 붙은 컨트롤을 위해 동작합니다.
            bool isValid = !Validation.GetHasError(node);
            if (!isValid)
            {
                // 객체가 유효하지 않고, 포커스를 받을 수 있다면,
                // 포커스를 맞춤.
                if (node is IInputElement) Keyboard.Focus((IInputElement)node);
                return false;
            }
        }

        // 객체가 유효하다면, 모든 자식 객체를 확인.
        foreach (object subnode in LogicalTreeHelper.GetChildren(node))
        {
            if (subnode is DependencyObject)
            {  
                // 자식 객체가 유효하지 않다면 즉시 false를 반환하고,
                // 그렇지 않으면 검사를 계속함.
                if (IsValid((DependencyObject)subnode) == false) return false;
            }
        }

        // 모든 객체가 유효함.
        return true;
    }
}

이 코드는 윈도 상에서 의존성 있는 모든 객체들을 열거하며, GetHasError의 반환값이 하나라도 유효하지 않다면, 유효하지 않은 컨트롤에 포커스가 맞춰지고, IsValidfalse를 반환하며, 윈도는 유효하지 않다고 판단합니다.

일단 다이얼로그 박스가 유효화되면, 안전하게 닫고 반환할 수 있습니다. 이것은 다이얼로그 결과가 설정되었다는 것을 의미합니다.

모덜 다이얼로그 결과 설정하기
ShowDialog를 사용하여 다이얼로그 박스를 여는 것은 호출하는 코드에 있는 코드는 ShowDialog가 반환될 때까지 기다린다는 점에서 기본적으로 메소드 호출과 비슷합니다. ShowDialog가 반환되었을 때, 호출하는 코드는 사용자가 다이얼로그 박스에서 적용(apply)하여 수집한 데이터인지 아닌지 즉, 확인했는지 취소했는지를 결정할 필요가 있습니다. 사용자가 다이얼로그 박스를 확인했는지 취소했는지 보고하기 위해, 다이얼로그 박스는 반드시 다이얼로그 박스 결과값을 반환해야 합니다.

다이얼로그 박스가 확인되면, OK 버튼을 눌렀을 때 DialogResult 속성을 설정함으로써 획득되는 true의 다이얼로그 박스 결과를 반환해야 합니다.

XAML
<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>

C#
public partial class MarginsDialogBox : Window
{
    ...
    void okButton_Click(object sender, RoutedEventArgs e)
    {
        // Dialog box accepted
        this.DialogResult = true;
    }
    ...
}

DialogResult 속성을 설정하는 것은 또한 명시적으로 Close를 호출하지 않아도 윈도가 자동으로 닫히는 원인이 된다는 것을 유념하십시오.

취소된 다이얼로그 박스는 false의 다이얼로그 박스 결과를 가져야 합니다.

XAML
<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>

C#
public partial class MarginsDialogBox : Window
{
    ...
    void cancelButton_Click(object sender, RoutedEventArgs e)
    {
        // Dialog box canceled
        this.DialogResult = false;
    }
    ...
}

그러나 IsCancel 속성이 true로 설정되어 있는 버튼이 있고 사용자가 그 버튼이나 ESC키를 눌렀을 때는 DialogResult는 자동으로 false로 설정됩니다. 다음의 코드는 Click 이벤트 핸들러가 없이 전술한 코드와 같은 효과를 얻을 수 있습니다.

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

다이얼로그 박스는 사용자가 타이틀 바에 있는 Close 버튼을 누르거나 시스템 메뉴에서 Close 메뉴 아이템을 선택할 때 자동으로 true를 반환할 것입니다.

모덜 다이얼로그 박스에서 반환된 데이터 처리하기
DialogResult가 다이얼로그 박스에 의해 설정되면 호출하는 코드는 ShowDialog 메소드가 반환되었을 때 DialogResult 속성을 검사하여 다이얼로그 박스 결과를 얻을 수 있습니다.

C#
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와 같은 모덜리스 다이얼로그 박스는 모덜 다이얼로그 박스와 같은 기본 형태를 가집니다.
사용자 삽입 이미지

그러나 동작은 다음 토픽에서 설명되는 것처럼 약간 다릅니다.

모덜리스 다이얼로그 박스 열기
모덜리스 다이얼로그 박스는 Show 메소드를 호출함으로써 열립니다.

C#
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는 어떤 정해진 빈도 없이 검색된 텍스트에 따라 하나 또는 그 이상의 검색 결과를 메인 윈도에 반환할 것입니다. 모덜 다이얼로그 박스의 경우처럼 모덜리스 다이얼로그 박스는 속성을 사용하여 결과를 반환할 수 있습니다. 그러나 다이얼로그 박스를 소유한 윈도는 언제 그 속성을 검사해야 하는지 알 필요가 있습니다. 다이얼로그 박스가 이것을 가능하게 하는 한가지 방법은 언제든 텍스트가 발견되었을 때 발생하는 이벤트를 구현하는 것입니다. FindDialogBox는 이런 목적으로 딜리게이트를 최우선으로 요구하는 TextFoundEvent를 구현합니다.

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

TextFoundEventHandler 딜리게이트를 이용하여 FindDialogBox는 다음과 같이 TextFoundEvent를 구현합니다.

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

따라서 찾기는 검색 결과가 나오면 이벤트를 띄웁니다.

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

소유 윈도는 이 이벤트를 등록하고 처리할 필요가 있습니다.

C#
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가 설정될 필요가 없기 때문에 다음을 포함하는 시스템 제공 메커니즘을 사용하여 모덜리스 다이얼로그를 닫을 수 있습니다.
  • 타이틀 바의 Close 버튼을 클릭.
  • ALT+F4 누름.
  • System Menu | Close를 선택
또는 취소 버튼을 클릭하면 코드에서 Close를 호출할 수 있습니다.

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


See Also

Concepts
Popup Overview

Other Resources
Dialog Box Sample
Wizard Sample
ColorPicker Custom Control Sample
Font Dialog Box Demo
신고
Posted by gongdo


티스토리 툴바