WPF - Application Development 프로그래밍/WPF2016. 9. 8. 03:46
응용 프로그램 개발
https://msdn.microsoft.com/ko-kr/library/bb613549(v=vs.110).aspx
1. WPF(Windows Presentation Foundation)은 다음과 같은 종류의 응용 프로그램을 개발하는 데 사용할 수 있는 프레젠테이션 프레임워크입니다.
1) 독립 실행형 응용 프로그램(클라이언트 컴퓨터에 설치해서 운영하는 실행 어셈블리로 구성된 전형적인 창 응용 프로그램)
2) XAML browser applications (XBAPs)(탐색 페이지로 이루어져 있고 이 페이지가 Microsoft Internet Explorer 또는 Mozilla Firefox 등의 웹 브라우저를 통해 호스팅되는 실행 어셈블리로 구성된 응용 프로그램)
3) 사용자 지정 컨트롤 라이브러리(재사용 가능한 컨트롤이 들어 있는 비실행 어셈블리)
4) 클래스 라이브러리(재사용 가능한 클래스가 들어 있는 비실행 어셈블리)
참고
1. Windows 서비스에서 WPF 형식을 사용하지 않는 것이 좋습니다.
2. Windows 서비스에서 이러한 기능을 사용하려고 하면 기능이 예상대로 작동하지 않을 수 있습니다.
2. 이러한 응용 프로그램 집합을 빌드하기 위해 WPF는 서비스 호스트를 구현합니다.
3. 이 항목에서는 이러한 서비스에 대한 개요와 더 자세한 정보를 찾을 수 있는 링크를 제공합니다.
응용 프로그램 관리
1. 실행 가능한 WPF 응용 프로그램에는 일반적으로 다음과 같은 핵심 기능 집합이 필요합니다.
1) 진입점 메서드와 시스템 및 입력 메시지를 수신하는 Windows 메시지 루프 만들기를 비롯한 공통 응용 프로그램 인프라 만들기 및 관리
2) 응용 프로그램의 수명 추적 및 상호 작용
3) 명령줄 매개 변수 검색 및 처리
4) 응용 프로그램 범위에 속한 속성 및 UI 리소스 공유
5) 처리되지 않은 예외 검색 및 처리
6) 종료 코드 반환
7) 독립 실행형 응용 프로그램에서 창 관리
8) XAML browser applications (XBAPs)와 탐색 창 및 프레임이 있는 독립 실행형 응용 프로그램에서 탐색 추적
2. 이러한 기능은 응용 프로그램 정의를 사용하여 응용 프로그램에 추가하는 Application 클래스로 구현됩니다.
3. 자세한 내용은 응용 프로그램 관리 개요를 참조하십시오.
WPF 응용 프로그램 리소스, 콘텐츠 및 데이터 파일
1. WPF에서는 리소스, 콘텐츠 및 데이터를 비롯한 세 가지 종류의 비실행 데이터 파일에 대한 지원으로 포함 리소스에 대한 Microsoft .NET Framework의 핵심 지원을 확장합니다.
2. 자세한 내용은 WPF 응용 프로그램 리소스, 콘텐츠 및 데이터 파일을 참조하십시오.
3. WPF 비실행 데이터 파일에 대한 지원에서 중요한 구성 요소는 고유한 URI를 사용하여 데이터 파일을 식별하고 로드하는 기능입니다.
4. 자세한 내용은 WPF의 Pack URI를 참조하십시오.
창 및 대화 상자
1. 사용자는 창을 통해 WPF 독립 실행형 응용 프로그램과 상호 작용합니다.
2. 창의 용도는 응용 프로그램 콘텐츠를 호스팅하고, 대개 사용자가 콘텐츠와 상호 작용할 수 있게 만드는 응용 프로그램 기능을 노출하는 것입니다.
3. WPF에서 창은 다음을 지원하는 Window 클래스로 캡슐화됩니다.
1) 창 만들기 및 표시
2) 소유자/소유된 창 관계 설정
3) 창 모양 구성(예: 크기, 위치, 아이콘, 제목 표시줄 텍스트, 테두리)
4) 창의 수명 추적 및 상호 작용
4. 자세한 내용은 WPF 창 개요를 참조하십시오.
5. Window는 대화 상자라고 하는 특수한 유형의 창을 만드는 기능을 지원합니다.
6. 모달 및 모덜리스 유형의 대화 상자를 모두 만들 수 있습니다.
7. 사용 편의를 높이고 응용 프로그램 간의 재사용 및 일관성 있는 사용자 환경을 제공하기 위해 WPF에서는 세 가지 공용 Windows 대화 상자인 OpenFileDialog, SaveFileDialog 및 PrintDialog를 노출합니다.
8. 메시지 상자는 사용자에게 중요한 텍스트 정보를 표시하고 간단한 예/아니요/확인/취소 질문을 하는 데 사용되는 특수한 유형의 대화 상자입니다.
9. MessageBox 클래스를 사용하여 메시지 상자를 만들고 표시할 수 있습니다.
10. 자세한 내용은 대화 상자 개요를 참조하십시오.
탐색
1. WPF는 페이지(Page)와 하이퍼링크(Hyperlink)를 사용하는 웹 스타일의 탐색을 지원합니다.
2. 이러한 탐색 기능은 다음을 비롯한 다양한 방식으로 구현할 수 있습니다.
1) 웹 브라우저에서 호스팅되는 독립 실행형 페이지
2) 웹 브라우저에서 호스팅되는 XBAP로 컴파일되는 페이지
3) 독립 실행형 응용 프로그램으로 컴파일되고 탐색 창에서 호스팅되는 페이지(NavigationWindow)
4) 독립 실행형 페이지 또는 XBAP나 독립 실행형 응용 프로그램으로 컴파일되는 페이지에서 호스팅될 수 있는 프레임(Frame)을 통해 호스팅되는 페이지
3. WPF에서는 효과적인 탐색을 위해 다음을 구현합니다.
1) Frame, NavigationWindow 및 응용 프로그램 간 탐색을 지원하는 XBAP에서 사용되는 탐색 요청을 처리하기 위한 공유 탐색 엔진인 NavigationService
2) 탐색을 초기화하는 탐색 메서드
3) 탐색 수명을 추적하고 상호 작용하는 탐색 이벤트
4) 검사 및 조작이 가능한 저널을 사용한 후방 및 전방 탐색 기억
4. 자세한 내용은 탐색 개요를 참조하십시오.
5. WPF에서는 구조적 탐색이라고 하는 특수한 유형의 탐색도 지원합니다.
6. 구조적 탐색을 사용하면 호출 함수와 일관성을 유지하는 구조적이며 예측 가능한 방식으로 데이터를 반환하는 하나 이상의 페이지를 호출할 수 있습니다.
7. 이 기능은 PageFunction<T> 클래스에 따라 달라집니다.
8. 이 클래스에 대해서는 구조적 탐색 개요에서 자세히 설명합니다.
9. 탐색 토폴로지 개요에서 설명하는 것처럼 복잡한 탐색 토폴로지를 간단하게 생성하기 위해서도 PageFunction<T>이 사용됩니다.
호스팅
1. XBAP는 Microsoft Internet Explorer 또는 Firefox에서 호스팅될 수 있습니다.
2. 각 호스팅 모델에는 WPF 응용 프로그램 호스팅 항목에 설명되어 있는 고유한 고려 사항과 제약 조건 집합이 있습니다.
빌드 및 배포
1. 명령줄 컴파일러를 사용하면 명령 프롬프트에서 간단한 WPF 응용 프로그램을 빌드할 수 있지만 WPF에서는 Microsoft Visual Studio를 통합하여 개발 및 빌드 프로세스를 단순화하는 추가적인 지원을 제공합니다.
2. 자세한 내용은 WPF 응용 프로그램 만들기(WPF)를 참조하십시오.
3. 빌드하는 응용 프로그램의 형식에 따라 하나 이상의 배포 옵션을 선택하여 사용할 수 있습니다.
4. 자세한 내용은 WPF 응용 프로그램 배포(WPF)를 참조하십시오.
제목 | 설명 |
---|---|
응용 프로그램 수명, 창, 응용 프로그램 리소스 및 탐색에 대한 관리를 비롯하여 Application 클래스에 대해 간략히 설명합니다. | |
Window 클래스 및 대화 상자 사용 방법을 비롯하여 응용 프로그램에서 창을 관리하는 방법에 대한 정보를 제공합니다. | |
응용 프로그램의 페이지 간 탐색 관리에 대해 간략히 설명합니다. | |
XAML browser applications (XBAPs)를 간략하게 설명합니다. | |
WPF 응용 프로그램을 만들고 배포하는 방법에 대해 설명합니다. | |
WPF의 주요 기능을 설명합니다. | |
페이지 탐색, 레이아웃, 컨트롤, 이미지, 스타일 및 바인딩을 사용하여 WPF 응용 프로그램을 만드는 방법을 보여 주는 연습을 제공합니다. |
응용 프로그램 관리 개요
https://msdn.microsoft.com/en-us/library/ms743714(v=vs.110).aspx
Application Management Overview
All applications tend to share a common set of functionality that applies to application implementation and management. This topic provides an overview of the functionality in the Application class for creating and managing applications.
The Application Class
In WPF, common application-scoped functionality is encapsulated in the Application class. The Application class includes the following functionality:
Tracking and interacting with application lifetime.
Retrieving and processing command-line parameters.
Detecting and responding to unhandled exceptions.
Sharing application-scope properties and resources.
Managing windows in standalone applications.
Tracking and managing navigation.
How to Perform Common Tasks Using the Application Class
If you are not interested in all of the details of the Application class, the following table lists some of the common tasks for Application and how to accomplish them. By viewing the related API and topics, you can find more information and sample code.
Task | Approach |
---|---|
Get an object that represents the current application | Use the Application.Current property. |
Add a startup screen to an application | |
Start an application | Use the Application.Run method. |
Stop an application | Use the Shutdown method of the Application.Current object. |
Get arguments from the command line | Handle the Application.Startup event and use the StartupEventArgs.Args property. For an example, see the Application.Startup event. |
Get and set the application exit code | Set the ExitEventArgs.ApplicationExitCode property in the Application.Exit event handler or call the Shutdown method and pass in an integer. |
Detect and respond to unhandled exceptions | Handle the DispatcherUnhandledException event. |
Get and set application-scoped resources | Use the Application.Resources property. |
Use an application-scope resource dictionary | |
Get and set application-scoped properties | Use the Application.Properties property. |
Get and save an application's state | See How to: Persist and Restore Application-Scope Properties Across Application Sessions. |
Manage non-code data files, including resource files, content files, and site-of-origin files. | |
Manage windows in standalone applications | See WPF Windows Overview. |
Track and manage navigation | See Navigation Overview. |
The Application Definition
To utilize the functionality of the Application class, you must implement an application definition. A WPF application definition is a class that derives fromApplication and is configured with a special Microsoft build engine (MSBuild) setting.
Implementing an Application Definition
A typical WPF application definition is implemented using both markup and code-behind. This allows you to use markup to declaratively set application properties, resources, and register events, while handling events and implementing application-specific behavior in code-behind.
The following example shows how to implement an application definition using both markup and code-behind:
<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="SDKSample.App" />
using System.Windows; // Application namespace SDKSample { public partial class App : Application { } }
To allow a markup file and code-behind file to work together, the following needs to happen:
In markup, the Application element must include the x:Class attribute. When the application is built, the existence of x:Class in the markup file causes MSBuild to create a partial class that derives from Application and has the name that is specified by the x:Class attribute. This requires the addition of an XML namespace declaration for the XAML schema (xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml").
In code-behind, the class must be a partial class with the same name that is specified by the x:Class attribute in markup and must derive fromApplication. This allows the code-behind file to be associated with the partial class that is generated for the markup file when the application is built (see Building a WPF Application (WPF)).
Note |
---|
When you create a new WPF Application project or WPF Browser Application project using Microsoft Visual Studio, an application definition is included by default and is defined using both markup and code-behind. |
This code is the minimum that is required to implement an application definition. However, an additional MSBuild configuration needs to be made to the application definition before building and running the application.
Configuring the Application Definition for MSBuild
Standalone applications and XAML browser applications (XBAPs) require the implementation of a certain level of infrastructure before they can run. The most important part of this infrastructure is the entry point. When an application is launched by a user, the operating system calls the entry point, which is a well-known function for starting applications.
Traditionally, developers have needed to write some or all of this code for themselves, depending on the technology. However, WPF generates this code for you when the markup file of your application definition is configured as an MSBuild ApplicationDefinition item, as shown in the following MSBuild project file:
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> ... <ApplicationDefinition Include="App.xaml" /> <Compile Include="App.xaml.cs" /> ... </Project>
Because the code-behind file contains code, it is marked as an MSBuild Compile item, as is normal.
The application of these MSBuild configurations to the markup and code-behind files of an application definition causes MSBuild to generate code like the following:
using System; // STAThread using System.Windows; // Application namespace SDKSample { public class App : Application { public App() { } [STAThread] public static void Main() { // Create new instance of application subclass App app = new App(); // Code to register events and set properties that were // defined in XAML in the application definition app.InitializeComponent(); // Start running the application app.Run(); } public void InitializeComponent() { ... } } }
The resulting code augments your application definition with additional infrastructure code, which includes the entry-point method Main. TheSTAThreadAttribute attribute is applied to the Main method to indicate that the main UI thread for the WPF application is an STA thread, which is required for WPF applications. When called, Main creates a new instance of App before calling the InitializeComponent method to register the events and set the properties that are implemented in markup. Because InitializeComponent is generated for you, you don't need to explicitly callInitializeComponent from an application definition like you do for Page and Window implementations. Finally, the Run method is called to start the application.
Getting the Current Application
Because the functionality of the Application class are shared across an application, there can be only one instance of the Application class perAppDomain. To enforce this, the Application class is implemented as a singleton class (see Implementing Singleton in C#), which creates a single instance of itself and provides shared access to it with the static Current property.
The following code shows how to acquire a reference to the Application object for the current AppDomain.
Current returns a reference to an instance of the Application class. If you want a reference to your Application derived class you must cast the value of the Current property, as shown in the following example.
You can inspect the value of Current at any point in the lifetime of an Application object. However, you should be careful. After the Application class is instantiated, there is a period during which the state of the Application object is inconsistent. During this period, Application is performing the various initialization tasks that are required by your code to run, including establishing application infrastructure, setting properties, and registering events. If you try to use the Application object during this period, your code may have unexpected results, particularly if it depends on the various Applicationproperties being set.
When Application completes its initialization work, its lifetime truly begins.
Application Lifetime
The lifetime of a WPF application is marked by several events that are raised by Application to let you know when your application has started, has been activated and deactivated, and has been shut down.
Splash Screen
Starting in the .NET Framework 3.5 SP1, you can specify an image to be used in a startup window, or splash screen. The SplashScreen class makes it easy to display a startup window while your application is loading. The SplashScreen window is created and shown before Run is called. For more information, see Application Startup Time and How to: Add a Splash Screen to a WPF Application.
Starting an Application
After Run is called and the application is initialized, the application is ready to run. This moment is signified when the Startup event is raised:
using System.Windows; // Application, StartupEventArgs, WindowState namespace SDKSample { public partial class App : Application { void App_Startup(object sender, StartupEventArgs e) { // Application is running ... } } }
At this point in an application's lifetime, the most common thing to do is to show a UI.
Showing a User Interface
Most standalone Windows applications open a Window when they begin running. The Startup event handler is one location from which you can do this, as demonstrated by the following code.
<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="SDKSample.App" Startup="App_Startup" />
using System.Windows; // Application, StartupEventArgs namespace SDKSample { public partial class App : Application { void App_Startup(object sender, StartupEventArgs e) { // Open a window MainWindow window = new MainWindow(); window.Show(); } } }
Note |
---|
The first Window to be instantiated in a standalone application becomes the main application window by default. This Window object is referenced by the Application.MainWindow property. The value of the MainWindow property can be changed programmatically if a different window than the first instantiated Window should be the main window. |
When an XBAP first starts, it will most likely navigate to a Page. This is shown in the following code.
<Application x:Class="SDKSample.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Startup="App_Startup" />
using System; // Uri, UriKind, EventArgs, Console using System.Windows; // Application, StartupEventArgs using System.Windows.Navigation; // NavigationWindow namespace SDKSample { public partial class App : Application { void App_Startup(object sender, StartupEventArgs e) { ((NavigationWindow)this.MainWindow).Navigate(new Uri("HomePage.xaml", UriKind.Relative)); } } }
If you handle Startup to only open a Window or navigate to a Page, you can set the StartupUri attribute in markup instead.
The following example shows how to use the StartupUri from a standalone application to open a Window.
<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" StartupUri="MainWindow.xaml" />
The following example shows how to use StartupUri from an XBAP to navigate to a Page.
<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" StartupUri="HomePage.xaml" />
This markup has the same effect as the previous code for opening a window.
Note |
---|
For more information on navigation, see Navigation Overview. |
You need to handle the Startup event to open a Window if you need to instantiate it using a non-default constructor, or you need to set its properties or subscribe to its events before showing it, or you need to process any command-line arguments that were supplied when the application was launched.
Processing Command-Line Arguments
In Windows, standalone applications can be launched from either a command prompt or the desktop. In both cases, command-line arguments can be passed to the application. The following example shows an application that is launched with a single command-line argument, "/StartMinimized":
wpfapplication.exe /StartMinimized
During application initialization, WPF retrieves the command-line arguments from the operating system and passes them to the Startup event handler via the Args property of the StartupEventArgs parameter. You can retrieve and store the command-line arguments using code like the following.
<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="SDKSample.App" Startup="App_Startup" />
using System.Windows; // Application, StartupEventArgs, WindowState namespace SDKSample { public partial class App : Application { void App_Startup(object sender, StartupEventArgs e) { // Application is running // Process command line args bool startMinimized = false; for (int i = 0; i != e.Args.Length; ++i) { if (e.Args[i] == "/StartMinimized") { startMinimized = true; } } // Create main application window, starting minimized if specified MainWindow mainWindow = new MainWindow(); if (startMinimized) { mainWindow.WindowState = WindowState.Minimized; } mainWindow.Show(); } } }
The code handles Startup to check whether the /StartMinimized command-line argument was provided; if so, it opens the main window with aWindowState of Minimized. Note that because the WindowState property must be set programmatically, the main Window must be opened explicitly in code.
XBAPs cannot retrieve and process command-line arguments because they are launched using ClickOnce deployment (see Deploying a WPF Application (WPF)). However, they can retrieve and process query string parameters from the URLs that are used to launch them.
Application Activation and Deactivation
Windows allows users to switch between applications. The most common way is to use the ALT+TAB key combination. An application can only be switched to if it has a visible Window that a user can select. The currently selected Window is the active window (also known as the foreground window) and is the Window that receives user input. The application with the active window is the active application (or foreground application). An application becomes the active application in the following circumstances:
It is launched and shows a Window.
A user switches from another application by selecting a Window in the application.
You can detect when an application becomes active by handling the Application.Activated event.
Likewise, an application can become inactive in the following circumstances:
A user switches to another application from the current one.
When the application shuts down.
You can detect when an application becomes inactive by handling the Application.Deactivated event.
The following code shows how to handle the Activated and Deactivated events to determine whether an application is active.
<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="SDKSample.App" StartupUri="MainWindow.xaml" Activated="App_Activated" Deactivated="App_Deactivated" />
using System; // EventArgs using System.Windows; // Application namespace SDKSample { public partial class App : Application { bool isApplicationActive; void App_Activated(object sender, EventArgs e) { // Application activated this.isApplicationActive = true; } void App_Deactivated(object sender, EventArgs e) { // Application deactivated this.isApplicationActive = false; } } }
A Window can also be activated and deactivated. See Window.Activated and Window.Deactivated for more information.
Note |
---|
Neither Application.Activated nor Application.Deactivated is raised for XBAPs. |
Application Shutdown
The life of an application ends when it is shut down, which can occur for the following reasons:
A user closes every Window.
A user closes the main Window.
A user ends the Windows session by logging off or shutting down.
An application-specific condition has been met.
To help you manage application shutdown, Application provides the Shutdown method, the ShutdownMode property, and the SessionEnding and Exitevents.
Note |
---|
Shutdown can only be called from applications that have UIPermission. Standalone WPF applications always have this permission. However, XBAPs running in the Internet zone partial-trust security sandbox do not. |
Shutdown Mode
Most applications shut down either when all the windows are closed or when the main window is closed. Sometimes, however, other application-specific conditions may determine when an application shuts down. You can specify the conditions under which your application will shut down by setting ShutdownMode with one of the following ShutdownMode enumeration values:
The default value of ShutdownMode is OnLastWindowClose, which means that an application automatically shuts down when the last window in the application is closed by the user. However, if your application should be shut down when the main window is closed, WPF automatically does that if you set ShutdownMode to OnMainWindowClose. This is shown in the following example.
<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="SDKSample.App" ShutdownMode="OnMainWindowClose" />
When you have application-specific shutdown conditions, you set ShutdownMode to OnExplicitShutdown. In this case, it is your responsibility to shut an application down by explicitly calling the Shutdown method; otherwise, your application will continue running even if all the windows are closed. Note that Shutdown is called implicitly when the ShutdownMode is either OnLastWindowClose or OnMainWindowClose.
Note |
---|
ShutdownMode can be set from an XBAP, but it is ignored; an XBAP is always shut down when it is navigated away from in a browser or when the browser that hosts the XBAP is closed. For more information, see Navigation Overview. |
Session Ending
The shutdown conditions that are described by the ShutdownMode property are specific to an application. In some cases, though, an application may shut down as a result of an external condition. The most common external condition occurs when a user ends the Windows session by the following actions:
Logging off
Shutting down
Restarting
Hibernating
To detect when a Windows session ends, you can handle the SessionEnding event, as illustrated in the following example.
<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="SDKSample.App" StartupUri="MainWindow.xaml" SessionEnding="App_SessionEnding" />
using System.Windows; // Application, SessionEndingCancelEventArgs, MessageBox, MessageBoxResult, MessageBoxButton namespace SDKSample { public partial class App : Application { void App_SessionEnding(object sender, SessionEndingCancelEventArgs e) { // Ask the user if they want to allow the session to end string msg = string.Format("{0}. End session?", e.ReasonSessionEnding); MessageBoxResult result = MessageBox.Show(msg, "Session Ending", MessageBoxButton.YesNo); // End session, if specified if (result == MessageBoxResult.No) { e.Cancel = true; } } } }
In this example, the code inspects the ReasonSessionEnding property to determine how the Windows session is ending. It uses this value to display a confirmation message to the user. If the user does not want the session to end, the code sets Cancel to true to prevent the Windows session from ending.
Note |
---|
SessionEnding is not raised for XBAPs. |
Exit
When an application shuts down, it may need to perform some final processing, such as persisting application state. For these situations, you can handle the Exit event.
<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="SDKSample.App" StartupUri="MainWindow.xaml" Startup="App_Startup" Exit="App_Exit"> ... </Application>
using System.Windows; // Application, StartupEventArgs using System.IO; // StreamReader, FileMode using System.IO.IsolatedStorage; // IsolatedStorageFile, IsolatedStorageFileStream namespace SDKSample { public partial class App : Application { string filename = "App.txt"; ... private void App_Exit(object sender, ExitEventArgs e) { // Persist application-scope property to isolated storage IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForDomain(); using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(filename, FileMode.Create, storage)) using (StreamWriter writer = new StreamWriter(stream)) { // Persist each application-scope property individually foreach (string key in this.Properties.Keys) { writer.WriteLine("{0},{1}", key, this.Properties[key]); } } } } }
For the complete example, see How to: Persist and Restore Application-Scope Properties Across Application Sessions.
Exit can be handled by both standalone applications and XBAPs. For XBAPs, Exit is raised when in the following circumstances:
An XBAP is navigated away from.
In Internet Explorer 7, when the tab that is hosting the XBAP is closed.
When the browser is closed.
Exit Code
Applications are mostly launched by the operating system in response to a user request. However, an application can be launched by another application to perform some specific task. When the launched application shuts down, the launching application may want to know the condition under which the launched application shut down. In these situations, Windows allows applications to return an application exit code on shutdown. By default, WPF applications return an exit code value of 0.
Note |
---|
When you debug from Visual Studio, the application exit code is displayed in the Output window when the application shuts down, in a message that looks like the following: The program '[5340] AWPFApp.vshost.exe: Managed' has exited with code 0 (0x0). You open the Output window by clicking Output on the View menu. |
To change the exit code, you can call the Shutdown(Int32) overload, which accepts an integer argument to be the exit code:
You can detect the value of the exit code, and change it, by handling the Exit event. The Exit event handler is passed an ExitEventArgs which provides access to the exit code with the ApplicationExitCode property. For more information, see Exit.
Note |
---|
You can set the exit code in both standalone applications and XBAPs. However, the exit code value is ignored for XBAPs. |
Unhandled Exceptions
Sometimes an application may shut down under abnormal conditions, such as when an unanticipated exception is thrown. In this case, the application may not have the code to detect and process the exception. This type of exception is an unhandled exception; a notification similar to that shown in the following figure is displayed before the application is closed.
From the user experience perspective, it is better for an application to avoid this default behavior by doing some or all of the following:
Displaying user-friendly information.
Attempting to keep an application running.
Recording detailed, developer-friendly, exception information in the Windows event log.
Implementing this support depends on being able to detect unhandled exceptions, which is what the DispatcherUnhandledException event is raised for.
<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="SDKSample.App" StartupUri="MainWindow.xaml" DispatcherUnhandledException="App_DispatcherUnhandledException" />
using System.Windows; // Application using System.Windows.Threading; // DispatcherUnhandledExceptionEventArgs namespace SDKSample { public partial class App : Application { void App_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) { // Process unhandled exception ... // Prevent default unhandled exception processing e.Handled = true; } } }
The DispatcherUnhandledException event handler is passed a DispatcherUnhandledExceptionEventArgs parameter that contains contextual information regarding the unhandled exception, including the exception itself (DispatcherUnhandledExceptionEventArgs.Exception). You can use this information to determine how to handle the exception.
When you handle DispatcherUnhandledException, you should set the DispatcherUnhandledExceptionEventArgs.Handled property to true; otherwise, WPF still considers the exception to be unhandled and reverts to the default behavior described earlier. If an unhandled exception is raised and either the DispatcherUnhandledException event is not handled, or the event is handled and Handled is set to false, the application shuts down immediately. Furthermore, no other Application events are raised. Consequently, you need to handle DispatcherUnhandledException if your application has code that must run before the application shuts down.
Although an application may shut down as a result of an unhandled exception, an application usually shuts down in response to a user request, as discussed in the next section.
Application Lifetime Events
Standalone applications and XBAPs don't have exactly the same lifetimes. The following figure illustrates the key events in the lifetime of a standalone application and shows the sequence in which they are raised.
Likewise, the following figure illustrates the key events in the lifetime of an XBAP, and shows the sequence in which they are raised.
WPF Windows Overview
https://msdn.microsoft.com/en-us/library/ms748948(v=vs.110).aspx
WPF Windows Overview
Users interact with Windows Presentation Foundation (WPF) standalone applications through windows. The primary purpose of a window is to host content that visualizes data and enables users to interact with data. Standalone WPF applications provide their own windows by using the Windowclass. This topic introduces Window before covering the fundamentals of creating and managing windows in standalone applications.
Note |
---|
Browser-hosted WPF applications, including XAML browser applications (XBAPs) and loose Extensible Application Markup Language (XAML) pages, don't provide their own windows. Instead, they are hosted in windows provided by Windows Internet Explorer. See WPF XAML Browser Applications Overview. |
The Window Class
The following figure illustrates the constituent parts of a window.
A window is divided into two areas: the non-client area and client area.
The non-client area of a window is implemented by WPF and includes the parts of a window that are common to most windows, including the following:
A border.
A title bar.
An icon.
Minimize, Maximize, and Restore buttons.
A Close button.
A System menu with menu items that allow users to minimize, maximize, restore, move, resize, and close a window.
The client area of a window is the area within a window's non-client area and is used by developers to add application-specific content, such as menu bars, tool bars, and controls.
In WPF, a window is encapsulated by the Window class that you use to do the following:
Display a window.
Configure the size, position, and appearance of a window.
Host application-specific content.
Manage the lifetime of a window.
Implementing a Window
The implementation of a typical window comprises both appearance and behavior, where appearance defines how a window looks to users andbehavior defines the way a window functions as users interact with it. In WPF, you can implement the appearance and behavior of a window using either code or XAML markup.
In general, however, the appearance of a window is implemented using XAML markup, and its behavior is implemented using code-behind, as shown in the following example.
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="SDKSample.MarkupAndCodeBehindWindow"> <!-- Client area (for content) --> </Window>
using System.Windows; // Window namespace SDKSample { public partial class MarkupAndCodeBehindWindow : Window { public MarkupAndCodeBehindWindow() { InitializeComponent(); } } }
To enable a XAML markup file and code-behind file to work together, the following are required:
In markup, the Window element must include the x:Class attribute. When the application is built, the existence of x:Class in the markup file causes Microsoft build engine (MSBuild) to create a partial class that derives from Window and has the name that is specified by the x:Classattribute. This requires the addition of an XML namespace declaration for the XAML schema (xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"). The generated partial class implements the InitializeComponentmethod, which is called to register the events and set the properties that are implemented in markup.
In code-behind, the class must be a partial class with the same name that is specified by the x:Class attribute in markup, and it must derive from Window. This allows the code-behind file to be associated with the partial class that is generated for the markup file when the application is built (see Building a WPF Application (WPF)).
In code-behind, the Window class must implement a constructor that calls the InitializeComponent method. InitializeComponent is implemented by the markup file's generated partial class to register events and set properties that are defined in markup.
With this configuration in place, you can focus on defining the appearance of the window in XAML markup and implementing its behavior in code-behind. The following example shows a window with a button, implemented in XAML markup, and an event handler for the button's Click event, implemented in code-behind.
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="SDKSample.MarkupAndCodeBehindWindow"> <!-- Client area (for content) --> <Button Click="button_Click">Click This Button</Button> </Window>
Configuring a Window Definition for MSBuild
How you implement your window determines how it is configured for MSBuild. For a window that is defined using both XAML markup and code-behind:
XAML markup files are configured as MSBuild Page items.
Code-behind files are configured as MSBuild Compile items.
This is shown in the following MSBuild project file.
<Project ... xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> ... <Page Include="MarkupAndCodeBehindWindow.xaml" /> <Compile Include=" MarkupAndCodeBehindWindow.xaml.cs" /> ... </Project>
For information about building WPF applications, see Building a WPF Application (WPF).
Window Lifetime
As with any class, a window has a lifetime that begins when it is first instantiated, after which it is opened, activated and deactivated, and eventually closed.
Opening a Window
To open a window, you first create an instance of it, which is demonstrated in the following example.
<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="SDKSample.App" Startup="app_Startup"> </Application>
using System.Windows; namespace SDKSample { public partial class App : Application { void app_Startup(object sender, StartupEventArgs e) { // Create a window MarkupAndCodeBehindWindow window = new MarkupAndCodeBehindWindow(); // Open a window window.Show(); } } }
In this example, the MarkupAndCodeBehindWindow is instantiated when the application starts, which occurs when the Startup event is raised.
When a window is instantiated, a reference to it is automatically added to a list of windows that is managed by the Application object (seeApplication.Windows). Additionally, the first window to be instantiated is, by default, set by Application as the main application window (seeApplication.MainWindow).
The window is finally opened by calling the Show method; the result is shown in the following figure.
A window that is opened by calling Show is a modeless window, which means that the application operates in a mode that allows users to activate other windows in the same application.
Note |
---|
ShowDialog is called to open windows such as dialog boxes modally. See Dialog Boxes Overview for more information. |
When Show is called, a window performs initialization work before it is shown to establish infrastructure that allows it to receive user input. When the window is initialized, the SourceInitialized event is raised and the window is shown.
As a shortcut, StartupUri can be set to specify the first window that is opened automatically when an application starts.
<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="SDKSample.App" StartupUri="PlainWindow.xaml" />
When the application starts, the window specified by the value of StartupUri is opened modelessly; internally, the window is opened by calling itsShow method.
Window Ownership
A window that is opened by using the Show method does not have an implicit relationship with the window that created it; users can interact with either window independently of the other, which means that either window can do the following:
Cover the other (unless one of the windows has its Topmost property set to true).
Be minimized, maximized, and restored without affecting the other.
Some windows require a relationship with the window that opens them. For example, an Integrated Development Environment (IDE) application may open property windows and tool windows whose typical behavior is to cover the window that creates them. Furthermore, such windows should always close, minimize, maximize, and restore in concert with the window that created them. Such a relationship can be established by making one window own another, and is achieved by setting the Owner property of the owned window with a reference to the owner window. This is shown in the following example.
// Create a window and make this window its owner Window ownedWindow = new Window(); ownedWindow.Owner = this; ownedWindow.Show();
After ownership is established:
The owned window can reference its owner window by inspecting the value of its Owner property.
The owner window can discover all the windows it owns by inspecting the value of its OwnedWindows property.
Preventing Window Activation
There are scenarios where windows should not be activated when shown, such as conversation windows of an Internet messenger-style application or notification windows of an e-mail application.
If your application has a window that shouldn't be activated when shown, you can set its ShowActivated property to false before calling theShow method for the first time. As a consequence:
The window is not activated.
The window's Activated event is not raised.
The currently activated window remains activated.
The window will become activated, however, as soon as the user activates it by clicking either the client or non-client area. In this case:
The window is activated.
The window's Activated event is raised.
The previously activated window is deactivated.
The window's Deactivated and Activated events are subsequently raised as expected in response to user actions.
Window Activation
When a window is first opened, it becomes the active window (unless it is shown with ShowActivated set to false). The active window is the window that is currently capturing user input, such as key strokes and mouse clicks. When a window becomes active, it raises the Activated event.
Note |
---|
When a window is first opened, the Loaded and ContentRendered events are raised only after the Activated event is raised. With this in mind, a window can effectively be considered opened when ContentRendered is raised. |
After a window becomes active, a user can activate another window in the same application, or activate another application. When that happens, the currently active window becomes deactivated and raises the Deactivated event. Likewise, when the user selects a currently deactivated window, the window becomes active again and Activated is raised.
One common reason to handle Activated and Deactivated is to enable and disable functionality that can only run when a window is active. For example, some windows display interactive content that requires constant user input or attention, including games and video players. The following example is a simplified video player that demonstrates how to handle Activated and Deactivated to implement this behavior.
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="SDKSample.CustomMediaPlayerWindow" Activated="window_Activated" Deactivated="window_Deactivated"> <!-- Media Player --> <MediaElement Name="mediaElement" Stretch="Fill" LoadedBehavior="Manual" Source="numbers.wmv" /> </Window>
using System; // EventArgs using System.Windows; // Window namespace SDKSample { public partial class CustomMediaPlayerWindow : Window { public CustomMediaPlayerWindow() { InitializeComponent(); } void window_Activated(object sender, EventArgs e) { // Recommence playing media if window is activated this.mediaElement.Play(); } void window_Deactivated(object sender, EventArgs e) { // Pause playing if media is being played and window is deactivated this.mediaElement.Pause(); } } }
Other types of applications may still run code in the background when a window is deactivated. For example, a mail client may continue polling the mail server while the user is using other applications. Applications like these often provide different or additional behavior while the main window is deactivated. With respect to the mail program, this may mean both adding the new mail item to the inbox and adding a notification icon to the system tray. A notification icon need only be displayed when the mail window isn't active, which can be determined by inspecting theIsActive property.
If a background task completes, a window may want to notify the user more urgently by calling Activate method. If the user is interacting with another application activated when Activate is called, the window's taskbar button flashes. If a user is interacting with the current application, calling Activate will bring the window to the foreground.
Note |
---|
You can handle application-scope activation using the Application.Activated and Application.Deactivated events. |
Closing a Window
The life of a window starts coming to an end when a user closes it. A window can be closed by using elements in the non-client area, including the following:
The Close item of the System menu.
Pressing ALT+F4.
Pressing the Close button.
You can provide additional mechanisms to the client area to close a window, the more common of which include the following:
An Exit item in the File menu, typically for main application windows.
A Close item in the File menu, typically on a secondary application window.
A Cancel button, typically on a modal dialog box.
A Close button, typically on a modeless dialog box.
To close a window in response to one of these custom mechanisms, you need to call the Close method. The following example implements the ability to close a window by choosing the Exit on the File menu.
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="SDKSample.WindowWithFileExit"> <Menu> <MenuItem Header="_File"> <MenuItem Header="E_xit" Click="fileExitMenuItem_Click" /> </MenuItem> </Menu> </Window>
using System.Windows; // window, RoutedEventArgs namespace SDKSample { public partial class WindowWithFileExit : System.Windows.Window { public WindowWithFileExit() { InitializeComponent(); } void fileExitMenuItem_Click(object sender, RoutedEventArgs e) { // Close this window this.Close(); } } }
When a window closes, it raises two events: Closing and Closed.
Closing is raised before the window closes, and it provides a mechanism by which window closure can be prevented. One common reason to prevent window closure is if window content contains modified data. In this situation, the Closing event can be handled to determine whether data is dirty and, if so, to ask the user whether to either continue closing the window without saving the data or to cancel window closure. The following example shows the key aspects of handling Closing.
using System; // EventArgs using System.ComponentModel; // CancelEventArgs using System.Windows; // window namespace CSharp { public partial class DataWindow : Window { // Is data dirty bool isDataDirty = false; ... void DataWindow_Closing(object sender, CancelEventArgs e) { MessageBox.Show("Closing called"); // If data is dirty, notify user and ask for a response if (this.isDataDirty) { string msg = "Data is dirty. Close without saving?"; MessageBoxResult result = MessageBox.Show( msg, "Data App", MessageBoxButton.YesNo, MessageBoxImage.Warning); if (result == MessageBoxResult.No) { // If user doesn't want to close, cancel closure e.Cancel = true; } } } } }
The Closing event handler is passed a CancelEventArgs, which implements the Boolean Cancel property that you set to true to prevent a window from closing.
If Closing is not handled, or it is handled but not canceled, the window will close. Just before a window actually closes, Closed is raised. At this point, a window cannot be prevented from closing.
Note |
---|
An application can be configured to shut down automatically when either the main application window closes (see MainWindow) or the last window closes. For details, see ShutdownMode. |
While a window can be explicitly closed through mechanisms provided in the non-client and client areas, a window can also be implicitly closed as a result of behavior in other parts of the application or Windows, including the following:
A user logs off or shuts down Windows.
A window's owner closes (see Owner).
The main application window is closed and ShutdownMode is OnMainWindowClose.
Shutdown is called.
Note |
---|
A window cannot be reopened after it is closed. |
Window Lifetime Events
The following illustration shows the sequence of the principal events in the lifetime of a window.
The following illustration shows the sequence of the principal events in the lifetime of a window that is shown without activation (ShowActivated is set to false before the window is shown).
Window Location
While a window is open, it has a location in the x and y dimensions relative to the desktop. This location can be determined by inspecting the Leftand Top properties, respectively. You can set these properties to change the location of the window.
You can also specify the initial location of a Window when it first appears by setting the WindowStartupLocation property with one of the followingWindowStartupLocation enumeration values:
Manual (default)
If the startup location is specified as Manual, and the Left and Top properties have not been set, Window will ask Windows for a location to appear in.
Topmost Windows and Z-Order
Besides having an x and y location, a window also has a location in the z dimension, which determines its vertical position with respect to other windows. This is known as the window's z-order, and there are two types: normal z-order and topmost z-order. The location of a window in thenormal z-order is determined by whether it is currently active or not. By default, a window is located in the normal z-order. The location of a window in the topmost z-order is also determined by whether it is currently active or not. Furthermore, windows in the topmost z-order are always located above windows in the normal z-order. A window is located in the topmost z-order by setting its Topmost property to true.
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" Topmost="True"> ... </Window>
Within each z-order, the currently active window appears above all other windows in the same z-order.
Window Size
Besides having a desktop location, a window has a size that is determined by several properties, including the various width and height properties and SizeToContent.
MinWidth, Width, and MaxWidth are used to manage the range of widths that a window can have during its lifetime, and are configured as shown in the following example.
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" MinWidth="300" Width="400" MaxWidth="500"> ... </Window>
Window height is managed by MinHeight, Height, and MaxHeight, and are configured as shown in the following example.
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" MinHeight="300" Height="400" MaxHeight="500"> ... </Window>
Because the various width values and height values each specify a range, it is possible for the width and height of a resizable window to be anywhere within the specified range for the respective dimension. To detect its current width and height, inspect ActualWidth and ActualHeight, respectively.
If you'd like the width and height of your window to have a size that fits to the size of the window's content, you can use the SizeToContent property, which has the following values:
Manual. No effect (default).
Width. Fit to content width, which has the same effect as setting both MinWidth and MaxWidth to the width of the content.
Height. Fit to content height, which has the same effect as setting both MinHeight and MaxHeight to the height of the content.
WidthAndHeight. Fit to content width and height, which has the same effect as setting both MinHeight and MaxHeight to the height of the content, and setting both MinWidth and MaxWidth to the width of the content.
The following example shows a window that automatically sizes to fit its content, both vertically and horizontally, when first shown.
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" SizeToContent="WidthAndHeight"> ... </Window>
Order of Precedence for Sizing Properties
Essentially, the various sizes properties of a window combine to define the range of width and height for a resizable window. To ensure a valid range is maintained, Window evaluates the values of the size properties using the following orders of precedence.
For Height Properties:
For Width Properties:
The order of precedence can also determine the size of a window when it is maximized, which is managed with the WindowState property.
Window State
During the lifetime of a resizable window, it can have three states: normal, minimized, and maximized. A window with a normal state is the default state of a window. A window with this state allows a user to move and resize it by using a resize grip or the border, if it is resizable.
A window with a minimized state collapses to its task bar button if ShowInTaskbar is set to true; otherwise, it collapses to the smallest possible size it can be and relocates itself to the bottom-left corner of the desktop. Neither type of minimized window can be resized using a border or resize grip, although a minimized window that isn't shown in the task bar can be dragged around the desktop.
A window with a maximized state expands to the maximum size it can be, which will only be as large as its MaxWidth, MaxHeight, and SizeToContentproperties dictate. Like a minimized window, a maximized window cannot be resized by using a resize grip or by dragging the border.
The state of a window can be configured by setting its WindowState property, which can have one of the following WindowState enumeration values:
The following example shows how to create a window that is shown as maximized when it opens.
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" WindowState="Maximized"> ... </Window>
In general, you should set WindowState to configure the initial state of a window. Once a resizable window is shown, users can press the minimize, maximize, and restore buttons on the window's title bar to change the window state.
Window Appearance
You change the appearance of the client area of a window by adding window-specific content to it, such as buttons, labels, and text boxes. To configure the non-client area, Window provides several properties, which include Icon to set a window's icon and Title to set its title.
You can also change the appearance and behavior of non-client area border by configuring a window's resize mode, window style, and whether it appears as a button in the desktop task bar.
Resize Mode
Depending on the WindowStyle property, you can control how (and if) users can resize the window. The choice of window style affects whether a user can resize the window by dragging its border with the mouse, whether the Minimize, Maximize, and Resize buttons appear on the non-client area, and, if they do appear, whether they are enabled.
You can configure how a window resizes by setting its ResizeMode property, which can be one of the following ResizeMode enumeration values:
As with WindowStyle, the resize mode of a window is unlikely to change during its lifetime, which means that you'll most likely set it from XAML markup.
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" ResizeMode="CanResizeWithGrip"> ... </Window>
Note that you can detect whether a window is maximized, minimized, or restored by inspecting the WindowState property.
Window Style
The border that is exposed from the non-client area of a window is suitable for most applications. However, there are circumstances where different types of borders are needed, or no borders are needed at all, depending on the type of window.
To control what type of border a window gets, you set its WindowStyle property with one of the following values of the WindowStyle enumeration:
The effect of these window styles are illustrated in the following figure.
You can set WindowStyle using either XAML markup or code; because it is unlikely to change during the lifetime of a window, you will most likely configure it using XAML markup.
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" WindowStyle="ToolWindow"> ... </Window>
Non-Rectangular Window Style
There are also situations where the border styles that WindowStyle allows you to have are not sufficient. For example, you may want to create an application with a non-rectangular border, like Microsoft Windows Media Player uses.
For example, consider the speech bubble window shown in the following figure.
This type of window can be created by setting the WindowStyle property to None, and by using special support that Window has for transparency.
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" WindowStyle="None" AllowsTransparency="True" Background="Transparent"> ... </Window>
This combination of values instructs the window to render completely transparent. In this state, the window's non-client area adornments (the Close menu, Minimize, Maximize, and Restore buttons, and so on) cannot be used. Consequently, you need to provide your own.
Task Bar Presence
The default appearance of a window includes a task bar button, like the one shown in the following figure.
Some types of windows don't have a task bar button, such as message boxes and dialog boxes (see Dialog Boxes Overview). You can control whether the task bar button for a window is shown by setting the ShowInTaskbar property (true by default).
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" ShowInTaskbar="False"> ... </Window>
Security Considerations
Window requires UnmanagedCode security permission to be instantiated. For applications installed on and launched from the local machine, this falls within the set of permissions that are granted to the application.
However, this falls outside the set of permissions granted to applications that are launched from the Internet or Local intranet zone using ClickOnce. Consequently, users will receive a ClickOnce security warning and will need to elevate the permission set for the application to full trust.
Additionally, XBAPs cannot show windows or dialog boxes by default. For a discussion on standalone application security considerations, see WPF Security Strategy - Platform Security.
Other Types of Windows
NavigationWindow is a window that is designed to host navigable content. For more information, see Navigation Overview).
Dialog boxes are windows that are often used to gather information from a user to complete a function. For example, when a user wants to open a file, the Open File dialog box is usually displayed by an application to get the file name from the user. For more information, see Dialog Boxes Overview.
Dialog Boxes Overview
https://msdn.microsoft.com/en-us/library/aa969773(v=vs.110).aspx
Standalone applications typically have a main window that both displays the main data over which the application operates and exposes the functionality to process that data through user interface (UI) mechanisms like menu bars, tool bars, and status bars. A non-trivial application may also display additional windows to do the following:
Display specific information to users.
Gather information from users.
Both display and gather information.
These types of windows are known as dialog boxes, and there are two types: modal and modeless.
A modal dialog box is displayed by a function when the function needs additional data from a user to continue. Because the function depends on the modal dialog box to gather data, the modal dialog box also prevents a user from activating other windows in the application while it remains open. In most cases, a modal dialog box allows a user to signal when they have finished with the modal dialog box by pressing either an OK or Cancel button. Pressing the OK button indicates that a user has entered data and wants the function to continue processing with that data. Pressing the Cancel button indicates that a user wants to stop the function from executing altogether. The most common examples of modal dialog boxes are shown to open, save, and print data.
A modeless dialog box, on the other hand, does not prevent a user from activating other windows while it is open. For example, if a user wants to find occurrences of a particular word in a document, a main window will often open a dialog box to ask a user what word they are looking for. Since finding a word doesn't prevent a user from editing the document, however, the dialog box doesn't need to be modal. A modeless dialog box at least provides aClose button to close the dialog box, and may provide additional buttons to execute specific functions, such as a Find Next button to find the next word that matches the find criteria of a word search.
Windows Presentation Foundation (WPF) allows you to create several types of dialog boxes, including message boxes, common dialog boxes, and custom dialog boxes. This topic discusses each, and the Dialog Box Sample provides matching examples.
Message Boxes
A message box is a dialog box that can be used to display textual information and to allow users to make decisions with buttons. The following figure shows a message box that displays textual information, asks a question, and provides the user with three buttons to answer the question.
To create a message box, you use the MessageBox class. MessageBox lets you configure the message box text, title, icon, and buttons, using code like the following.
// 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;
To show a message box, you call the static Show method, as demonstrated in the following code.
When code that shows a message box needs to detect and process the user's decision (which button was pressed), the code can inspect the message box result, as shown in the following code.
// 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; }
For more information on using message boxes, see MessageBox, MessageBox Sample, and Dialog Box Sample.
Although MessageBox may offer a simple dialog box user experience, the advantage of using MessageBox is that is the only type of window that can be shown by applications that run within a partial trust security sandbox (see Security (WPF)), such as XAML browser applications (XBAPs).
Most dialog boxes display and gather more complex data than the result of a message box, including text, selection (check boxes), mutually exclusive selection (radio buttons), and list selection (list boxes, combo boxes, drop-down list boxes). For these, Windows Presentation Foundation (WPF) provides several common dialog boxes and allows you to create your own dialog boxes, although the use of either is limited to applications running with full trust.
Common Dialog Boxes
Windows implements a variety of reusable dialog boxes that are common to all applications, including dialog boxes for opening files, saving files, and printing. Since these dialog boxes are implemented by the operating system, they can be shared among all the applications that run on the operating system, which helps user experience consistency; when users are familiar with the use of an operating system-provided dialog box in one application, they don't need to learn how to use that dialog box in other applications. Because these dialog boxes are available to all applications and because they help provide a consistent user experience, they are known as common dialog boxes.
Windows Presentation Foundation (WPF) encapsulates the open file, save file, and print common dialog boxes and exposes them as managed classes for you to use in standalone applications. This topic provides a brief overview of each.
Open File Dialog
The open file dialog box, shown in the following figure, is used by file opening functionality to retrieve the name of a file to open.
The common open file dialog box is implemented as the OpenFileDialog class and is located in the Microsoft.Win32 namespace. The following code shows how to create, configure, and show one, and how to process the result.
// 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; }
For more information on the open file dialog box, see Microsoft.Win32.OpenFileDialog.
Note |
---|
OpenFileDialog can be used to safely retrieve file names by applications running with partial trust (see Security (WPF)). |
Save File Dialog Box
The save file dialog box, shown in the following figure, is used by file saving functionality to retrieve the name of a file to save.
The common save file dialog box is implemented as the SaveFileDialog class, and is located in the Microsoft.Win32 namespace. The following code shows how to create, configure, and show one, and how to process the result.
// Configure save file dialog box Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog(); dlg.FileName = "Document"; // Default file name dlg.DefaultExt = ".text"; // 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; }
For more information on the save file dialog box, see Microsoft.Win32.SaveFileDialog.
Print Dialog Box
The print dialog box, shown in the following figure, is used by printing functionality to choose and configure the printer that a user would like to print data to.
The common print dialog box is implemented as the PrintDialog class, and is located in the System.Windows.Controls namespace. The following code shows how to create, configure, and show one.
// 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 }
For more information on the print dialog box, see System.Windows.Controls.PrintDialog. For detailed discussion of printing in WPF, see Printing Overview.
Custom Dialog Boxes
While common dialog boxes are useful, and should be used when possible, they do not support the requirements of domain-specific dialog boxes. In these cases, you need to create your own dialog boxes. As we'll see, a dialog box is a window with special behaviors. Window implements those behaviors and, consequently, you use Window to create custom modal and modeless dialog boxes.
Creating a Modal Custom Dialog Box
This topic shows how to use Window to create a typical modal dialog box implementation, using the Margins dialog box as an example (seeDialog Box Sample). The Margins dialog box is shown in the following figure.
Configuring a Modal Dialog Box
The user interface for a typical dialog box includes the following:
The various controls that are required to gather the desired data.
Showing an OK button that users click to close the dialog box, return to the function, and continue processing.
Showing a Cancel button that users click to close the dialog box and stop the function from further processing.
Showing a Close button in the title bar.
Showing an icon.
Showing Minimize, Maximize, and Restore buttons.
Showing a System menu to minimize, maximize, restore, and close the dialog box.
Opening above and in the center of the window that opened the dialog box.
Dialog boxes should be resizable where possible so, to prevent the dialog box from being too small, and to provide the user with a useful default size, you need to set both default and a minimum dimensions respectively.
Pressing the ESC key should be configured as a keyboard shortcut that causes the Cancel button to be pressed. This is achieved by setting the IsCancel property of the Cancel button to true.
Pressing the ENTER (or RETURN) key should be configured as a keyboard shortcut that causes the OK button to be pressed. This is achieved by setting the IsDefault property of the OK button true.
The following code demonstrates this configuration.
<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; // Window, RoutedEventArgs, IInputElement, DependencyObject using System.Windows.Controls; // Validation using System.Windows.Input; // Keyboard namespace SDKSample { public partial class MarginsDialogBox : Window { public MarginsDialogBox() { InitializeComponent(); } ... } }
The user experience for a dialog box also extends into the menu bar of the window that opens the dialog box. When a menu item runs a function that requires user interaction through a dialog box before the function can continue, the menu item for the function will have an ellipsis in its header, as shown here.
<!--Main Window--> ... <MenuItem Name="formatMarginsMenuItem" Header="_Margins..." Click="formatMarginsMenuItem_Click" />
When a menu item runs a function that displays a dialog box which does not require user interaction, such as an About dialog box, an ellipsis is not required.
Opening a Modal Dialog Box
A dialog box is typically shown as a result of a user selecting a menu item to perform a domain-specific function, such as setting the margins of a document in a word processor. Showing a window as a dialog box is similar to showing a normal window, although it requires additional dialog box-specific configuration. The entire process of instantiating, configuring, and opening a dialog box is shown in the following code.
using System; // EventArgs using System.ComponentModel; // CancelEventArgs using System.Windows; // Window, MessageBoxXxx, RoutedEventArgs using System.Windows.Controls; // TextChangedEventArgs using Microsoft.Win32; // OpenFileDialog namespace SDKSample { 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(); ... } ... } }
Here, the code is passing default information (the current margins) to the dialog box. It is also setting the Window.Owner property with a reference to the window that is showing the dialog box. In general, you should always set the owner for a dialog box to provide window state-related behaviors that are common to all dialog boxes (see WPF Windows Overview for more information).
Note |
---|
You must provide an owner to support user interface (UI) automation for dialog boxes (see UI Automation Overview). |
After the dialog box is configured, it is shown modally by calling the ShowDialog method.
Validating User-Provided Data
When a dialog box is opened and the user provides the required data, a dialog box is responsible for ensuring that the provided data is valid for the following reasons:
From a security perspective, all input should be validated.
From a domain-specific perspective, data validation prevents erroneous data from being processed by the code, which could potentially throw exceptions.
From a user-experience perspective, a dialog box can help users by showing them which data they have entered is invalid.
From a performance perspective, data validation in a multi-tier application can reduce the number of round trips between the client and the application tiers, particularly when the application is composed of Web services or server-based databases.
To validate a bound control in WPF, you need to define a validation rule and associate it with the binding. A validation rule is a custom class that derives from ValidationRule. The following example shows a validation rule, MarginValidationRule, which checks that a bound value is aDouble and is within a specified range.
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); } } }
In this code, the validation logic of a validation rule is implemented by overriding the Validate method, which validates the data and returns an appropriate ValidationResult.
To associate the validation rule with the bound control, you use the following markup.
<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> ... <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>
Once the validation rule is associated, WPF will automatically apply it when data is entered into the bound control. When a control contains invalid data, WPF will display a red border around the invalid control, as shown in the following figure.
WPF does not restrict a user to the invalid control until they have entered valid data. This is good behavior for a dialog box; a user should be able to freely navigate the controls in a dialog box whether or not data is valid. However, this means a user can enter invalid data and press theOK button. For this reason, your code also needs to validate all controls in a dialog box when the OK button is pressed by handling the Clickevent.
using System.Windows; // Window, RoutedEventArgs, IInputElement, DependencyObject using System.Windows.Controls; // Validation using System.Windows.Input; // Keyboard 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; } } }
This code enumerates all dependency objects on a window and, if any are invalid (as returned by GetHasError, the invalid control gets the focus, the IsValid method returns false, and the window is considered invalid.
Once a dialog box is valid, it can safely close and return. As part of the return process, it needs to return a result to the calling function.
Setting the Modal Dialog Result
Opening a dialog box using ShowDialog is fundamentally like calling a method: the code that opened the dialog box using ShowDialog waits until ShowDialog returns. When ShowDialog returns, the code that called it needs to decide whether to continue processing or stop processing, based on whether the user pressed the OK button or the Cancel button. To facilitate this decision, the dialog box needs to return the user's choice as a Boolean value that is returned from the ShowDialog method.
When the OK button clicked, ShowDialog should return true. This is achieved by setting the DialogResult property of the dialog box when theOK button is clicked.
Note that setting the DialogResult property also causes the window to close automatically, which alleviates the need to explicitly call Close.
When the Cancel button is clicked, ShowDialog should return false, which also requires setting the DialogResult property.
using System.Windows; // Window, RoutedEventArgs, IInputElement, DependencyObject using System.Windows.Controls; // Validation using System.Windows.Input; // Keyboard namespace SDKSample { public partial class MarginsDialogBox : Window { ... void cancelButton_Click(object sender, RoutedEventArgs e) { // Dialog box canceled this.DialogResult = false; } ... } }
When a button's IsCancel property is set to true and the user presses either the Cancel button or the ESC key, DialogResult is automatically set to false. The following markup has the same effect as the preceding code, without the need to handle the Click event.
<Button Name="cancelButton" IsCancel="True">Cancel</Button>
A dialog box automatically returns false when a user presses the Close button in the title bar or chooses the Close menu item from the Systemmenu.
Processing Data Returned from a Modal Dialog Box
When DialogResult is set by a dialog box, the function that opened it can get the dialog box result by inspecting the DialogResult property when ShowDialog returns.
using System; // EventArgs using System.ComponentModel; // CancelEventArgs using System.Windows; // Window, MessageBoxXxx, RoutedEventArgs using System.Windows.Controls; // TextChangedEventArgs using Microsoft.Win32; // OpenFileDialog 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; } } ... } }
If the dialog result is true, the function uses that as a cue to retrieve and process the data provided by the user.
Note |
---|
After ShowDialog has returned, a dialog box cannot be reopened. Instead, you need to create a new instance. |
If the dialog result is false, the function should end processing appropriately.
Creating a Modeless Custom Dialog Box
A modeless dialog box, such as the Find Dialog Box shown in the following figure, has the same fundamental appearance as the modal dialog box.
However, the behavior is slightly different, as described in the following sections.
Opening a Modeless Dialog Box
A modeless dialog box is opened by calling the Show method.
<!--Main Window-->
using System; // EventArgs using System.ComponentModel; // CancelEventArgs using System.Windows; // Window, MessageBoxXxx, RoutedEventArgs using System.Windows.Controls; // TextChangedEventArgs using Microsoft.Win32; // OpenFileDialog 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(); } ... } }
Unlike ShowDialog, Show returns immediately. Consequently, the calling window cannot tell when the modeless dialog box is closed and, therefore, does not know when to check for a dialog box result or get data from the dialog box for further processing. Instead, the dialog box needs to create an alternative way to return data to the calling window for processing.
Processing Data Returned from a Modeless Dialog Box
In this example, the FindDialogBox may return one or more find results to the main window, depending on the text being searched for without any specific frequency. As with a modal dialog box, a modeless dialog box can return results using properties. However, the window that owns the dialog box needs to know when to check those properties. One way to enable this is for the dialog box to implement an event that is raised whenever text is found. FindDialogBox implements the TextFoundEvent for this purpose, which first requires a delegate.
using System; namespace SDKSample { public delegate void TextFoundEventHandler(object sender, EventArgs e); }
Using the TextFoundEventHandler delegate, FindDialogBox implements the TextFoundEvent.
using System; // EventArgs using System.Windows; // Window, MessageBoxXxx, RoutedEventArgs using System.Windows.Controls; // TextBox, TextChangedEventArgs using System.Text.RegularExpressions; // Regex 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); } ... } }
Consequently, Find can raise the event when a search result is found.
using System; // EventArgs using System.Windows; // Window, MessageBoxXxx, RoutedEventArgs using System.Windows.Controls; // TextBox, TextChangedEventArgs using System.Text.RegularExpressions; // Regex 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(); ... } ... } }
The owner window then needs to register with and handle this event.
using System; // EventArgs using System.ComponentModel; // CancelEventArgs using System.Windows; // Window, MessageBoxXxx, RoutedEventArgs using System.Windows.Controls; // TextChangedEventArgs using Microsoft.Win32; // OpenFileDialog 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(); } } }
Closing a Modeless Dialog Box
Because DialogResult does not need to be set, a modeless dialog can be closed using system provide mechanisms, including the following:
Clicking the Close button in the title bar.
Pressing ALT+F4.
Choosing Close from the System menu.
Alternatively, your code can call Close when the Close button is clicked.
using System; // EventArgs using System.Windows; // Window, MessageBoxXxx, RoutedEventArgs using System.Windows.Controls; // TextBox, TextChangedEventArgs using System.Text.RegularExpressions; // Regex namespace SDKSample { public partial class FindDialogBox : Window { ... void closeButton_Click(object sender, RoutedEventArgs e) { // Close dialog box this.Close(); } } }
How to: Automatically Size a Window to Fit Its Content
// Manually alter window height and width
this.SizeToContent = SizeToContent.Manual; // Automatically resize width relative to content this.SizeToContent = SizeToContent.Width; // Automatically resize height relative to content this.SizeToContent = SizeToContent.Height; // Automatically resize height and width relative to content this.SizeToContent = SizeToContent.WidthAndHeight;
How to: Get all Windows in an Application
This example shows how to get all Window objects in an application.
Example
Every instantiated Window object, whether visible or not, is automatically added to a collection of window references that is managed by Application, and exposed from Windows.
You can enumerate Windows to get all instantiated windows using the following code:
foreach( Window window in Application.Current.Windows ) { Console.WriteLine(window.Title); }
How to: Get and Set the Main Application Window
This example shows how to get and set the main application window.
Example
The first Window that is instantiated within a Windows Presentation Foundation (WPF) application is automatically set by Application as the main application window. The first Window to be instantiated will most likely be the window that is specified as the startup uniform resource identifier (URI) (seeStartupUri).
The first Window could also be instantiated using code. One example is opening a window during application startup, like the following:
public partial class App : Application { void App_Startup(object sender, StartupEventArgs e) { MainWindow window = new MainWindow(); window.Show(); } }
Sometimes, the first instantiated Window is not actually the main application window e.g. a splash screen. In this case, you can specify the main application window using markup, like the following:
<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" StartupUri="StartupWindow.xaml" > <Application.MainWindow> <NavigationWindow Source="MainPage.xaml" Visibility="Visible"></NavigationWindow> </Application.MainWindow> </Application>
Whether the main window is specified automatically or manually, you can get the main window from MainWindow using the following code, like the following:
How to: Open a Dialog Box
This example shows how to open a dialog box.
Example
A dialog box is a window that is opened by instantiating Window and calling the ShowDialog method. ShowDialog opens a window and doesn't return until the new dialog box has been closed. This type of window is also known as a modal window, and restricts user input.
.NET Framework Security
Calling ShowDialog requires permission to use all windows and user input events without restriction.
How to: Open a Message Box
This example shows how to open a message box.
Example
A message box is a prefabricated modal dialog box for displaying information to users. A message box is opened by calling the static Show method of the MessageBox class. When Show is called, the message is passed using a string parameter. Several overloads of Show allow you to configure how a message box will appear (see MessageBox).
How to: Open a Window
This example shows how to open a window.
How to: Return a Dialog Box Result
This example shows how to retrieve the dialog result for a window that is opened by calling ShowDialog.
Example
Before a dialog box closes, its DialogResult property should be set with a Nullable<T> Boolean that indicates how the user closed the dialog box. This value is returned by ShowDialog to allow client code to determine how the dialog box was closed and, consequently, how to process the result.
Note |
---|
DialogResult can only be set if a window was opened by calling ShowDialog. |
DialogBoxWithResult dialogBoxWithResult = new DialogBoxWithResult(); // Open dialog box and retrieve dialog result when ShowDialog returns bool? dialogResult = dialogBoxWithResult.ShowDialog(); switch (dialogResult) { case true: // User accepted dialog box break; case false: // User canceled dialog box break; default: // Indeterminate break; }
.NET Framework Security
Calling ShowDialog requires permission to use all windows and user input events without restriction.
Navigation Overview
https://msdn.microsoft.com/en-us/library/ms750478(v=vs.110).aspx
'프로그래밍 > WPF' 카테고리의 다른 글
WPF 고급 - 입력 (Input) (0) | 2016.10.15 |
---|---|
ObservableCollection<T>, INotifyPropertyChanged Interface (0) | 2016.10.15 |
WPF 고급 - 아키텍처, XAML (0) | 2016.09.23 |
Data Binding (WPF) (0) | 2016.09.04 |
Windows Presentation Foundation (0) | 2016.08.26 |