Управление состояниями UI при разработке под Windows Phone

в 17:00, , рубрики: .net, mvvm, silverlight, windows phone 7, WP7, разработка под windows phone, метки: , , , ,

Недавно нашей командой (Sly Lamb) был выпущен клиент для сервиса Pruffi.ru под Windows Phone. Во время разработки у нас возник вопрос – как отображать пользователю список вакансий, который может находиться в нескольких состояниях.

В этой статье мы хотим показать легкий механизм изменения состояния отображения элементов при помощи Expression Blend и паттерна MVVM. Пример будет приведен с использованием фреймворка MVVM Light Toolkit, но думаю, различия с другими должны быть минимальны.

Для чего это нужно?

Итак, на панораме есть список вакансий. Он может загружаться, быть пуст, или отображаться. Первые два состояния можно объединить в одно визуальное – это вывод сообщения. Итого два состояния: показать список, показать сообщение.

Но как показать сообщение? Нехорошо пугать человека стандартными MessageBox-ами. Тогда, ориентируясь на стандартные приложения, мы решили убирать все элементы, и выводить сообщение на месте элементов. Мы поступили так же, как на скриншотах.
Управление состояниями UI при разработке под Windows Phone

Как реализовать?

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

Для данного случая Expression Blend приготовил нам удобный инструмент, это State(состояния) для каждого элемента, а также поведение DataStateBehavior.

State – это визуальное состояние элемента относительно базового, в котором хранятся параметры самого элемента и дочерних, такие как цвета, положения, прозрачность и т. д.
Управление состояниями UI при разработке под Windows Phone

DataStateBehavior – это поведение, которое приключает между двумя State, в зависимости от условия. Если привязанный параметр совпадает со значением Value, тогда используется TrueState, если не совпадает, тогда FalseState.
Управление состояниями UI при разработке под Windows Phone

Как использовать?

Приведу небольшой пример, в котором создаются и переключаются по времени два состояния.

Создаем пустой проект, используя шаблон MvvmLight (WP71).
Шаблон входит в состав MVVM Light Toolkit.

Сразу создадим логику во ViewModel страницы MainPage. Добавим свойство, которое будет меняться каждые пять секунд с текста «ok» на «hello world».

Откроем MainViewModel.cs и создадим там свойство MessageText:

public const string MessageTextPropertyName = "MessageText";
private string _messageText = "ok";

public string MessageText
{
  get { return _messageText; }

  set
      {
        if (_messageText == value)
                    return;

        _messageText = value;
        RaisePropertyChanged(MessageTextPropertyName);
       }
}

Чтобы свойство менялось каждые пять секунд, добавим в конструктор класса MainViewModel код:

//создаем таймер
var dispatcherTimer = new System.Windows.Threading.DispatcherTimer();

//устанавливаем действие при каждом тике таймера
dispatcherTimer.Tick += ((a,b) =>
                     {
                         MessageText = MessageText == "ok" ? "hello world" : "ok";
                     });

//определяем интервал между тиками
dispatcherTimer.Interval = new TimeSpan(0, 0, 5);

//запускаем таймер
dispatcherTimer.Start();

Перейдем к дизайну страницы, для этого откроем проект в Expression Blend.

Добавим на MainPage кнопку и текстовый блок. Кнопку будем отображать, когда свойство MessageText равно «ok», во всех остальных случаях отображаем текстовое поле с содержимым MessageText.

Замечу, что кнопка играет роль контента страницы, а текстовое поле – некритичной ошибки или сообщения, при котором контент показывать нельзя или он пуст.
После добавления форма будет выглядеть примерно так.
Управление состояниями UI при разработке под Windows Phone

К значению Text элемента TextBlock привязываем наше свойство MessageText, нажав на квадрат справа от свойства и выбрав пунк DataBinding. В открывшемся окне нужно выбрать нужное свойство и нажать «OK».
Управление состояниями UI при разработке под Windows Phone

Перейдем к созданию состояний. Откройте вкладку States в панели, которая находиться в левом верхнем углу экрана. Нажмите в ней кнопку Add state group. Выберите состояние Base – это то, от которого буду отталкиваться все остальные.
Управление состояниями UI при разработке под Windows Phone

Измените, свойство Visibility у текстового поля на Collapsed, чтобы оно пропало.

Нажмите справа у группы состояний VisualStateGroup кнопу Add State, чтобы создать состояние с название Normal, а затем c названием Message.
Управление состояниями UI при разработке под Windows Phone

Состояние Normal оставим, т.к. оно должно быть таким же, как и Base. А состояние Message запишем, нажав на него. Должно появиться сообщение о записи как на скриншоте. После чего изменим свойство Visiblity у кнопки на Collapsed, а у текстового блока на Visiblity. Для завершения записи нажмите на одну из красных кнопок.

Состояния созданы, осталось добавить переключатель между ними. Для этого добавим на страницу DataStateBehavior из вкладки Assets в категории Behaviors.

Свойство Binding привязываем к свойству MessageText, значение Value выставляем в «ok». Состояние TrueState ставим Normal, а FalseState ставим Message. Запускаем приложение и видим, как меняется состояние страницы в зависимости от значения поля MessageText.
Управление состояниями UI при разработке под Windows Phone

Также можно добавлять анимацию между состояниями или простые переходы через свойство Default transition в VisualStateGroup.

Еще хочется обратить ваше внимание на GoToStateAction, который умеет переходить на состояние при каком либо действие, например при нажатие на кнопку.

На этом все, комментируйте, буду рад ответить на ваши вопросы.

Исходный код: скачать/посмотреть

Автор: StrangeAndr

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js