Pull to refresh

Создание приложения для Windows Phone 7 от начала до конца. Часть 14. Валидация вводимых данных

Development for Windows Phone *
Translation
Original author: Microsoft Developer Guidance team
Предыдущая часть

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

В этой части вы узнаете:
  • Как осуществлять валидацию на Windows Phone.
  • Как выполнить проверку несохранённых изменений, когда пользователь нажимает кнопку «Назад».

Валидация


Обычно полезно ограничить данные, которые пользователи могут ввести. Вот два простых способа, как можно ограничить вводимые пользователем данные:
  • Установить свойство TextBox.MaxLength так, чтобы пользователи могли вводить только ожидаемое количество текста.
  • Установить свойство TextBox.InputScope, так чтобы пользователи могли вводить только ожидаемый тип данных (такой как цифровые данные). Как это сделать описывалось в части «Использование элементов управления».
Даже с этими ограничениями, как правило, еще можно ввести значения, которые неправильно отформатированы или недействительны по другим причинам.

Ваши требования к валидации могут быть различными, но, как правило, вы будете проверять данные, чтобы предотвратить сохранение неправильных значений. В этом случае полезно привязывать пользовательский интерфейс ко временным объектам, чем привязывать непосредственно к хранилищу данных. Например, в приложении Fuel Tracker, новые данные о заправке не добавляются в коллекцию FillupHistory, пока пользователь не нажмёт кнопку «Save». Однако, прежде чем они будут сохранены пользователь может просмотреть данные, чтобы убедиться, что они указаны точно. Когда пользователь нажмёт кнопку «Save», код валидации выполнит одну последнюю проверку на ошибки и предупредит пользователя о любых проблемах.

Следующий код демонстрирует простой метод проверки, используемый в классе Fillup.
  1. public IEnumerable<string> Validate()
  2. {
  3.     if (OdometerReading <= 0) yield return
  4.         "The odometer value must be greater than zero.";
  5.  
  6.     if (DistanceDriven <= 0) yield return
  7.         "The odometer value must be greater than the previous value.";
  8.  
  9.     if (FuelQuantity <= 0) yield return
  10.         "The fuel quantity must be greater than zero.";
  11.  
  12.     if (PricePerFuelUnit <= 0) yield return
  13.         "The fuel price must be greater than zero.";
  14. }
* This source code was highlighted with Source Code Highlighter.

На следующем изображении показан пример сообщения, которое отображается при нажатии кнопки «Save», когда указано значение показаний одометра меньше предыдущего значения.

image

Этот код просто проверяет значения свойства Fillup и возвращает сообщения об ошибках для любых недопустимых значений. Однако, не все проверяемые значения указываются пользователем, поэтому некоторая инициализация должна произойти заранее. В частности, расстояние должно быть рассчитано путем сравнения значения Fillup.OdometerReading с предыдущим значением показаний одометра. Однако, текущий объект Fillup не имеет доступа к предыдущему значению, так что это действие осуществляется методом CarDataStore.SaveFillup, как показано в следующем фрагменте кода.
  1. public static SaveResult SaveFillup(Fillup fillup, Action errorCallback)
  2. {
  3.     var lastReading =
  4.         Car.FillupHistory.Count > 0 ?
  5.         Car.FillupHistory.First().OdometerReading :
  6.         Car.InitialOdometerReading;
  7.     fillup.DistanceDriven = fillup.OdometerReading - lastReading;
  8.  
  9.     var saveResult = new SaveResult();
  10.     var validationResults = fillup.Validate();
  11.     if (validationResults.Count() > 0)
  12.     {
  13.         saveResult.SaveSuccessful = false;
  14.         saveResult.ErrorMessages = validationResults;
  15.     }
  16.     else
  17.     {
  18.         Car.FillupHistory.Insert(0, fillup);
  19.         saveResult.SaveSuccessful = true;
  20.         SaveCar(delegate {
  21.             saveResult.SaveSuccessful = false;
  22.             errorCallback(); });
  23.     }
  24.     return saveResult;
  25. }
* This source code was highlighted with Source Code Highlighter.

Метод CarDataStore.SaveFillup принимает объект Fillup для сохранения и делегат Action для обработки ошибок. Этот метод начинается с вычитания из текущих показаний одометра предыдущего значения показаний и сохраняет результаты в свойстве Fillup.DistanceDriven так, чтобы проверка молга быть осуществлена в этом классе. Далее метод SaveFillup вызывает метод Fillup.Validate и сохраняет результаты в специальный объект SaveResult, который он возвращает вызывающему методу. Если ошибок валидации не происходит, метод SaveFillup сохраняет данные о заправке и об автомобиле. Наконец, метод SaveFillup возвращает объект SaveResult.

Примечание:
Silverlight for Windows Phone предоставляет базовую, встроенную в привязку валидацию через свойство Binding.ValidatesOnExceptions. Тем не менее, версии элементов управления для Windows Phone не предоставляют шаблонов валидации. Для поддержки валидации одним из вариантов является предоставление собственных шаблонов валидации для элементов управления.

Следующий фрагмент кода демонстрирует, что происходит, когда пользователь нажимает кнопку «Save» на странице информации о заправке.
  1. private void SaveButton_Click(object sender, EventArgs e)
  2. {
  3.     CommitTextBoxes();
  4.  
  5.     SaveResult result = CarDataStore.SaveFillup(currentFillup,
  6.         delegate {
  7.             MessageBox.Show("There is not enough space on your phone to " +
  8.             "save your fill-up data. Free some space and try again.",
  9.             "Warning", MessageBoxButton.OK);
  10.         });
  11.  
  12.     if (result.SaveSuccessful)
  13.     {
  14.         Microsoft.Phone.Shell.PhoneApplicationService.Current
  15.             .State["FillupSaved"] = true;
  16.         cacheChanges = false;
  17.         NavigationService.GoBack();
  18.     }
  19.     else
  20.     {
  21.          string errorMessages = String.Join(
  22.             Environment.NewLine + Environment.NewLine,
  23.             result.ErrorMessages.ToArray());
  24.          if (!String.IsNullOrEmpty(errorMessages))
  25.          {
  26.              MessageBox.Show(errorMessages,
  27.              "Warning: Invalid Values", MessageBoxButton.OK);
  28.          }
  29.     }
  30. }
* This source code was highlighted with Source Code Highlighter.

Этот код вызывает метод SaveFillup, передав ему callback ошибки, как описано выше. Этот делегат просто отображает условие ошибки в окне сообщения. Затем метод проверяет, есть ли ошибки валидации, обработчик события отображает их в окне сообщения.

Если сохранение прошло успешно, метод SaveButton_Click использует словарь состояния уровня приложения для хранения значения, указывающего, что новая информация о заправке только что была сохранена. Затем метод осуществляет переход назад, хотя сначала он устанавливает флаг, чтобы предотвратить кэширование, как было описано ранее в части «Восстановлении приложения после деактивации». После выполнения перехода, если SummaryPage обнаруживает, что значение хранится в словаре состояний, страница отображает первый пункт сводной информации так, чтобы пользователь мог сразу увидеть результаты заправки. В противном случае, SummaryPage будет автоматически отображаться в зависимости от того, какой пункт сводной информации показывался до перехода к FillupPage.

Здесь описан только один способ валидации, но помимо него существует ещё множество других.

Проверка на несохраненные изменения при переходе назад


По умолчанию, нажатие кнопки «Назад» осуществляет переход назад. Если у вас есть страница ввода данных с несохраненными изменениями, и пользователь нажимает кнопку «Назад», вы должны сообщить об этом пользователю. Чтобы реализовать данное поведение, можно перегрузить метод PhoneApplicationPage.OnBackKeyPress и выполнить проверку на несохраненные изменения. Если есть несохраненные изменения, вы можете сообщить об этом пользователю и, возможно, отменить переход назад.

Сертификационное требование:
Для поддержки согласованного пользовательского опыта, кнопка «Назад» должна использоваться только для перехода назад в приложении.

Для выполнения этого требования, вы не должны использовать перегрузку OnBackKeyPress для отмены перехода назад и полностью изменять поведение кнопки «Назад». Возможность отмены навигации назад предоставляется для того, чтобы выполнить необходимые связанные с навигацией операции, такие, как ожидание подтверждения пользователем удаления данных.
Приложение Fuel Tracker имеет две страницы для ввода данных: CarDetailsPage и FillupPage. Если есть несохраненные изменения на этих страницах и пользователь нажимает «Назад», на экране появится сообщение, требующее подтверждение, которое позволяет отменить переход назад. На следующем изображении показан пример сообщения, требующего подтверждение.

image

Рекомендация по проектированию интерфейса:
Действия приложения, которые перезаписывают или удаляют данные, или не могут быть обратимы должны иметь кнопку «Отмена».
Следующий фрагмент кода показывает, как приложение Fuel Tracker перегружает метод PhoneApplicationPage.OnBackKeyPress для отображения сообщения, требующего подтверждение, если есть несохраненные данные.
  1. protected override void OnBackKeyPress(
  2.     System.ComponentModel.CancelEventArgs e)
  3. {
  4.     base.OnBackKeyPress(e);
  5.  
  6.     // If there are no changes, do nothing.
  7.     if (!hasUnsavedChanges) return;
  8.  
  9.     var result = MessageBox.Show("You are about to discard your " +
  10.         "changes. Continue?", "Warning", MessageBoxButton.OKCancel);
  11.     if (result == MessageBoxResult.OK)
  12.     {
  13.         // Normal navigation; there's no need to handle tombstoning,
  14.         // so set the cacheChanges flag and clear the current cache.
  15.         cacheChanges = false;
  16.         this.State.Remove(CURRENT_FILLUP_KEY);
  17.     }
  18.     else
  19.     {
  20.         // Cancel backward navigation.
  21.         e.Cancel = true;
  22.     }
  23. }
* This source code was highlighted with Source Code Highlighter.

Сначала этот метод проверяет, есть ли несохраненные изменения. Если их нет, то метод не делает ничего, и переход назад происходит автоматически. В противном случае, метод отображает сообщение, требующее подтверждение. Если пользователь нажимает «ОК», чтобы продолжить переход назад, то странице не нужно обрабатывать tombstoning, так что метод выполняет некоторые действия и выполняет переход назад. Если пользователь нажимает «Отмена», то переход назад будет отменен.

Здесь будет ссылка на следующую часть.
Первая часть
Tags:
Hubs:
Total votes 57: ↑32 and ↓25 +7
Views 2.2K
Comments Comments 9