레이블이 WPFHelloWorld인 게시물을 표시합니다. 모든 게시물 표시
레이블이 WPFHelloWorld인 게시물을 표시합니다. 모든 게시물 표시

2021년 11월 20일 토요일

(C#, WPF 동영상, WPF교육)WPF학원가지말고 혼자 해보세요, WPF란, WPF개요, WPF HelloWorld!, C#코드기반, XAML기반

 

(C#, WPF 동영상, WPF교육)WPF학원가지말고 혼자 해보세요, WPF란, WPF개요, WPF HelloWorld!, C#코드기반, XAML기반

http://ojc.asia/bbs/board.php?bo_table=WPF&wr_id=154 


(C#, WPF 동영상)WPF란, WPF개요, WPF HelloWorld!, C#코드기반, XAML기반

(C#, WPF 동영상)WPF란, WPF개요, WPF HelloWorld!, C#코드기반, XAML기반1.1 WPF 소개? XAML기반 HelloWorld 따라하기2002년 정식으로 출시된닷넷 프레임워크에서 윈폼 이라는 기술이 등장하여 윈도우 응용프로그

ojc.asia



https://www.youtube.com/watch?v=innYXvo9WpA&list=PLxU-iZCqT52Cmj47aKB1T-SxI33YL7rYS&index=2&t=29s 

https://www.youtube.com/watch?v=vlVKwC1ALmM&list=PLxU-iZCqT52Cmj47aKB1T-SxI33YL7rYS&index=4&t=37s1.1 WPF 소개?  XAML기반 HelloWorld 따라하기


  • 2002년 정식으로 출시된 닷넷 프레임워크에서 윈폼 이라는 기술이 등장하여 윈도우 응용프로그램 개발을 주도했지만 요구가 다양해지면서 비디오, 미디어, 애니메이션, 2D, 3D그래픽 등을 다이나믹하게 사용할 수 있기를 원했지만 기존의 윈도우 플랫폼들에서 독립된 기술들로 분산되어 있었고 여러 다른 기술들을 각각 모두 이해해야만 통합된 개발이 가능했다. 결국 통합된 기술이 필요했는데 이러한 요구에서 만들어진 기술이 바로 WPF(Windows Presentation Foundation) 이다.
  • WPF는 닷넷3.X부터 추가된 기술로  Vista에서 UX를 구현하기 위해 탄생되었으며 비주얼 스튜디오 2008에 추가 되었다.
  • 시각적으로 뛰어난 사용자 환경에서 윈도우 응용 프로그램을 만들 수 있는 차세대 프레젠테이션 시스템으로 WPF를 이용하면 광범위한 독립 실행형 응용 프로그램과 브라우저에서 호스팅되는 응용 프로그램을 모두 만들 수 있다.
  • WPF를 사용하여 Extensible Application Markup Language (XAML), 컨트롤, 데이터 바인딩, 레이아웃, 2-D 및 3-D 그래픽, 애니메이션, 스타일, 템플릿, 문서, 미디어, 텍스트, 입력 체계 등의 광범위한 응용 프로그램 개발이 가능하다.
  • 클래스를 인스턴스화한 후 속성을 설정하고, 메서드를 호출하고, 이벤트를 처리하는 등의 모든 작업을 C#, VB.NET등의 익숙한 .NET Framework 프로그래밍 언어로 수행할 수 있다.
  • WPF는 대부분 System.Windows 네임스페이스에 있는 클래스, 인터페이스들을 다룬다.            


  • WPF의 아키텍처는 실제로 다층 아키텍처로 WPF Managed Layer, WPF Unmanaged Layer 및 Core operating system 요소의 세 가지 레이어가 있으며 이러한 레이어는 전체 프레임 워크를 모으는 어셈블리 집합으로 해석할 수 있다.
  • Managed Layer : Presentation Framework, Presentation Core 및 Window Base는 Managed Layer의 세 가지 주요 구성 요소로 공개 API는이 레이어를 통해서만 노출된다.


PresentationFramework.dll : 응용 프로그램을 빌드하는 데 필요한 응용 프로그램의 Windows, Panels, Styles Controls, Layouts, Content 등과 같은 고급 기능이 포함되어 있으며 data binding, time-dependencis, animation 등을 비롯한 최종 사용자 프레젠테이션 기능을 구현한다. (대부분의 클래스가 여기에 해당 된다.)


PresentationCore.dll : 2D, 3D, 기하학 등의 기능을 제공하는 WPF에 의해 노출 된 Low Level급 API 이다. 모든 도형들의 개체와 컨트롤이 파생되는 UIElement 타입과 Visual 타입을 포함한다. Presentation Core는 MILCore를 관리하는 래퍼 역할을하며 MIL(Media Integration Layer)용 공용 인터페이스를 제공한다. Presentation Core는 WPF Visual System의 기본이며 응용 프로그램 비주얼 트리를 만드는 데 필요한 클래스를 제공한다. Visual System은 Visual Elements 및 렌더링을 위한 응용 프로그램이 포함 된 시각적 트리를 만든다.


WindowsBase.dll : Dispatcher Objects 및 Dependency Objects와 같은 WPF 환경 외부에서 재사용 할 수 있는 요소를 보유하고 있다.


  • Unmanaged Layer : 


milCore.dll : WPF 렌더링의 핵심, WPF 응용 프로그램을 렌더링 하는 컴포지션 엔진의 기본 구성 요소로 Media Integration Layer (MIL)라고하며 milCore.dll에 존재한다. milCore의 목적은 DirectX와 직접 인터페이스하여 2D 및 3D 표면에 대한 기본 지원을 제공한다. 즉 DirectX와 CLR (더하기 레이어 이상) 간의 인터페이스로 MILCORE는 DirectX의 도움으로 2D, 3D, 애니메이션을 처리하는 Unmanaged 구성 요소 이다. Window Vista, 7의 필수적인 구성요소로 WPF에서의 모든 디스플레이는 DirectX 엔진을 통해 수행되므로 효율적인 하드웨어 및 소프트웨어 렌더링을 허용한다. 


WindowsCodecs.dll : 이미지 처리, 이미지 표시 및 크기 조정 등과 같은 WPF 응용 프로그램의 이미징 지원을 위한 Low Level API로 WPF 화면으로 렌더링 될 벡터 그래픽으로 이미지를 인코딩 / 디코딩하는 여러 코덱으로 구성된다.


DirectX : WPF에서 모든 그래픽을 렌더링하는 Low Level API로 드라이버와 대화하고 내용을 렌더링 한다.


User32 : 메모리와 프로세스 분리를 ​​관리하는데 모든 응용 프로그램에서 사용하는 기본 핵심 API로 어떤 요소가 화면의 어디에 배치 될지등을 결정한다.


GDI : 그래픽 장치 인터페이스(Graphic Device Interface)의 약자로 확장 된 그래픽 프리미티브 세트와 렌더링시 퀄리티 향상을 제공한다.


CLR : WPF는 전체 .NET Framework를 활용하고 CLR (Common Language Runtime)에서 실행된다.


Device Drivers : 운영 체제에 따라 다르며 저수준 API에 액세스하는 데 사용된다.

  • 일반적으로 XAML 태그는 UI를 구현하는 데 사용되고 C# 비하인드 코드로 프로그램의 동작을 구현한다.
  • XAML은 선언적으로 UI를 구현하는 데 사용되는 XML 기반 태그 언어로 일반적으로 창, 대화 상자, 페이지 및 사용자 정의 컨트롤을 만들고 이러한 항목을 컨트롤, 도형 및 그래픽으로 채우는 데 사용된다.

WPF 클래스 계층구조


  • System.Object

기본적인 WPF 프로그래밍 모델은 Managed Code를 통해 노출되는데 그 최상위에 System.Object가 존재 한다. CLR에서는 보다 생산적이며 강력한 개발 작업을 수행하는 데 유용한 여러 기능(메모리 관리, 오류 처리, 공용 형식 시스템 등)을 제공한다.


  • System.Threading.DispatcherObject

WPF는 단일 쓰레드 모델(STA)를 사용하는데 유저 인터페이스 전체를 하나의 쓰레드가 소유하는 것을 의미하며 이를 위해서 디스패처의 지배를 받는다. 대부분의 개체는 동시성 및 쓰레드 처리를 위한 기본구문을 제공하는 DispatcherObject에서 파생된다. 디스패처는 우선 순위가 지정된 여러 개의 큐가 있는 시스템으로 마우스 이동, 프레임워크 기능(레이아웃), 사용자의 메서드 실행하고자 하면 DispatcherObject를 상속받아 STA 쓰레드로 CLR 개체를 만들면 생성 시 디스패처에 포인터가 지정되고 관리를 받게된다.


  • System.Windows.DependencyObject

데이터 바인딩을 사용하기 위해서는 바인드의 양쪽(소스, 타겟)이 변화에 대한 알림을 지원해야 한다. 어떤 메소드가 속성 값에 연결되려면 속성 값이 변경될 때 알림을 받아야 하는데 닷넷 프레임워크에서 개체가 속성의 변화를 알릴 수 있는 INotifyPropertyChanged 인터페이스가 있지만 이것은 선택사항이다.


데이터 바인딩에 의존속성(Dependency Property)이 사용되는데 이 의존속성을 래핑하는 클래스에서 DependencyObject를 상속받고 의존속성을 싸고 있는 속성 등에서 DependencyObject의 GetValue, SetValue 메소드를 호출하여 외부로 값을 주거나 외부로부터 입력되는 값으로 의존속성을 설정한다. 이부분은 데이터바인딩 부분에서 살펴보자.


  • System.Windows.Media.Visual

WPF 시스템이 정의되면 다음 단계는 화면에서 픽셀을 그리는 것인데 Visual 클래스는 시각적 개체들을 빌드하기 위해 렌더링하는 방법에 대한 메타데이터를 제공한다. Visual은 매우 간단하고 유연하므로 대부분의 기능에 공개 API 노출이 없고 이러한 기능이 보호되는 콜백 기능에 크게 의존한다.


Visual은 WPF 컴퍼지션 시스템의 진정한 진입점으로 두 하위 시스템인 Managed API와 UnManaged milcore 사이의 연결 지점이다.


  • System.Windows.UIElement

UIElement는 레이아웃, 입력 및 이벤트를 비롯한 핵심 하위 시스템을 정의한다.

레이아웃은 WPF의 핵심 개념으로 대부분의 시스템에는 고정된 레이아웃이 있거나 레이아웃 모델이 아예 없다(User32는 실제로 절대 위치 지정만 지원). 


  • System.Windows.FrameworkElement

WPF 요소에 WPF 프레임워크 수준의 속성, 이벤트 및 메서드 집합을 제공한다. 이 클래스는 UIElement에 정의된 몇가지 멤버에 대해 구현을 했다.





System.Object

  System.Windows.Threading.DispatcherObject

    System.Windows.DependencyObject

      System.Windows.Media.Visual

        System.Windows.UIElement

          System.Windows.FrameworkElement

                 ….. 여러 컨트롤들






간단히 XAML기반 WPF HelloWorld를 만들어 보자.


  1. Visual Studio 2017에서 Visual C# >> WPF 앱(.NET Framework)을 선택 후 프로젝트명은 WpfApp2으로 하자.


  1. MainWindow.xaml을 더블클릭하여 XAML 디자인 화면을 열어서 Label, TextBox, Button 컨트롤을 그림처럼 배치하자. (TextBox : “txtName”, Button : “btnSayHello”)


  1. 컨트롤을 올려서 완성된 MainWindow.xaml 코드

<Window x:Class="WpfApp2.MainWindow"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

        xmlns:local="clr-namespace:WpfApp2"

        mc:Ignorable="d"

        Title="MainWindow" Height="181.2" Width="503.4">

    <Grid Margin="0,0,0.4,1.8">

        <Label x:Name="label" Content="이름을 입력하세요." HorizontalAlignment="Left" Margin="64,55,0,0" VerticalAlignment="Top" Height="34" Width="135" FontSize="14"/>

        <TextBox x:Name="txtName" HorizontalAlignment="Left" Height="34" Margin="204,55,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/>

        <Button x:Name="btnSayHello" Content="Say Hello!" HorizontalAlignment="Left" Margin="329,55,0,0" VerticalAlignment="Top" Width="75" Height="34" Click="btnSayHello_Click"/>

    </Grid>

</Window>


  1. 버튼을 클릭하고 속성항에서 번개표시를 누르면 이벤트들이 나타나는데 Click 이벤트를 더블클릭 하여 이벤트 핸들러를 작성하자.


private void btnSayHello_Click(object sender, RoutedEventArgs e)

{

    MessageBox.Show("Hello " + txtName.Text); 

}


  1. 완성된 MainWindow.xaml.cs

using System.Windows;


namespace WpfApp2

{

public partial class MainWindow : Window

    {

        public MainWindow()

        {

            InitializeComponent();

        }


        private void btnSayHello_Click(object sender, RoutedEventArgs e)

        {

            MessageBox.Show("Hello " + txtName.Text);

        }

    }

}


  1. 실행화면(F5)

1.2 HelloWorld XAML기반 WPF 프로그램 작동 원리


  • WPF 프로젝트를 생성하면 App.xaml, MainWindow.xaml 두개의 xaml 파일이 생성되는데 App.xaml이 App 라는 클래스로 메인 메소드(Main)를 가지면서 자동 생성되고 이 메인에서 MainWindow를 StartupUri로 지정해서 MainWindow가 처음 시작된다.
  • App.xaml이 엔트리 포인트이며 앞에서 작성한 HelloWorld 프로젝트에서 App.g.cs 파일로 변환되어 생성된다. (App.g.i.cs 파일도 생성되는데 임시 파일로 보면 된다.)
  • [App.g.cs]

#pragma checksum "..\..\App.xaml" "{406ea660-64cf-4c82-b6f0-42d48172a799}" "72192FBCE1E41E0B66442FD984320E84"

//------------------------------------------------------------------------------

// <auto-generated>

//     이 코드는 도구를 사용하여 생성되었습니다.

//     런타임 버전:4.0.30319.42000

//

//     파일 내용을 변경하면 잘못된 동작이 발생할 수 있으며, 코드를 다시 생성하면

//     이러한 변경 내용이 손실됩니다.

// </auto-generated>

//------------------------------------------------------------------------------


using System;

using System.Diagnostics;

using System.Windows;

using System.Windows.Automation;

using System.Windows.Controls;

using System.Windows.Controls.Primitives;

using System.Windows.Data;

using System.Windows.Documents;

using System.Windows.Ink;

using System.Windows.Input;

using System.Windows.Markup;

using System.Windows.Media;

using System.Windows.Media.Animation;

using System.Windows.Media.Effects;

using System.Windows.Media.Imaging;

using System.Windows.Media.Media3D;

using System.Windows.Media.TextFormatting;

using System.Windows.Navigation;

using System.Windows.Shapes;

using System.Windows.Shell;

using WpfApp2;



namespace WpfApp2 {

    

    

    /// <summary>

    /// App

    /// </summary>

    public partial class App : System.Windows.Application {

        

        /// <summary>

        /// InitializeComponent

        /// </summary>

        [System.Diagnostics.DebuggerNonUserCodeAttribute()]

        [System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "4.0.0.0")]

        public void InitializeComponent() {

            

            #line 5 "..\..\App.xaml"

            this.StartupUri = new System.Uri("MainWindow.xaml", System.UriKind.Relative);

            

            #line default

            #line hidden

        }

        

        /// <summary>

        /// Application Entry Point.

        /// </summary>

        [System.STAThreadAttribute()]

        [System.Diagnostics.DebuggerNonUserCodeAttribute()]

        [System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "4.0.0.0")]

        public static void Main() {

            WpfApp2.App app = new WpfApp2.App();

            app.InitializeComponent();

            app.Run();

        }

    }

}


  • App.xaml의 코드 비하인드 파일이 App.xaml.cs로 하나의 App라는 이름의 부분 클래스로 생성된다.
  • 만약 App.xaml StartupUri을 삭제하면 App.xaml.cs 소스코드에서 아래처럼 OnStartUp 메소드를 오버라이드 하면 된다.

public partial class App : Application

{

    protected override void OnStartup(StartupEventArgs e)

    {

        base.OnStartup(e);

        // here you take control

    MainWindow w = new MainWindow();

    w.Show();

    }

}


  • 물론 App.xaml, App.xaml.cs 파일을 모두 삭제하고 새로운 메인을 만들어도 된다.



[MyMain.cs]

using System;

using System.Windows;


namespace WpfApp2

{

    class MyMain

    {

        [STAThread]

        public static void Main()

        {

            Application app = new Application();

            app.Run(new MainWindow());

        }

    } 

}


  • 만약 응용프로그램에서 Main 메소드를 가지는 클래스가 여러 개 라면 프로젝트의 속성에서 시작 클래스를 지정할 수도 있다.



-----------------------------------------------------------------------------------------------------------



1.4 WPF HelloWorld-2(C#코드 기반)

  • Visual Studio File -> New -> Project -> Visual C# -> WPF 응용프로그램

프로젝트명 : HelloWorld2

  • App.xaml, MainWindow.xaml 삭제
  • 프로젝트 >> 추가 >> 새항목에서 MyMain.cs 파일 추가



[MyMain.cs]

using System;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Input;


namespace HelloWorld2

{

    class MyMain : Application

    {

        [STAThread]

        public static void Main()

        {

            MyMain app = new MyMain();

            app.ShutdownMode = ShutdownMode.OnLastWindowClose;

            app.Run();

        }


        protected override void OnStartup(StartupEventArgs e)

        {

            base.OnStartup(e);


            Window mainWindow = new Window();

            mainWindow.Title = "WPF Sample(Main)";

            mainWindow.MouseDown += WinMouseDown;

            mainWindow.Show();


            for (int i = 0; i < 2; i++)

            {

                Window win = new Window();

                win.Title = "Extra Window No." + (i + 1);

                win.Show();

            }

        }


        void WinMouseDown(Object sender, MouseEventArgs args)

        {

            Window win = new Window();

            win.Title = "Modal DialogBox";

            win.Width = 400;

            win.Height = 200;


            Button b = new Button();

            b.Content = "Click Me!";

            b.Click += Button_Click;


            win.Content = b;

            win.ShowDialog();  //Modal 형태

        }


        private void Button_Click(object sender, EventArgs e)

        {

            MessageBox.Show("Button Click!", sender.ToString());

        }

    }

}



  • 실행화면(F5)



[코드설명]

  • using System.Windows : 이 네임스페이스에는 Application, Window를 포함한 WPF 클래스, 구조체, 인터페이스, 열거형들을 포함한다.


  • WPF Main에는 [STAThread] 속성이 반드시 나타나야 하며 그렇지 않다면 InvalidOperationException이 발생한다. STAThread는 최초 응용프로그램을 Single-Thread Apartment로 실행한다는 의미이며, COM과 같이 사용되는 경우에 쓰이게 되서 응용프로그램이 멀티쓰레드를 허용하지 않는다는 의미로 사용된다. 일반적인 C# 응용프로그램은 기본적으로 Multi-Thread Apartment이다. 


  1. 일반적으로 C#에서 STA를 사용하는 경우는 싱글 쓰레드로만 동작되는 COM 객체를 사용하는 경우인데 드래그 드롭 기능, 클립보드 관련 기능, OpenDialog, SaveFileDialog, 웹브라우저 컨트롤 등을 사용하는 경우 반드시 STAThread로 동작되어야 한다.


  • 프로젝트에서 우측 마우스 클릭 후 속성창에서 실행형태를 Console로 하면 Console 창도 같이 뜨면서 실행되는데 이는 실행중이거나 디버깅시 Console.Wirte등을 이용하여 텍스트를 출력해 볼 수 있으므로 유용하다.



가령 윈도우 프로그램을 잘못짜서 무한 루프에 빠지게 했다면 콘솔창에서 Ctrl + C 키로 종료할 수 있다. 만약 콘솔창이 없다면 윈도우는 먹통이 되어서 중단시키기도 불편하다


  • 응용프로그램의 시작이 되는 클래스는 Application 클래스를 상속받아야 하며 해당 인스턴스의 Run() 메소드를 통해 응용프로그램이 시작한다. 


위 예제에서 Application 클래스를 상속받지 않는 형태로 윈도프로그램을 시작하려면 OnStartUp을 오버라이드 하지 않고 메인에서 다음과 같이 하면 된다.


using System;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Input;


namespace HelloWorld2

{

    class MyMain

    {

        [STAThread]

        public static void Main()

        {

            Window mainWindow = new Window();

            mainWindow.Title = "WPF Sample(Main)";

            mainWindow.MouseDown += WinMouseDown;

            //mainWindow.Show();


            for (int i = 0; i < 2; i++)

            {

                Window win = new Window();

                win.Title = "Extra Window No." + (i + 1);

                win.Show();

            }


            // WPF Samplw(Main) 윈도우를 맨 마지막에 띄움

            Application app = new Application();

            app.Run(mainWindow);

        }


        static void WinMouseDown(Object sender, MouseEventArgs args)

        {

            Window win = new Window();

            win.Title = "Modal DialogBox";

            win.Width = 400;

            win.Height = 200;


            Button b = new Button();

            b.Content = "Click Me!";

            b.Click += Button_Click;


            win.Content = b;

            win.ShowDialog();

        }


        static void Button_Click(object sender, EventArgs e)

        {

            MessageBox.Show("Button Click!", sender.ToString());

        }

    } 

}


Application 클래스는 하나의 프로젝트에서 하나만 사용 가능하고 Window는 보이지만 Application 객체는 보이지 않는다. Window 객체의 Show() 메소드를 호출하는 대신 Run() 메소드의 인자로 넘겨도 된다. App.Run(win); 이 경우 Run() 메소드는 win 객체의 Show()를 호출하는 것까지 담당한다.


응용프로그램은 Run() 메소드가 실행되기 전까지 실제 시작되지 않으며 호출된 후에 Window 객체가 사용자의 입력에 반응을 할 수 있다. 사용자가 창을 닫고 Run() 메소드를 종료하면 프로그램은 종료를 준비한다.


C# 윈폼, WPF 응용프로그램에서 프로그램이 대체로 하는 일은 사용자의 이벤트에 기반해서 프로그램이 작동되는데 이벤트란 키보드, 마우스, 스타일러스 팬의 입력을 의미한다. UIElement 클래스는 키보드, 마우스, 스타일러스 팬의 입력과 관련된 몇가지의 이벤트가 정의되어 있는데 Window 클래스는 이 모든 이벤트를 상속받는다. 본 예제에서는 이벤트 중 버튼 클릭, 마우스 다운과 관련된 이벤트를 사용하였다.


  • MouseDown 이벤트에서 첫 번째 인자는 object형의 이벤트 발생 객체이며 두 번째 인자인 MouseEventArgs는 마우스 관련 이벤트가 발생했을 때 넘어오는 데이터, 즉 왼쪽 또는 오른쪽 버튼을 눌렀는지, 몇 번 눌렀는지 등이 넘어오게 된다. 이 클래스는 System.Windows.Input 네임스페이스에 정의되어 있으므로 using문으로 선언을 해야 한다.


  • MessageBox 클래스는 System.Windows 네임스페이스에 정의되어 있으며 사용자에게 어떤 메시지를 보여주기 위한 것으로 대화상자라고 부른다. 


  • Application 클래스는 유용한 몇 가지 이벤트가 정의되어 있는데 닷넷의 관례대로 대부분의 이벤트는 이를 처리하는 protected 메소드와 연관이 되어 있다. StartUp 이벤트는 OnStartUp 메소드와 연관되고 Run() 메소드가 호출된 직후에 실행된다. Run() 메소드가 리턴되기 전에 Exit 이벤트가 발생되고 이에 대응되는 OnExit() 메소드가 호출되게 된다.


사용자가 윈도우를 로그오프 하거나 컴퓨터를 종료시킬 때는 SessionEnding 이벤트가 발생한다. 이때 인자로 SessionEndingCancelEventArgs 타입의 이벤트 데이터를 넘기는데 만약 윈도우가 종료되는 것을 방지하고 싶다면 Cancle 프로퍼티로 설정하면 된다. 


* 참고로 출력형식을 콘솔이 아닌 Window 응용 프로그램으로 컴파일한 경우에만 SessionEnding 이벤트를 받을 수 있다.

 

  • OnStartUp에서 생성된 윈도우는 이 응용프로그램 내에서 모두 동등하다고 할 수 있는데 어떤 창이라도 클릭하면 전면으로 나오게 되고 임의의 순서대로 닫을 수 있으며 마지막 창이 종료되면 프로그램은 종료된다. 


예제를 실행하면 하단 태스크바에 윈도우 아이콘 세개가 나타나는데 하나만 나타나게 하려면 for 루프에 다음 코드를 추가하면 된다.


win.ShowInTaskbar = false;


하지만 문제가 하나 있다. Extra Window.1, 2가 떠있더라도 “WPF Sample(Main)” 메인 윈도우가 닫히면 태스크바 아이콘이 사라진다. 일반적으로 Run() 메소드가 리턴될 때 프로그램이 종료된다. 


마지막 창을 닫을 때 Run() 메소드가 리턴되므로 이러한 동작은 Application의 ShutdownMode 프로퍼티를 어떻게 설정하느냐에 따라 다르게 동작하는데 열거형 멤버로 설정한다. 기본값은 ShutdownMode.OnLastWindowClose 이며 마지막 윈도우가 닫힐 때 프로그램이 종료되는 것으로 값을 OnMainWindowClose로 변경하여 다시 실행해 보자. Run() 메소드를 호출하기전에 아래 코드를 삽입 후 실행하여 결과를 확인하자.


// “WPF Sample(Main)” 윈도우 닫을 때 서브 윈도우 같이 닫힌다.

app.ShutdownMode = ShutdownMode.OnMainWindowClose;


OnStartUp() 메소드에 다음처럼 삽입해도 동일한 결과를 얻는다.

this.ShutdownMode = ShutdownMode.OnMainWindowClose;


위 코드를 그대로 두고 for 루프안에서 아래처럼 설정해보자.

this.MainWindow = win;


결론적으로 for문에서 마지막에 뜨는 윈도우가 메인 윈도우가 되므로 이 창을 닫으면 프로그램이 종료된다. 마지막으로 ShutdownMode에 대입가능한  ShutdownMode.OnExplicitShutdown 값이 있는데 Application 클래스의 Shutdown 메소드를 명시적으로 호출하는 경우에만 응용프로그램이 종료된다.


이번에는 여러 창의 계층구조를 만드는 방법에 대해 살펴보자.


Window 클래스의 Owner 속성을 이용하는데 여기에 다른 윈도우 객체를 대입하면 된다. for 루프에 다음코드를 추가해 보자.

//메인창이 나머지 두 개의 창을 소유한 Owner가 된다.

win.Owner = mainWindow;  


소유된 창이 소유한 창앞에 나타나게 되어 있으며 Owner를 최소화 시키면 하위 창들도 자동으로 최소화 되고 닫으면 같이 닫힌다.


  • 솔루션 탐색기의 참조에는 PresentationCore, PresentationFramework. System, WindowsBase등은 기본적으로 포함되어 있어야 한다. 


#WPF강좌, #WPF교육, #WPFHelloWorld, #WPD강좌, #WPF학원, #WPF동영상, #WPF헬로월드

WPF강좌, WPF교육, WPFHelloWorld, WPD강좌, WPF학원, WPF동영상, WPF헬로월드 

(C#교육동영상)C# ADO.NET 실습 ODP.NET/ODAC 설치 오라클 함수 호출 실습, C#학원, WPF학원, 닷넷학원, 자바학원

  (C#교육동영상)C# ADO.NET 실습  ODP.NET/ODAC 설치  오라클 함수 호출 실습, C#학원, WPF학원, 닷넷학원, 자바학원 https://www.youtube.com/watch?v=qIPU85yAlzc&list=PLxU-i...