Случилось мне писать WPF Wizard. И было это сложно и интересно и много проблем порешал я.
- автоматическое отслеживание представлениями состояния валидности объекта (кнопки Next, Save и т.п. должны быть отключены, если редактируемый объект в невалидном состоянии, и наоборот. Проще говоря, wizard не должен дать вам совершить ошибку);
- прозрачное для разработчика валидирование - это не должна быть его забота и он не должен писать в code-behind никакой логики валидирования;
Что есть:
- В WPF binding engine есть валидация. Она реализуется при помощи объектов классов наследников ValidationRule и статического класса Validation. Почему бы не использовать их и не угомониться на этом? Да потому что это валидация данных, лежащих в UI контролах, а не валидация бизнес объектов. Нужен унифицированный механизм, не завязанный на UI технологию, т.к. валидровать объект можно не только в UI. Но эту технологию можно использовать как точку расширения и подключения дополнительной логики в процессе валидирования данных wizard.
- В Enterprise library (EL) есть Validation Application Block (VAB), который предназначен для решения задачи валидирования бизнес-объектов;
- В предыдущих постах я писал об использовании комманд WPF, управляющих состоянием UI.
- на первой странице заполняются ФИО, причем имя или фамилия поля обязательные.
- на второй странице заполняются настройки доступа - логин, пароль, подтверждение пароля
- на третьей странице заполняется и так далее... =)
- ObservableObject - уже встречавшийся нам класс, реализующий InotifyPropertyChanged.
- DomainObject - базовый класс домена. Содержит шаблонный метод DoValidate, в котором наследниками должна будет реализовываться логика валидирования. Не является data contract, но помечен аттрибутом [Serializable]. Такое решение принято чтобы не вводить зависимость домена от технологии создания сервисов (WCF).
- DomainDTO - базовый класс для всех дата контрактов. Знает обо всех своих наследниках (при помощи аттрибута [KnownType]).
- DomainDTO
, где Т - тип класса наследника. Реализует логику валидирования объекта.
Базовый класс домена.
Как видите класс не сериализует результаты валидирования, ибо нет нужды передавать их через границу сервиса.
Базовый дата контракт, реализующий шаблоный метод.
DomainDTO
Здесь он просит фасад VAB фабрики объектов создать композитный валидатор по указанному ruleSet подмножеству, а затем передает себя валидатору, который собирает, комбинирует и возвращает ответ от всех валидаторов, входящих в указанный validationRuleSet.
В wizard'е есть следующие команды:
- NextPage - переход на следующую страницу;
- BackPage - переход на предыдущую страницу;
- GoToPage - переход на указаную страницу;
- Save - сохранить редактируемый объект;
- Cancel - отменить редактирование объекта;
- Help - показать файл справки;
Для демонстрации этой возможности представьте себе следующий сценарий:
на странице wizard'а редактируется объект пользовательских данных для разграничения доступа (логин, пароль). На странице есть 1 TextBox - Login, и 2 PasswordBox'а - Password, PasswordConfirmation. В DataContext страницы wizard'а лежит бизнес-объект (пусть LoginCredential). Поле Text textbox'а Login привязано (binding) к свойству LoginCredential.Login, поле Text passwordbox'а Password в codebehind привязно к LoginCredential.Password. Для валидации данных, необходимо, чтобы пользователь повторил пароль, но в объекте LoginCredential нет поля повтор пароля. Если в passwordbox PasswordConfirmation не будет введен идентичный первому пароль все навигационные кнопки не должны быть активными. Как быть? Мы по-прежнему не хотим писать spaghetti-code.
Здесь и вступает в игру binding validation, ведь теперь мы валидируем не бизнес объект, а данные, которые лежат в UI, но сильно влияют на принятие решения о валидности объекта.
Также у класса есть attached-свойство Bag, которое будет очень полезно объектам у которых нет dependency-свойств, чтобы привязывать какие-либо данные через WPF binding.
Логика очень проста - если пароли различны, то при помощи вспомогательного метода ValidationHelper.MarkInvalid страница помечается невалидной и в OnQueryEnabled будет принято решение о невалидности данных,т.к. страница невалидна. Если же введенные пароли идентичны, то страница помечается валидной вспомогательным методом ValidationHelper.ClearInvalid.
3 комментария:
есть source code для wizard framework?
есть source code для вашей wizard framework?
я бы не называл это framework, потому что стиль в xaml надо немного доработать для того, чтобы он стал легкокастомизуемым, так что можете взять код и немного поправить для себя, либо использовать как есть. ссылка: http://www.megaupload.com/?d=OEWPQ15D
Отправить комментарий