Многооконные приложения в wpf можно осуществить с помощью
В моем приложении может быть несколько окон дизайнера. Каждое окно состоит из нескольких пользовательских элементов управления, которые динамически взаимодействуют с помощью RelayCommands. Я создал следующий класс как основу командной инфраструктуры.
Каждая модель представления для пользовательских элементов управления будет делать что-то подобное в конструкторе
Однако я совершенно упустил тот момент, что приложение может иметь несколько окон. Когда каждое окно открывается, статические команды устанавливаются для этого конкретного окна.
Окно A открывается - конструкторы для пользовательских элементов управления устанавливают RelayCommands, и все в порядке.
Окно B открыто - конструкторы для пользовательских элементов управления устанавливают RelayCommands. Привязка команд окна A потеряна!
Поэтому, когда я меняю вкладку на Окно A (окна имеют вкладки), никакие команды не работают.
Мне нужна идея, чтобы, когда я меняю вкладку, активное окно всегда устанавливает команды. Я могу попробовать поместить команду в событие tab_selection_changed, но мне почему-то это плохо выглядит. Есть ли правильный способ сделать это? Буду признателен за любую оказанную помощь.
Вопрос оказался немного запутанным среди читателей. Я не пытаюсь создать несколько подписчиков для команды. В любой момент активно только одно окно. Это окно состоит из нескольких пользовательских элементов управления, некоторые из которых загружаются динамически с помощью команд; но каждая команда обрабатывается одним классом модели представления, поэтому нет нескольких подписчиков. Моя проблема в том, что приложение может загружать несколько окон на вкладках - в любой момент активно только одно окно, но пользователь может сделать с другой вкладкой и сделать другое окно активным. Поскольку конструктор модели представления назначает статические RelayCommands, при загрузке каждого нового окна для статической команды устанавливается новая привязка.
Окно Открытое окно Конструктор модели представления устанавливает привязку статической команды к своему обработчику команд объекта. Окно А активно. Командовать - это нормально.
Конструктор модели представления B в загруженном окне B устанавливает статическую привязку команды к своему обработчику команд объекта. Окно B активно. Командировать - это нормально.
Теперь пользователь выбирает вкладку Window A, чтобы установить окно A как активное. Командование не сработает. Конечно, это не так, поскольку команда привязана к обработчику команд Window B.
Теоретически статические команды могут обрабатывать сценарий, поскольку в любой момент будет только одно активное окно. Но как??
Для реализации функциональности приложения необходимо для страницы приложения установить механизм запуска задач при выборе соответствующих пунктов меню и нажатии на кнопки панели инструментов. Технология WPF предлагает модель команд для выполнения такой привязки.
Модель команд обеспечивает делегирование событий определенным командам и управление доступностью элементов управления в зависимости от состояния соответствующей команды. В WPF команда представляет собой задачу приложения и механизм слежения за тем, когда она может быть выполнена. В то же время сама команда не содержит конкретного кода выполнения задачи. Одна и та же команда может быть привязана к одному или нескольким интерфейсным элементам приложения. Инициируют команду источники, которые могут быть различными элементами управления, например пункты меню MenuItem или кнопки – Button. Целевым объектом команды является элемент, для которого предназначена эта команда .
Классы, реализующие команды должны поддерживать интерфейс ICommand. В этом интерфейсе определены два метода Execute, CanExecute и событие CanExecuteChanged.
Метод Execute может содержать код, реализующий бизнес-логику приложения. Метод CanExecute возвращает информацию о состоянии команды. Событие CanExecuteChanged вызывается при изменении состояния команды.
В WPF имеется библиотека базовых команд. Команды доступны через статические свойства следующих статических классов:
- ApplicationCommands ;
- NavigationCommands ;
- EditingCommands ;
- MediaCommands.
Для создания пользовательских команд целесообразно использовать классы RoutedCommand, который имеет реализацию интерфейса ICommand.
Для разработки пользовательских команд добавьте в проект папку Commands и в ней создайте класс DataCommands.
В классе DataCommands объявлены два свойства Delete и Edit типа RoutedCommand. Класс RoutedCommand определяет команду, реализующую ICommand. В конструкторе данного класса определяется объект inputs типа InputGestureCollection. Класс InputGestureCollection представляет упорядоченную коллекцию объектов InputGesture, которые позволяют с помощью класса KeyGesture задать комбинацию клавиш для вызова команды.
Для использования страницей приложения пользовательских команд в XAML -документе необходимо добавить пространство имен , где расположен класс DataCommands. Данному пространству имен присвоим ссылку command.
Теперь для страницы приложения сформируйте коллекцию объектов CommandBinding, которая осуществляет привязку команд для данного элемента и объявляет связь между командой, ее событиями и обработчиками.
Для класса CommandBinding свойство Command определяет ссылку на соответствующую команду, а свойства Executed и CanExecute задают обработчики событий при выполнении команды.
На странице приложения используются следующие команды: Отменить, Создать, Редактировать, Поиск, Сохранить и Удалить. Команды могут быть доступны или недоступны пользователю при работе приложения. Это проверяет метод CanExecute при генерации события CanExecuteChanged, которое вызывается при изменении состояния команды. Доступность команд определяется состоянием, в котором находится приложение . В тоже время выполнение какой-либо команды переводит, как правило, приложение в какое-либо другое состояние. Для проектируемого приложения можно определить следующие состояния:
- первоначальная загрузка страницы;
- просмотр данных;
- редактирование данных;
- создание новой записи.
В код программы класса страницы приложения введите логическое поле isDirty для управления доступностью команд.
В дальнейшем в обработчики необходима будет добавить код для обеспечения требуемой функциональности.
В коде класса необходимо добавить обработчики (реализация метода CanExecute ), которые управляют доступностью команд.
Необходимо модифицировать XAML -документ в части задания свойства Command при описании пунктов меню и панели инструментов для привязки команд.
При описании меню ( Menu ) XAML -документ модифицирован следующим образом.
Соответствующие изменения XAML -документа необходимо провести и для панели инструментов ToolBar.
Обычно можно запускать произвольное количество копий приложения WPF. В некоторых сценариях это проектное решение совершенно оправдано. Однако в других случаях это может стать проблемой, особенно при построении приложений, основанных на документах.
Например, рассмотрим текстовый процессор Microsoft Word. Независимо от того, сколько документов открывается (и как они открываются), в каждый момент времени загружен только единственный экземпляр winword.exe. При открытии новых документов они появляются в новых окнах, но всеми окнами документов управляет единственное приложение. Такое решение представляет собой наилучший подход, когда требуется сократить накладные расходы, связанные с работой приложения, централизовать определенные средства (например, создать единый диспетчер очереди печати) либо интегрировать разнородные окна (например, предоставить средство, которое упорядочит все текущие открытые окна документов, расположив их рядом друг с другом).
В WPF не предусмотрено встроенного решения для приложений одного экземпляра, но можно воспользоваться несколькими обходными маневрами. Базовый прием заключается в проверке существования другого запущенного экземпляра приложения при возникновении события Application.Startup. Простейший путь сделать это состоит в использовании системного мьютекса (объекта синхронизации, предоставляемого операционной системой, позволяющей межпроцессное взаимодействие).
Этот подход прост, но ограничен — важнее всего то, что при этом не существует возможности взаимодействия нового экземпляра приложения с уже существующим. Это становится проблемой для приложений, основанных на документах, потому что новому экземпляру может понадобиться сообщить существующему экземпляру о необходимости открытия определенного документа, если он передан в командной строке. (Например, двойной щелчок на файле .doc в проводнике Windows при запущенном приложении Word должен приводить к загрузке в Word этого файла.) Это взаимодействие более сложно и обычно осуществляется через технологию Remoting или Windows Communication Foundation (WCF). Корректная реализация требует включения способа обнаружения удаленного сервера и его использования для передачи аргументов командной строки.
Однако простейший подход, рекомендованный для WPF, предусматривает применение встроенной поддержки, которая предоставляется в Windows Forms, и изначально предназначалась для приложений Visual Basic. Этот подход обрабатывает все запутанные детали "за кулисами".
Создание оболочки для приложения одного экземпляра
Первый шаг заключается в добавлении ссылки на сборку Microsoft.VisualBasic.dll и наследовании специального класса от класса Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase. В этом классе определены три важных члена, которые используются для управления экземплярами:
Свойство IsSingleInstance
Позволяет создать приложение одного экземпляра. Это свойство устанавливается в true в конструкторе.
Метод OnStartup()
Инициируется при старте приложения. Этот метод переопределяется и в данной точке создается объект приложения WPF.
Метод OnStartupNextInstance()
Инициируется при запуске другого экземпляра приложения. Этот метод обеспечивает доступ к аргументам командной строки. В данной точке, скорее всего, будет вызван метод класса приложения WPF, чтобы отобразить новое окно, не создавая другого объекта приложения.
im ищет некоторые подсказки и подсказки, как я могу создать свое приложение в хорошем смысле.
Итак, вот некоторые сведения: у меня в настоящее время Mainwindow разработан с сеткой, которая содержит 4 кадра. это выглядит так.
В верхней части находится меню, позволяющее выбрать разные страницы. У меня для основной области около 8 страниц, например. страницу настроек и 4 страницы содержимого. Боковая панель отображает дополнительную информацию, которую пользователь может выбрать, а внизу отображается только страница, когда открывается одна из страниц содержимого.
Таким образом, у моих страниц контента есть ViewModels, чтобы заполнить их, и я пытаюсь использовать команды в ближайшем будущем, когда я пойму все их функции;). Поэтому я пытаюсь использовать MVVM-путь, но im очень новый.
Мне действительно не нужно меню навигации, которое оно отображается в окнах навигации.
Итак, лучший способ для приложения использовать Frames или есть ли какие-нибудь лучшие решения?
спросил(а) 2021-01-09T12:39:11+03:00 10 месяцев, 3 недели назадФреймы поддерживают встроенную навигационную инфраструктуру WPF, поэтому они являются хорошим выбором, если вы планируете использовать это. У этого есть некоторые проблемы (по крайней мере, некоторые люди думают так, включая меня), но для простых/небольших приложений это будет прекрасно. Конечно, они также будут работать, если вы хотите перевернуть свою собственную легкую навигационную систему, как я обычно делаю. Обычно я перемещаюсь, отправляя экземпляры ViewModels и устанавливая их как содержимое окон или элементов управления содержимым, и позволяя DataTemplates "одевать" их, как они определены в представлениях. Для больших проектов я всегда рекомендую одну из потрясающих рамок, которые включают в себя навигационные системы, такие как Prism или Magellan.
В основном все зависит от ваших требований; есть много способов сделать это правильно. Хорошо, что вы пытаетесь использовать MVVM, старайтесь придерживаться этого, и он, как правило, автоматически направит вас в хорошем направлении.
Читайте также: