Опубликован: 05.08.2010 | Доступ: свободный | Студентов: 2010 / 47 | Оценка: 4.50 / 4.40 | Длительность: 60:26:00
Самостоятельная работа 8:

Создание приложений WPF

Упражнение 3. Множественные окна в WPF

Одно и то же приложение может создавать несколько окон, которые одновременно могут быть открыты. Если этим окнам не назначен владелец, то при закрытии порождающего окна они так и останутся открытыми. Это можно проверить и на последнем примере, если выполнить следующее

  • Заменить в обработчике LifeEvents() файла Window0.axml.cs код модального открытия окна wnd1.ShowModal() ; на wnd1.Show() ;
  • Запустить приложение и из окна Window0 открыть несколько экземпляров окна Window1, затем закрыть окно Window0

После таких действий все дочерние окна остаюся открытыми и их нужно закрывать вручную (если только мы их запускали не из под оболочки). К тому же пиктограммы окон не отображаются в панели задач и стоит нам перекрыть экран другим окном, то эти окна придется закрывать либо, предварительно свернув все другие окна, либо через диспетчер задач.


Такое поведение не совсем хорошее, поэтому разработчики платформы WPF предусмотрели в объекте Application соответствующие средства. Мы их рассмотрим в данном упражнении.

  • Добавьте к решению новый WPF-проект с именем WpfApp3 и назначьте его стартовым

  • В панели Solution Explorer удалите из проекта WpfApp3 файл с автоматически созданным именем Window1.xaml и добавьте новый файл с именем WindowList.xaml (чтобы не переименовывать во многих местах)

  • Откройте файл App.xaml проекта WpfApp3 и поменяйте значение параметра StartupUri объекта Application на имя файла нового стартового окна
<Application x:Class="WpfApp3.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    StartupUri="WindowList.xaml"
             >
</Application>
  • Откройте файл WindowList.xaml в режиме View XAML и настройте стартовое окно следующим образом
<Window x:Class="WpfApp3.WindowList"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="WindowList"
    SizeToContent="WidthAndHeight"  
    MinWidth="200"
        >
    <StackPanel>
        <Button Click="NewWindowClicked">Создать новое окно</Button>
        <Button Click="ListOpenWindows">Список открытых окон</Button>
    </StackPanel>
</Window>
  • Проследите, чтобы одновременно были созданы зарегистрированные в кнопках обработчики
  • Модифицируйте файл WindowList.xaml.cs следующим образом
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
    
namespace WpfApp3
{
    /// <summary>
    /// Interaction logic for WindowList.xaml
    /// </summary>
    public partial class WindowList : Window
    {
        static int createCount;
        public WindowList()
        {
            InitializeComponent();
    
            // Определение заголовка окна
            this.Title = "Окно № " + (createCount++).ToString();
        }
    
        private void NewWindowClicked(object sender, RoutedEventArgs e)
        {
            new WindowList().Show();
        }
    
        private void ListOpenWindows(object sender, RoutedEventArgs e)
        {
            StringBuilder sb = new StringBuilder();
            foreach (Window openWindow in Application.Current.Windows)
                sb.AppendLine(openWindow.Title);
    
            MessageBox.Show(sb.ToString(), "Открытые окна приложения");
        }
    }
}
  • Запустите приложение - оно хранит и выдает список открытых в текущий момент окон


Однако все окна, открытые приложением, приходится по-прежнему закрывать вручную. Для решения этой проблемы есть два пути:

  1. Назначить какое-нибудь из открытых окон главным, присвоив свойству Application.Current.MainWindow ссылку на это окно
  2. Использовать метод Application.Current.Shutdown()

Какой из этих двух вариантов будет работать, определяет свойство Application.Current.ShutdownMode. Оно может принимать одно из следующих значений одноименного перечисления:

  1. ShutdownMode.OnLastWindowClose - закрывать приложение вместе с закрытием последнего окна (установлено по умолчанию)
  2. ShutdownMode.OnMainWindowClose - закрывать приложение вместе с закрытием главного окна
  3. ShutdownMode.OnExplicitShutdown - закрывать приложение только тогда, когда явно вызван метод Shutdown()

Приложение в режиме ShutdownMode.OnExplicitShutdown может закрыться только методом Shutdown(), но и в двух предыдущих режимах метод Shutdown() работает всегда.

Испытаем оба способы. Для разнообразия сделаем главным окно под номером 3, а во все окна добавим кнопку вызова метода Shutdown().

  • Откройте файл WindowList.xaml в режиме View XAML и добавьте к стартовому окну еще одну кнопку
<Window x:Class="WpfApp3.WindowList"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="WindowList"
    SizeToContent="WidthAndHeight"  
    MinWidth="200"
        >
    <StackPanel>
        <Button Click="NewWindowClicked">Создать новое окно</Button>
        <Button Click="ListOpenWindows">Список открытых окон</Button>
        <Button Click="AllCloseWindows">Закрыть все окна</Button>
    </StackPanel>
</Window>
  • Проследите, чтобы одновременно был создан зарегистрированный в кнопке обработчик
  • Модифицируйте файл WindowList.xaml.cs следующим образом
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
    
namespace WpfApp3
{
    /// <summary>
    /// Interaction logic for WindowList.xaml
    /// </summary>
    public partial class WindowList : Window
    {
        static int createCount;
        public WindowList()
        {
            InitializeComponent();
    
            // Определение заголовка окна и назначение главного окна
            if (createCount == 3)
            {
                Application.Current.ShutdownMode = ShutdownMode.OnMainWindowClose;
                Application.Current.MainWindow = this;
                this.Title = "Главное окно № " + (createCount++).ToString();
            }
            else
                this.Title = "Окно № " + (createCount++).ToString();
        }
    
        private void NewWindowClicked(object sender, RoutedEventArgs e)
        {
            new WindowList().Show();
        }
    
        private void ListOpenWindows(object sender, RoutedEventArgs e)
        {
            StringBuilder sb = new StringBuilder();
            foreach (Window openWindow in Application.Current.Windows)
                sb.AppendLine(openWindow.Title);
    
            MessageBox.Show(sb.ToString(), "Открытые окна приложения");
        }
    
        private void AllCloseWindows(object sender, RoutedEventArgs e)
        {
            //Application.Current.ShutdownMode = ShutdownMode.OnExplicitShutdown;
            Application.Current.Shutdown();// Закрывает при любом режиме
        }
    }
}
  • Запустите приложение и убедитесь, что оно в любом месте закрывается методом Shutdown(), а также при закрытии третьего окна

Если установить режим ShutdownMode.OnExplicitShutdown, то приложение можно завершить только методом Shutdown().

Алексей Бабушкин
Алексей Бабушкин

При выполнении в лабораторной работе упражнения №1 , а именно при выполнении нижеследующего кода:

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

using Microsoft.Xna.Framework.Graphics;

   

namespace Application1

{

    public partial class MainForm : Form

    {

        // Объявим поле графического устройства для видимости в методах

        GraphicsDevice device;

   

        public MainForm()

        {

            InitializeComponent();

   

            // Подпишемся на событие Load формы

            this.Load += new EventHandler(MainForm_Load);

   

            // Попишемся на событие FormClosed формы

            this.FormClosed += new FormClosedEventHandler(MainForm_FormClosed);

        }

   

        void MainForm_FormClosed(object sender, FormClosedEventArgs e)

        {

            //  Удаляем (освобождаем) устройство

            device.Dispose();

            // На всякий случай присваиваем ссылке на устройство значение null

            device = null;       

        }

   

        void MainForm_Load(object sender, EventArgs e)

        {

            // Создаем объект представления для настройки графического устройства

            PresentationParameters presentParams = new PresentationParameters();

            // Настраиваем объект представления через его свойства

            presentParams.IsFullScreen = false; // Включаем оконный режим

            presentParams.BackBufferCount = 1;  // Включаем задний буфер

                                                // для двойной буферизации

            // Переключение переднего и заднего буферов

            // должно осуществляться с максимальной эффективностью

            presentParams.SwapEffect = SwapEffect.Discard;

            // Устанавливаем размеры заднего буфера по клиентской области окна формы

            presentParams.BackBufferWidth = this.ClientSize.Width;

            presentParams.BackBufferHeight = this.ClientSize.Height;

   

            // Создадим графическое устройство с заданными настройками

            device = new GraphicsDevice(GraphicsAdapter.DefaultAdapter, DeviceType.Hardware,

                this.Handle, presentParams);

        }

   

        protected override void OnPaint(PaintEventArgs e)

        {

            device.Clear(Microsoft.Xna.Framework.Graphics.Color.CornflowerBlue);

   

            base.OnPaint(e);

        }

    }

}

Выбрасывается исключение:

Невозможно загрузить файл или сборку "Microsoft.Xna.Framework, Version=3.0.0.0, Culture=neutral, PublicKeyToken=6d5c3888ef60e27d" или один из зависимых от них компонентов. Не удается найти указанный файл.

Делаю все пунктуально. В чем может быть проблема?