Как сделать несколько окон в wpf

Добавил пользователь Евгений Кузнецов
Обновлено: 18.09.2024

Я новичок в wpf.I есть два окна, такие как window1 и window2. У меня есть одна кнопка в окне1. если я нажму эту кнопку, откроется окно2. что я должен делать для этого. Вот код, который я пробовал.

Что вы пробовали? Это основная вещь, которую вы можете найти с помощью поиска, если у вас нет особых проблем, о которых вы не упоминали.

Напишите свой код в window1 .

Вам нужно создать новое приложение WPF. После этого вы должны иметь файл .xaml и файл .cs. Они представляют ваше главное окно. Создайте дополнительный файл .xaml и .cs для представления вашего дополнительного окна.

Это имеет смысл, поскольку запуск приложения представляет собой корень моей композиции.

Окна WPF в моем приложении основаны на моделях представления. Модели просмотра используют внедрение конструктора. Например, я могу составить модель представления, внедрив реализацию IAccountServices .

Когда дело доходит до создания моего главного окна, я могу сделать следующее внутри метода OnStartup:

Оказавшись внутри главного окна, я могу открыть другое окно. Пока мне удалось придумать один способ сделать это, а именно создать фабрику окон и попросить фабрику окон разрешить экземпляр окна. Я должен убедиться, что фабрика окон доступна в каждой модели представления, которая может потребоваться для открытия нового окна. На мой взгляд, это так же плохо, как прохождение контейнера IoC вокруг моего приложения (на ум приходит анти-шаблон локатора сервисов).

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


Я думаю, прежде чем реализовывать шаблоны поведения, такие как a Mediator и т.п., необходимо выбрать общий шаблон для упрощения структуры приложения. Для этой цели, а именно для создания самостоятельных окон, хорошо подходит Abstract factory узор.

Создание окон может быть реализовано сбоку ViewModel с помощью таких методов, как IDialogService . Но я считаю, что эту задачу нужно реализовывать на стороне View , потому что Window объект относится к, View а не к ViewModel . Итак, вы должны создать архитектуру в стиле MVVM, которая позволяет создавать независимые окна с использованием шаблонов проектирования.

Я создал проект, в котором Abstract factory создает окно на стороне, View используя прикрепленное поведение. Abstract factory также реализует шаблон Singleton для создания глобальной точки доступа и обеспечения уникальности вновь созданного объекта. Прикрепленное поведение неявно реализует декоратор шаблона, который является оболочкой для абстрактной фабрики, которая используется на стороне XAML. К Abstract factory не относится к объектам, которые расположены в ViewModel , используется шаблон прокси, который представляет собой ContentControl с DataTemplate без DataType. Также используется Command шаблон для независимых действий между объектами. В результате в этом проекте используются следующие шаблоны:

  • Абстрактная фабрика
  • Синглтон
  • Декоратор
  • Прокси
  • Командование

Структура проекта выглядит так:

введите описание изображения здесь

В прикрепленном поведении есть прикрепленное свойство зависимости Name , которое передается в имени нового окна. Для него прописан PropertyChangedEvent вызов метода Make абстрактной фабрикой:

WindowFactory вместе с паттерном Синглтон выглядит так:

Для свойства Window.ContentTemplate установите DataTemplate из ресурсов. ContentTemplate отвечает за визуальное представление, чтобы связать свойства из ViewModel, вам необходимо установить объект в Content. Но в этом случае Abstract factory ссылка будет на ViewModel и, чтобы избежать их и использовать шаблон прокси следующим образом:

В DataTemplate прокси не указан DataType, но он есть в реальном объекте.

В MainViewModel нем есть команды, чтобы просто установить имя окна, которое будет давать входные данные для прикрепленного поведения:

MainWindow выглядит как:

Тест View-ViewModel для первого окна выглядит так (они практически идентичны):

Это имеет смысл, поскольку запуск приложения представляет собой мой корневой состав.

Окна WPF в моем приложении основаны на моделях просмотра. В моделях модели используются инъекции конструктора. Например. Я могу составить модель представления, введя реализацию IAccountServices .

Когда дело доходит до создания моего главного окна, я могу сделать следующее внутри метода OnStartup:

Как только я окажусь внутри главного окна, я могу открыть другое окно. До сих пор я смог придумать один из способов сделать это: создать окно factory и спросить окно factory для разрешения экземпляра окна. Я должен убедиться, что окно factory доступно в каждой модели представлений, которая может потребоваться для открытия нового окна. На мой взгляд, это так же плохо, как перенос контейнера IoC вокруг моего приложения (на ум приходит анти-шаблон службы поиска).

Этот подход кажется вам правильным? Чувство моего чувства говорит мне, что это неправильно, но я не придумал лучшего способа достичь этого (пока).

ОТВЕТЫ

Ответ 1

Я думаю, что перед тем, как реализовать шаблоны поведения, такие как Mediator и т.п., необходимо принять решение об общем шаблоне для легкой структуры приложения. Для этой цели, а именно для создания независимых окон, хорошо подходит шаблон Abstract factory .

Создание окон может быть реализовано на стороне ViewModel с использованием таких методов, как IDialogService . Но я думаю, что эта задача должна быть реализована на стороне View , потому что объект Window относится к View , а не к ViewModel . Таким образом, вы должны создать архитектуру стиля MVVM, которая позволяет создавать независимые окна с использованием шаблонов проектирования.

Я создал проект, в котором Abstract factory создает окно со стороны View , используя прикрепленное поведение. Abstract factory также реализует шаблон Singleton для создания глобальной точки доступа и обеспечения уникальности вновь созданного объекта. Приложенное поведение неявно реализует шаблон Decorator, который является оберткой для абстрактного factory, который используется на стороне XAML. Для Abstract factory не относится к объектам, расположенным в ViewModel , используется шаблон прокси, который является ContentControl с DataTemplate без DataType. Также используется шаблон Command для независимого действия между объектами. В результате в этом проекте используются следующие шаблоны:

  • Аннотация factory
  • Singleton
  • декоратор
  • Proxy
  • Command

Структура проекта выглядит следующим образом:

enter image description here

WindowFactory вместе с шаблоном Singleton выглядит следующим образом:

Для свойства Window.ContentTemplate установите DataTemplate из ресурсов. ContentTemplate отвечает за визуальное представление, чтобы связать свойства с ViewModel, вам нужно установить объект в Content. Но в этом случае ссылка Abstract factory будет отображаться в ViewModel и избегать их и использовать шаблон прокси-сервера следующим образом:

В DataTemplate прокси не указан DataType, но он находится в реальном объекте.

В MainViewModel есть команды, чтобы просто установить имя окна, которое даст ввод для прикрепленного поведения:

MainWindow выглядит так:

Тест View-ViewModel для первого окна выглядит так (они практически идентичны):

В последних главах руководства мы познакомились с использованием диалоговых окон, встроенных в WPF. Создание собственных так же является довольно простым процессом. Для этого Вам просто необходимо создать Окно, добавить требуемые элементы управления и показать его.

Однако, здесь существует несколько подводных камней, о которых стоит помнить при разработке собственных диалоговых окон, для обеспечения их работы подобно как в других приложениях Windows. В этой статье мы создадим крайне простое окно, для опроса пользователя и возврата его ответа, при этом мы рассмотрим "лучшие практики", которым необходимо следовать.

Проектирование диалогового окна

Я хочу, чтобы Label в моем окне передал пользователю, какую информацию я хочу от него получить (TextBox для ответа) и добавлю стандартные кнопки Ok и Cancel. Еще я решил добавить иконку в окно, для более изящного вида. Вот результат:


А это код диалогового окна:

Код достаточно простой, но в нем есть несколько моментов, на которые стоит обратить внимание:

В разметке XAML я использовал Grid в качестве контейнера для элементов - ничего удивительного. Я удалил свойства Width и Height элемента Window и вместо этого установил их как Auto, для автоматического подбора размера под размеры контента (что, конечно же имеет смысл при проектировании диалогового окна), этот механизм освобождает Вас от необходимости подбора размеров, при сохранении хорошего внешнего вида. Вместо этих свойств используйте поля и минимальные размеры, для того, чтобы диалоговое окно выглядело так как Вы хотите, при изменении пользователем его размеров.

Следующим свойством Window, которое я изменил является WindowStartupLocation. Для подобного диалогового окна, вероятно как и для большинства нестандартных окон, Вам следует изменить его значение на CenterScreen или CenterOwner, для определения поведения по умолчанию (позицией окна будет управлять Windows), вместо того, чтобы "вручную" определять свойства Top и Left.

Уделите внимание двум свойствам, которые я определил для кнопок окна: IsCancel и IsDefault. IsCancel сообщает WPF, что если пользователь нажмет на нее, то DialogResult Окна надо будет определить как false, что также закроет окно. Вдобавок, это гарантирует, что если пользователь нажмет Esc - окно закроется (учитывая то, что подобный функционал всегда будет реализован в стандартных окнах Windows).

В свою очередь свойство IsDefault направляет фокус на кнопку Ok, и, также гарантирует, что если пользователь нажмет Enter, эта кнопка сработает. Для реализации подобного механизма, необходимо определить обработчик событий для DialogResult, что будет оговорено позже.

Code-behind

В Code-behind я определил конструктор с двумя входными параметрами, один из которых является опциональным. Это позволяет разместить вопрос и ответ по умолчанию (если предусмотрен) в элементы пользовательского интерфейса.

Кнопка Ok имеет обработчик событий, который гарантирует, что при нажатии на нее, свойство Окна DialogResult будет определено как true, для сигнализации инициатора диалогового окна о том, что пользователь подтвердил введенное значение. Мы не нуждаемся в имплементации кнопки Cancel, так как WPF сделает это за нас (при свойстве IsCancel равном true), как было описано выше.

Для того, чтобы во время открытия окно сфокуировалось на элементе TextBox, я подписался на событие ContentRendered, в котором выбрал весь текст в TextBox и передал последнему фокус. Если я захочу просто передать фокус, я использую свойство окна FocusManager.FocusedElement, но в нашем примере, я так же хотел выбрать весь текст из TextBox, чтобы позволить пользователю моментально переопределить ответ, предлагаемый по умолчанию (если он существует, конечно).

Последняя деталь - свойство Answer, которое я определил. Оно просто дает доступ к введенному в элемент TextBox значению, что является "хорошей практикой", предоставляющей свойство с возвращаемым значением(значениями) диалогового окна, вместо прямого доступа к элементу извне. Это также позволяет Вам повлиять на выходной параметр, до того, как он будет возвращен (если Вам это нужно.)

Использование диалогового окна

Совместив все описанное выше вместе, мы наконец-то можем использовать наше окно. Это достаточно простая задача, я создал простое приложение для его тестирования. Вот код:


Здесь нет ничего сверхъестественного - просто несколько элементов TextBlock и кнопка для вызова окна. В обработчике событий Click, мы создаем окно InputDialogSample, предоставляя пользователю вопрос и ответ по умолчанию, а после используем метод ShowDialog() для отображения диалогового окна (всегда следует использовать метод ShowDialog(), а не просто Show(), для подобных модальных окон).

Если результат окна равняется true, это значит, что пользователь нажал на кнопку Ok либо на Enter, а результат присвоился элементу Label, отвечающему за отображение имени. Вот и все!

Is your preferred language not on the list? Click here to help us translate this article into your language!

Читайте также: