Dialog boxes overview(대화 상자 개요)

독립 실행형 애플리케이션에는 일반적으로 애플리케이션이 작동하는 주 데이터를 표시하고 메뉴 모음, 도구 모음 및 상태 표시줄과 같은 UI(사용자 인터페이스) 메커니즘을 통해 데이터 처리 기능을 노출하는 주 창이 있습니다. 특수 애플리케이션에는 다음을 수행하는 추가 창이 표시될 수도 있습니다.

  • 사용자에게 특정 정보 표시.

  • 사용자로부터 정보 수집.

  • 정보 표시 및 수집.

이러한 유형의 창을 대화 상자라고 하며, 모달과 모덜리스의 두 가지 유형이 있습니다.

모달 대화 상자는 계속하려면 함수에 사용자의 추가 데이터가 필요한 경우에 함수에서 표시합니다. 함수가 작동하려면 모달 대화 상자를 통해 데이터를 수집해야 하기 때문에, 모달 대화 상자가 열려 있는 동안에는 사용자가 다른 창을 활성화할 수 없습니다. 대부분의 경우 모달 대화 상자를 사용하면 사용자가 모달 대화 상자에서 작업을 마쳤을 때 확인 또는 취소 단추를 눌러 신호를 보낼 수 있습니다. 확인 단추를 누르는 것은 사용자가 데이터를 입력했으며 계속해서 함수로 데이터를 처리하고 싶어한다는 뜻입니다. 취소 단추를 누르는 것은 사용자가 함수의 실행을 중지하고 싶어한다는 뜻입니다. 데이터를 열고, 저장하고, 인쇄하는 가장 일반적인 모달 대화 상자의 예가 나와 있습니다.

한편 모덜리스 대화 상자는 열려 있는 동안에도 사용자가 다른 창을 활성화할 수 있습니다. 예를 들어, 사용자가 문서에서 특정 단어를 찾으려고 할 때 주 창에서 사용자가 찾으려는 단어를 입력할 대화 상자를 열 때가 많습니다. 단어를 찾는다고 해서 사용자가 문서를 편집하지 못하게 되는 것은 아니기 때문에 대화 상자를 모덜로 설정할 필요가 없습니다. 모덜리스 대화 상자는 대화 상자를 닫을 수 있는 닫기 단추가 있으며, 단어 검색에서 조건과 일치하는 다음 단어를 찾는 다음 찾기 단추와 같이 특정 기능을 실행하는 추가 단추를 제공할 수도 있습니다.

WPF(Windows Presentation Foundation)를 사용하면 메시지 상자, 일반 대화 상자, 사용자 지정 대화 상자와 같은 몇 가지 유형의 대화 상자를 만들 수 있습니다. 이 항목에서는 각각에 대해 설명하고, 대화 상자 샘플에서는 해당되는 예를 제공합니다.

메시지 상자

메시지 상자는 텍스트 정보를 표시하고 사용자가 단추를 통해 결정할 수 있게 만드는 데 사용할 수 있는 대화 상자입니다. 다음 그림에는 텍스트 정보를 표시하고, 질문을 하고, 질문에 대답할 때 사용할 세 개의 단추를 사용자에게 제공하는 메시지 상자가 있습니다.

애플리케이션이 닫히기 전에 문서의 변경 내용을 저장할지 묻는Word 프로세서 대화 상자.

메시지 상자를 만들려면 MessageBox 클래스를 사용합니다. MessageBox를 사용하면 다음과 같은 코드를 사용하여 메시지 상자 텍스트, 제목, 아이콘, 단추를 구성할 수 있습니다.

// Configure the message box to be displayed
string messageBoxText = "Do you want to save changes?";
string caption = "Word Processor";
MessageBoxButton button = MessageBoxButton.YesNoCancel;
MessageBoxImage icon = MessageBoxImage.Warning;
' Configure the message box to be displayed
Dim messageBoxText As String = "Do you want to save changes?"
Dim caption As String = "Word Processor"
Dim button As MessageBoxButton = MessageBoxButton.YesNoCancel
Dim icon As MessageBoxImage = MessageBoxImage.Warning

메시지 상자를 표시하려면 다음 코드에서와 같이 staticShow 메서드를 호출합니다.

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

메시지 상자를 표시하는 코드로 사용자의 결정을 감지하고 처리해야 할 경우는(단추 누름) 다음 코드에서와 같이 코드를 통해 메시지 상자 결과를 검사할 수 있습니다.

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

// Process message box results
switch (result)
{
    case MessageBoxResult.Yes:
        // User pressed Yes button
        // ...
        break;
    case MessageBoxResult.No:
        // User pressed No button
        // ...
        break;
    case MessageBoxResult.Cancel:
        // User pressed Cancel button
        // ...
        break;
}
' Display message box
Dim result As MessageBoxResult = MessageBox.Show(messageBoxText, caption, button, icon)

' Process message box results
Select Case result
    Case MessageBoxResult.Yes
        ' User pressed Yes button
        ' ...
    Case MessageBoxResult.No
        ' User pressed No button
        ' ...
    Case MessageBoxResult.Cancel
        ' User pressed Cancel button
        ' ...
End Select

메시지 상자 사용에 대한 자세한 내용은 MessageBox, MessageBox 샘플대화 상자 샘플을 참조하세요.

MessageBox에서 단순한 대화 상자 사용자 경험을 제공할 수도 있지만, MessageBox를 사용할 때의 장점은 XBAP(XAML 브라우저 애플리케이션)와 같은 부분 신뢰 보안 샌드박스에서 실행되는 애플리케이션에서 표시할 수 있는 유일한 창 유형이라는 것입니다(보안 참조).

대부분의 대화 상자는 텍스트, 선택(확인란), 상호 배타적인 선택(라디오 단추), 목록 선택(목록 상자, 콤보 상자, 드롭다운 목록 상자)과 같이 메시지 상자의 결과보다 복잡한 데이터를 표시하고 수집합니다. WPF(Windows Presentation Foundation)에서는 이러한 경우에 몇 가지 일반적인 대화 상자를 제공하고 사용자가 직접 대화 상자를 만들 수 있게 하지만, 이러한 사용은 완전 신뢰로 실행하는 경우로만 제한됩니다.

일반 대화 상자

Windows에서는 파일을 열고, 파일을 저장하고, 인쇄하는 등의 용도로 사용되는 대화 상자를 비롯하여 모든 애플리케이션에서 공통되는, 다양한 재사용 가능 대화 상자를 구현합니다. 이러한 대화 상자는 운영 체제에서 구현되므로 운영 체제에서 실행되는 모든 애플리케이션에서 공유할 수 있어 사용자 경험의 일관성에 도움이 됩니다. 운영 체제에서 제공되는 대화 상자를 사용자가 한 애플리케이션에서 익히고 나면 다른 애플리케이션에서 대화 상자의 사용 방법을 다시 익힐 필요가 없습니다. 이러한 대화 상자는 모든 애플리케이션에서 사용할 수 있고 일관성 있는 사용자 경험에 도움이 되므로, 일반 대화 상자라고 합니다.

WPF(Windows Presentation Foundation)에서는 파일 열기, 파일 저장 및 인쇄 일반 대화 상자를 캡슐화하여 독립 실행형 애플리케이션에서 사용할 수 있는 관리되는 클래스로 노출합니다. 이 항목에서는 각각의 개요를 간략하게 제공합니다.

파일 열기 대화 상자

다음 그림에 표시된 파일 열기 대화 상자는 파일 열기 기능에서 열려는 파일의 이름을 검색할 때 사용됩니다.

파일을 검색할 위치를 보여주는 열기 대화 상자.

일반 파일 열기 대화 상자는 OpenFileDialog 클래스로 구현되며 Microsoft.Win32 네임스페이스에 있습니다. 다음 코드에서는 코드를 만들고 구성 및 표시하는 방법과 결과를 처리하는 방법을 보여 줍니다.

// Configure open file dialog box
Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
dlg.FileName = "Document"; // Default file name
dlg.DefaultExt = ".txt"; // Default file extension
dlg.Filter = "Text documents (.txt)|*.txt"; // 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;
}
' Configure open file dialog box
Dim dlg As New Microsoft.Win32.OpenFileDialog()
dlg.FileName = "Document" ' Default file name
dlg.DefaultExt = ".txt" ' Default file extension
dlg.Filter = "Text documents (.txt)|*.txt" ' Filter files by extension

' Show open file dialog box
Dim result? As Boolean = dlg.ShowDialog()

' Process open file dialog box results
If result = True Then
    ' Open document
    Dim filename As String = dlg.FileName
End If

파일 열기 대화 상자에 대한 자세한 내용은 Microsoft.Win32.OpenFileDialog를 참조하세요.

참고

OpenFileDialog를 사용하면 부분 신뢰로 실행하는 애플리케이션에서 파일 이름을 안전하게 검색할 수 있습니다(보안 참조).

파일 저장 대화 상자

다음 그림에 표시된 파일 저장 대화 상자는 파일 저장 기능에서 저장하려는 파일의 이름을 검색할 때 사용됩니다.

파일을 검색할 위치를 보여주는 다른 이름으로 저장 대화 상자.

일반 파일 저장 대화 상자는 SaveFileDialog 클래스로 구현되며 Microsoft.Win32 네임스페이스에 있습니다. 다음 코드에서는 코드를 만들고 구성 및 표시하는 방법과 결과를 처리하는 방법을 보여 줍니다.

// Configure save file dialog box
Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog();
dlg.FileName = "Document"; // Default file name
dlg.DefaultExt = ".txt"; // Default file extension
dlg.Filter = "Text documents (.txt)|*.txt"; // 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;
}
' Configure save file dialog box
Dim dlg As New Microsoft.Win32.SaveFileDialog()
dlg.FileName = "Document" ' Default file name
dlg.DefaultExt = ".txt" ' Default file extension
dlg.Filter = "Text documents (.txt)|*.txt" ' Filter files by extension

' Show save file dialog box
Dim result? As Boolean = dlg.ShowDialog()

' Process save file dialog box results
If result = True Then
    ' Save document
    Dim filename As String = dlg.FileName
End If

파일 저장 대화 상자에 대한 자세한 내용은 Microsoft.Win32.SaveFileDialog를 참조하세요.

다음 그림에 표시된 인쇄 대화 상자는 인쇄 기능에서 사용자가 데이터를 인쇄할 프린터를 선택하고 구성할 때 사용됩니다.

인쇄 대화 상자를 보여주는 스크린샷.

일반 인쇄 대화 상자는 PrintDialog 클래스로 구현되며 System.Windows.Controls 네임스페이스에 있습니다. 다음 코드에서는 만들고, 구성하고, 표시하는 방법을 보여 줍니다.

// Configure printer dialog box
System.Windows.Controls.PrintDialog dlg = new System.Windows.Controls.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
}
' Configure printer dialog box
Dim dlg As New PrintDialog()
dlg.PageRangeSelection = PageRangeSelection.AllPages
dlg.UserPageRangeEnabled = True

' Show save file dialog box
Dim result? As Boolean = dlg.ShowDialog()

' Process save file dialog box results
If result = True Then
    ' Print document
End If

인쇄 대화 상자에 대한 자세한 내용은 System.Windows.Controls.PrintDialog를 참조하세요. WPF에서의 인쇄에 대한 자세한 내용은 인쇄 개요를 참조하세요.

사용자 지정 대화 상자

일반 대화 상자는 유용하며 가능한 경우 사용하는 편이 좋지만, 도메인별 대화 상자의 요구 사항은 지원하지 않습니다. 이러한 경우 사용자가 직접 대화 상자를 만들어야 합니다. 살펴보겠지만, 대화 상자는 특별한 동작이 있는 창입니다. Window는 그와 같은 동작을 구현하며, 그 뒤로는 사용자가 Window를 사용하여 사용자 지정 모달 및 모덜리스 대화 상자를 만듭니다.

모달 사용자 지정 대화 상자 만들기

이 항목에서는 Window를 사용하여 일반적인 모달 대화 상자 구현을 만드는 방법을 보여 주며, 예로는 Margins 대화 상자를 사용합니다(대화 상자 샘플 참조). Margins 대화 상자는 다음 그림에 나와 있습니다.

왼쪽 여백, 상단 여백, 오른쪽 여백, 아래 여백을 정의하기 위한 필트가 있는 여백 대화 상자.

모달 대화 상자 구성

일반 대화 상자의 사용자 인터페이스에는 다음이 포함됩니다.

  • 원하는 데이터를 수집하는 데 필요한 다양한 컨트롤.

  • 사용자가 클릭하여 대화 상자를 닫고, 함수로 돌아가고, 처리를 계속할 수 있게 만들어 주는 확인 단추입니다.

  • 사용자가 클릭하여 대화 상자를 취소하고 함수의 처리를 중단할 수 있게 만들어 주는 취소 단추입니다.

  • 제목 표시줄에 닫기 단추입니다.

  • 아이콘.

  • 최소화, 최대화복원 단추.

  • 대화 상자를 최소화, 최대화, 복원하고 닫을 수 있게 해 주는 시스템 메뉴입니다.

  • 대화 상자를 열 창의 위와 중앙에 있는 위치입니다.

  • 대화 상자가 너무 작아지는 것을 방지하고 사용자에게 유용한 기본 크기를 제공하기 위해 가능한 경우 크기를 조정할 수 있는 기능입니다. 이렇게 하려면 기본 차원과 최소 차원을 모두 설정해야 합니다.

  • ESC 키는 취소 단추를 누르는 하는 바로 가기 키입니다. 취소 단추의 IsCancel 속성을 true로 설정하여 이 작업을 수행합니다.

  • 확인 단추를 누르는 하는 바로 가기 키인 ENTER(또는 RETURN) 키입니다. 확인 단추 trueIsDefault 속성을 설정하여 이 작업을 수행합니다.

다음 코드에서는 이 구성을 보여 줍니다.

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

  <Grid>
    <!-- Accept or Cancel -->
    <StackPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="4">
      <Button Name="okButton" Click="okButton_Click" IsDefault="True">OK</Button>
      <Button Name="cancelButton" IsCancel="True">Cancel</Button>
    </StackPanel>
  </Grid >
</Window>
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace SDKSample
{
    public partial class MarginsDialogBox : Window
    {
        public MarginsDialogBox()
        {
            InitializeComponent();
        }
    }
}
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Input

Namespace SDKSample
    Public Class MarginsDialogBox
        Inherits Window

        Public Sub New()
            Me.InitializeComponent()
        End Sub
    End Class
End Namespace

대화 상자의 사용자 경험은 대화 상자를 여는 창의 메뉴 모음으로 확장됩니다. 메뉴 항목에서 함수를 계속하기 전에 대화 상자를 통한 사용자 상호 작용을 필요로 하는 함수를 실행하면, 함수의 메뉴 항목 헤더에 다음과 같이 줄임표가 표시됩니다.

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

메뉴 항목에서 [정보] 대화 상자와 같이 사용자 상호 작용이 필요하지 않은 대화 상자를 표시하는 함수를 실행할 경우는 줄임표가 필요하지 않습니다.

모달 대화 상자 열기

대화 상자는 일반적으로 워드 프로세서에서 문서 여백을 설정하는 경우와 같이 사용자가 메뉴 항목을 선택하여 도메인 관련 함수를 수행할 때 표시됩니다. 추가 창을 대화 상자로 표시하는 것은 일반 창을 표시하는 것과 비슷하지만, 추가로 대화 상자 관련 구성이 필요합니다. 대화 상자를 인스턴스화하고, 구성하고, 여는 과정 전체가 다음 코드에 표시되어 있습니다.

using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Win32;

namespace SDKSample
{
    public partial class MainWindow : Window
    {
        bool needsToBeSaved;
        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();
        }
    }
}
Imports System.ComponentModel
Imports System.Windows
Imports System.Windows.Controls
Imports Microsoft.Win32

Namespace SDKSample
    Public Class MainWindow
        Inherits Window
        
        Private Sub formatMarginsMenuItem_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
            ' Instantiate the dialog box
            Dim dlg As New MarginsDialogBox

            ' Configure the dialog box
            dlg.Owner = Me
            dlg.DocumentMargin = Me.documentTextBox.Margin

            ' Open the dialog box modally 
            dlg.ShowDialog()
        End Sub
    End Class
End Namespace

여기에서 코드는 대화 상자로 기본 정보(현재 여백)를 전달합니다. 또한 대화 상자를 표시하는 창에 대한 참조를 사용하여 Window.Owner 속성을 설정합니다. 일반적으로 항상 대화 상자의 소유자가 모든 대화 상자에서 공통적인 창 상태 관련 동작을 제공하도록 설정해야 합니다(자세한 내용은 WPF 창 개요 참조).

참고

대화 상자의 UI(사용자 인터페이스) 자동화를 지원하려면 소유자를 제공해야 합니다(UI 자동화 개요 참조).

대화 상자가 구성된 후 ShowDialog 메서드를 호출하여 모달로 표시됩니다.

사용자가 제공한 데이터의 유효성 검사

대화 상자가 열리고 사용자가 필요한 데이터를 제공할 때, 다음과 같은 이유로 대화 상자에서 제공된 데이터가 유효한지 확인해야 합니다.

  • 보안 관점에서, 모든 입력이 유효해야 합니다.

  • 도메인 관련 관점에서, 데이터의 유효성을 검사하면 코드에서 잘못된 데이터를 처리하여 예외를 일으키는 것을 방지할 수 있습니다.

  • 사용자 경험 관점에서, 대화 상자는 사용자가 입력한 데이터 중에 어느 것이 유효한지 표시하여 사용자를 도울 수 있습니다.

  • 성능 관점에서, 다중 계층 애플리케이션의 데이터 유효성 검사를 수행하면 클라이언트와 애플리케이션 계층 사이의 왕복 횟수를 줄일 수 있으며 특히 애플리케이션이 웹 서비스나 서버 기반 데이터베이스로 구성된 경우에 효과가 좋습니다.

WPF에서 바인딩된 컨트롤의 유효성을 검사하려면 유효성 검사 규칙을 정의하고 바인딩과 연결해야 합니다. 유효성 검사 규칙은 ValidationRule에서 파생되는 사용자 지정 클래스입니다. 다음 예제에서는 바인딩 값이 Double이며 지정된 범위에 있는지 확인하는 유효성 검사 규칙 MarginValidationRule을 보여 줍니다.

using System.Globalization;
using System.Windows.Controls;

namespace SDKSample
{
    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, 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);
        }
    }
}
Imports System.Globalization
Imports System.Windows.Controls

Namespace SDKSample
    Public Class MarginValidationRule
        Inherits ValidationRule

        Private _maxMargin As Double
        Private _minMargin As Double

        Public Property MaxMargin() As Double
            Get
                Return Me._maxMargin
            End Get
            Set(ByVal value As Double)
                Me._maxMargin = value
            End Set
        End Property

        Public Property MinMargin() As Double
            Get
                Return Me._minMargin
            End Get
            Set(ByVal value As Double)
                Me._minMargin = value
            End Set
        End Property

        Public Overrides Function Validate(ByVal value As Object, ByVal cultureInfo As CultureInfo) As ValidationResult
            Dim margin As Double

            ' Is a number?
            If Not Double.TryParse(CStr(value), margin) Then
                Return New ValidationResult(False, "Not a number.")
            End If

            ' Is in range?
            If ((margin < Me.MinMargin) OrElse (margin > Me.MaxMargin)) Then
                Dim msg As String = String.Format("Margin must be between {0} and {1}.", Me.MinMargin, Me.MaxMargin)
                Return New ValidationResult(False, msg)
            End If

            ' Number is valid
            Return New ValidationResult(True, Nothing)
        End Function
    End Class
End Namespace

이 코드에서는 데이터를 유효성 검사한 후 적절한 ValidationResult를 반환하는 Validate 메서드를 재정의하여 유효성 검사 규칙의 유효성 검사 논리를 구현합니다.

유효성 검사 규칙을 바인딩 컨트롤과 연결하려면 다음과 같은 표시를 사용합니다.

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

  <Grid>

    <!-- 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>
  </Grid >
</Window>

유효성 검사 규칙을 연결하고 나면 바인딩 컨트롤에 데이터가 입력될 때 WPF에서 자동으로 규칙을 적용합니다. 컨트롤에 잘못된 데이터가 포함되어 있으면 WPF에서는 다음 그림과 같이 잘못된 컨트롤 주위에 빨간색 테두리를 표시합니다.

잘못된 왼쪽 여백 값 주위에 빨간색 테두리가 있는 여백 대화 상자.

WPF에서는 사용자가 유효한 데이터를 입력할 때까지 사용자를 잘못된 데이터로 제한하지 않습니다. 대화 상자에서 좋은 동작입니다. 사용자는 데이터의 유효성에 관계없이 대화 상자에서 컨트롤을 자유롭게 탐색할 수 있어야 합니다. 한편, 그러면 사용자가 잘못된 데이터를 입력하고 확인 단추를 누를 수도 있습니다. 이러한 이유로 Click 이벤트를 처리하여 확인 단추가 눌렸을 때 대화 상자에서 모든 컨트롤의 유효성을 검사할 필요도 있습니다.

using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace SDKSample
{
    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;
        }
    }
}
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Input

Namespace SDKSample
    Public Class MarginsDialogBox
        Inherits Window

        Private Sub okButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
            ' Don't accept the dialog box if there is invalid data
            If Not Me.IsValid(Me) Then Return
        End Sub

        ' Validate all dependency objects in a window
        Private Function IsValid(ByVal node As DependencyObject) As Boolean
            ' Check if dependency object was passed and if dependency object is valid.
            ' NOTE: Validation.GetHasError works for controls that have validation rules attached 
            If ((Not node Is Nothing) AndAlso Validation.GetHasError(node)) Then
                ' If the dependency object is invalid, and it can receive the focus,
                ' set the focus
                If TypeOf node Is IInputElement Then
                    Keyboard.Focus(DirectCast(node, IInputElement))
                End If
                Return False
            End If

            ' If this dependency object is valid, check all child dependency objects
            Dim subnode As Object
            For Each subnode In LogicalTreeHelper.GetChildren(node)
                If (TypeOf subnode Is DependencyObject AndAlso Not Me.IsValid(DirectCast(subnode, DependencyObject))) Then
                    ' If a child dependency object is invalid, return false immediately,
                    ' otherwise keep checking
                    Return False
                End If
            Next

            ' All dependency objects are valid
            Return True
        End Function
    End Class
End Namespace

이 코드를 실행하면 창에서 모든 종속성 개체를 열거하고 잘못된 것이 있으면(GetHasError에서 반환) 잘못된 컨트롤러 포커스를 옮긴 후 IsValid 메서드에서 false를 반환하고 창이 잘못된 것으로 간주합니다.

대화 상자가 유효하면 안전하게 닫고 반환할 수 있습니다. 반환 과정의 일부로서 결과를 호출 함수에 반환해야 합니다.

모달 대화 상자 결과 설정

ShowDialog를 사용하여 대화 상자를 여는 것은 기본적으로 메서드를 호출하는 것과 같습니다. ShowDialog를 사용하여 대화 상자를 연 코드는 ShowDialog가 반환될 때까지 기다립니다. ShowDialog가 반환되면 사용자가 확인 단추와 취소 단추 중에 어느 것을 눌렀는지에 따라 호출한 코드에서 처리를 계속할지 중지할지 결정합니다. 이 결정을 용이하게 하기 위해, 대화 상자에서는 사용자의 선택을 ShowDialog 메서드에서 반환된 Boolean 값으로 반환해야 합니다.

확인 단추를 클릭하면 ShowDialogtrue를 반환해야 합니다. 이를 위해 확인 단추가 클릭되었을 때 대화 상자의 DialogResult 속성을 설정합니다.

using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace SDKSample
{
    public partial class MarginsDialogBox : Window
    {

        void okButton_Click(object sender, RoutedEventArgs e)
        {
            this.DialogResult = true;
        }
    }
}
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Input

Namespace SDKSample
    Public Class MarginsDialogBox
        Inherits Window

        Private Sub okButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
            ' Dialog box accepted
            MyBase.DialogResult = New Nullable(Of Boolean)(True)
        End Sub
    End Class
End Namespace

DialogResult 속성을 설정하면 창도 자동으로 닫히므로 명시적으로 Close를 호출할 필요가 없습니다.

취소 단추를 클릭하면 ShowDialog에서 false를 반환해야 하며 이를 위해서는 DialogResult 속성을 설정해야 합니다.

using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace SDKSample
{
    public partial class MarginsDialogBox : Window
    {

        void cancelButton_Click(object sender, RoutedEventArgs e)
        {
            // Dialog box canceled
            this.DialogResult = false;
        }
    }
}
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Input

Namespace SDKSample
    Public Class MarginsDialogBox
        Inherits Window

        Private Sub cancelButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
            ' Dialog box canceled
            Me.DialogResult = False
        End Sub
    End Class
End Namespace

단추의 IsCancel 속성이 true로 설정되어 있고 사용자가 취소 단추나 ESC 키를 누르면 DialogResult가 자동으로 false로 설정됩니다. 다음 표시는 Click 이벤트를 처리할 필요 없이 전의 코드와 같은 효과를 발휘합니다.

<Button Name="cancelButton" IsCancel="True">Cancel</Button>

사용자가 제목 표시줄에서 닫기 단추를 누르거나 시스템 메뉴에서 닫기 메뉴 항목을 선택하면 대화 상자에서 자동으로 false를 반환합니다.

모달 대화 상자에서 반환된 데이터 처리

대화 상자에서 DialogResult가 설정되면 대화 상자를 연 함수에서 DialogResult가 반환될 때 ShowDialog 속성을 검사하여 대화 상자의 결과를 얻을 수 있습니다.

using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Win32;

namespace SDKSample
{
    public partial class MainWindow : Window
    {

        void formatMarginsMenuItem_Click(object sender, RoutedEventArgs e)
        {

            // Process data entered by user if dialog box is accepted
            if (dlg.DialogResult == true)
            {
                // Update fonts
                this.documentTextBox.Margin = dlg.DocumentMargin;
            }
        }
    }
}
Imports System.ComponentModel
Imports System.Windows
Imports System.Windows.Controls
Imports Microsoft.Win32

Namespace SDKSample
    Public Class MainWindow
        Inherits Window
        
        Private Sub formatMarginsMenuItem_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
            ' Process data entered by user if dialog box is accepted
            If (dlg.DialogResult.GetValueOrDefault = True) Then
                Me.documentTextBox.Margin = dlg.DocumentMargin
            End If
        End Sub
    End Class
End Namespace

대화 상자의 결과가 true이면 함수에서 그 결과를 검색 신호로 사용하여 사용자가 제공한 데이터를 검색하고 처리합니다.

참고

ShowDialog가 반환된 후에는 대화 상자를 다시 열 수 없습니다. 대신 새 인스턴스를 만들어야 합니다.

대화 상자의 결과가 false이면 함수에서 적절하게 처리를 끝내야 합니다.

모덜리스 사용자 지정 대화 상자 만들기

다음 그림의 찾기 대화 상자와 같은 모덜리스 대화 상자는 기본적인 모양이 모덜 대화 상자와 같습니다.

찾기 대화 상자를 보여주는 스크린샷.

그러나 다음 섹션에 설명된 것처럼 동작은 약간 다릅니다.

모덜리스 대화 상자 열기

모덜리스 대화 상자는 Show 메서드를 호출해서 엽니다.

<!--Main Window-->
<MenuItem Name="editFindMenuItem" Header="_Find" InputGestureText="Ctrl+F" Click="editFindMenuItem_Click" />
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Win32;

namespace SDKSample
{
    public partial class MainWindow : Window
    {
        void editFindMenuItem_Click(object sender, RoutedEventArgs e)
        {
            // Instantiate the dialog box
            FindDialogBox dlg = new FindDialogBox(this.documentTextBox);

            // Configure the dialog box
            dlg.Owner = this;
            dlg.TextFound += new TextFoundEventHandler(dlg_TextFound);

            // Open the dialog box modally
            dlg.Show();
        }
    }
}
Imports System.ComponentModel
Imports System.Windows
Imports System.Windows.Controls
Imports Microsoft.Win32

Namespace SDKSample
    Public Class MainWindow
        Inherits Window
        
        Private Sub editFindMenuItem_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
            Dim dlg As New FindDialogBox(Me.documentTextBox)
            dlg.Owner = Me
            AddHandler dlg.TextFound, New TextFoundEventHandler(AddressOf Me.dlg_TextFound)
            dlg.Show()
        End Sub
    End Class
End Namespace

ShowDialog와 달리 Show는 즉시 반환합니다. 따라서 호출하는 창에서는 모덜리스 대화 상자가 닫히는 시기를 알 수 없기 때문에 대화 상자의 결과를 검사하거나 대화 상자에서 더 처리할 데이터를 가져올 시기를 알 수가 없습니다. 대신, 대화 상자에서 호출한 창에 처리할 데이터를 반환할 다른 방법을 만들어야 합니다.

모덜리스 대화 상자에서 반환된 데이터 처리

이 예제에서 FindDialogBox는 특정 빈도를 사용하지 않고 검색한 텍스트에 따라 주 창으로 하나 이상의 찾기 결과를 반환할 수 있습니다. 모달 대화 상자와 마찬가지로, 모덜리스 대화 상자에서도 속성을 사용하여 결과를 반환할 수 있습니다. 그러나 대화 상자를 소유한 창에서 해당 속성을 검사할 시기를 알아야 합니다. 한 가지 방법은 대화 상자에서 텍스트를 찾을 때마다 발생하는 이벤트를 구현하는 것입니다. FindDialogBox는 이 목적으로 사전에 대리자가 필요한 TextFoundEvent를 구현합니다.

using System;

namespace SDKSample
{
    public delegate void TextFoundEventHandler(object sender, EventArgs e);
}
Namespace SDKSample
   Public Delegate Sub TextFoundEventHandler(ByVal sender As Object, ByVal e As EventArgs)
End Namespace

FindDialogBox에서는 TextFoundEventHandler 대리자를 사용하여 TextFoundEvent를 구현합니다.

using System;
using System.Windows;
using System.Windows.Controls;
using System.Text.RegularExpressions;

namespace SDKSample
{
    public partial class FindDialogBox : Window
    {
        public event TextFoundEventHandler TextFound;

        protected virtual void OnTextFound()
        {
            TextFoundEventHandler textFound = this.TextFound;
            if (textFound != null) textFound(this, EventArgs.Empty);
        }

    }
}
Imports System.Windows
Imports System.Windows.Controls
Imports System.Text.RegularExpressions

Namespace SDKSample

    Public Class FindDialogBox
        Inherits Window

        Public Event TextFound As TextFoundEventHandler

        Protected Overridable Sub OnTextFound()
            RaiseEvent TextFound(Me, EventArgs.Empty)
        End Sub

    End Class
End Namespace

따라서 Find에서는 검색 결과를 발견했을 때 이벤트를 발생시킬 수 있습니다.

using System;
using System.Windows;
using System.Windows.Controls;
using System.Text.RegularExpressions;

namespace SDKSample
{
    public partial class FindDialogBox : Window
    {

        void findNextButton_Click(object sender, RoutedEventArgs e)
        {
                // Text found
                this.index = match.Index;
                this.length = match.Length;
                OnTextFound();
        }
    }
}
Imports System.Windows
Imports System.Windows.Controls
Imports System.Text.RegularExpressions

Namespace SDKSample

    Public Class FindDialogBox
        Inherits Window



            Me.Index = match.Index
            Me.Length = match.Length
            RaiseEvent TextFound(Me, EventArgs.Empty)

    End Class
End Namespace

소유자 창에서는 그 후에 이 이벤트를 등록하고 처리해야 합니다.

using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Win32;

namespace SDKSample
{
    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();
        }
    }
}
Imports System.ComponentModel
Imports System.Windows
Imports System.Windows.Controls
Imports Microsoft.Win32

Namespace SDKSample
    Public Class MainWindow
        Inherits Window
        
        Private Sub dlg_TextFound(ByVal sender As Object, ByVal e As EventArgs)
            Dim dlg As FindDialogBox = DirectCast(sender, FindDialogBox)
            Me.documentTextBox.Select(dlg.Index, dlg.Length)
            Me.documentTextBox.Focus()
        End Sub
    End Class
End Namespace

모덜리스 대화 상자 닫기

DialogResult를 설정할 필요가 없기 때문에, 모덜리스 대화 상자는 다음과 같이 시스템에서 제공되는 메커니즘을 사용하여 닫을 수 있습니다.

  • 제목 표시줄에서 닫기 단추를 클릭합니다.

  • ALT+F4 누르기.

  • 시스템 메뉴에서 닫기를 선택합니다.

또는 닫기 단추를 클릭했을 때 코드에서 Close를 호출할 수 있습니다.

using System;
using System.Windows;
using System.Windows.Controls;
using System.Text.RegularExpressions;

namespace SDKSample
{
    public partial class FindDialogBox : Window
    {

        void closeButton_Click(object sender, RoutedEventArgs e)
        {
            // Close dialog box
            this.Close();
        }
    }
}
Imports System.Windows
Imports System.Windows.Controls
Imports System.Text.RegularExpressions

Namespace SDKSample

    Public Class FindDialogBox
        Inherits Window

        Private Sub closeButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
            MyBase.Close()
        End Sub
    End Class
End Namespace

참고 항목