Как я могу принудительно проверить форму/элемент управления в Compact Framework?

Есть ли способ принудительно проверить контроль в .NET CF? В полной версии .NET есть метод Validate(), но он отсутствует в CF.

Я пытаюсь заставить элемент управления привязывать данные обратно к модели при закрытии формы, но нажатие кнопки главного меню, похоже, не крадет фокус у элемента управления, а события Validating и Validated не срабатывают.

Знаете ли вы обходные пути для этой проблемы?


person Michał Drozdowicz    schedule 19.11.2009    source источник


Ответы (3)


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

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

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

ОБНОВИТЬ

Вот как это выглядело. Сообщите, что я объявляю список элементов управления, которые необходимо проверить:

private List<TextBoxWithValidation> textBoxesWithValidation;

В конструкторе я добавляю элементы управления в список:

TextBoxWithValidation emailTextBoxWithValidation = new TextBoxWithValidation(emailTextBox);
emailTextBoxWithValidation.AddValidationPair(Validator.ValidationType.VALIDATE_NOT_EMPTY, "ValidateNotEmptyEmail");
emailTextBoxWithValidation.AddValidationPair(Validator.ValidationType.VALIDATE_EMAIL, "ValidateEmailEmail");
textBoxesWithValidation.Add(emailTextBoxWithValidation);

Затем я могу проверить форму:

private bool ValidateForm()
{
  foreach (TextBoxWithValidation textBoxWithValidation in textBoxesWithValidation)
  {
    if (!textBoxWithValidation.Validate())
    {
      return false;
    }
  }
  return true;
}

И текстовое поле с проверкой выглядит так:

class TextBoxWithValidation
{
  class ValidationTypeMessagePair
  {
    public Validator.ValidationType ValidationType { get; set; }
    public string ValidationMessage { get; set; }

    public ValidationTypeMessagePair(Validator.ValidationType validationType, string validationMessage)
    {
      this.ValidationType = validationType;
      this.ValidationMessage = validationMessage;
    }
  }

  private List<ValidationTypeMessagePair> validationPairs;
  private TextBox textBox;

  public TextBoxWithValidation(TextBox textBox)
  {
    this.textBox = textBox;
    this.textBox.DataBindings["Text"].DataSourceUpdateMode = DataSourceUpdateMode.Never;            
    validationPairs = new List<ValidationTypeMessagePair>();
  }

  public void AddValidationPair(Validator.ValidationType validationType, string validationMessage)
  {
    validationPairs.Add(new ValidationTypeMessagePair(validationType, validationMessage));
  }

  public bool Validate()
  {
    foreach (ValidationTypeMessagePair validationPair in validationPairs)
    {
      if (!Validator.Validate(validationPair.ValidationType, textBox, Messages.Localize(validationPair.ValidationMessage))) return false;
    }
    textBox.DataBindings["Text"].WriteValue();
    return true;
  }

  public void ClearValidationStatus()
  {
    textBox.BackColor = System.Drawing.SystemColors.Window;
  }

}
person empi    schedule 19.11.2009
comment
Интересный подход — как именно вы реализовали эти методы Validate в обертках? На самом деле у меня возникла эта проблема со сторонним элементом управления (Resco DetailView), и мне интересно, можно ли применить ту же технику. Вы унаследовали от этих элементов управления? Удалось ли вам сохранить поддержку во время разработки? - person Michał Drozdowicz; 20.11.2009
comment
Спасибо за код - раньше не видел DataBindings[string].WriteValue. Согласно моему ответу, мне не нужно было следовать вашему подходу, но если мне когда-нибудь понадобится принудительно привязать данные обратно, ваш ответ будет очень полезен. - person Michał Drozdowicz; 21.11.2009

Если кто-то найдет это полезным, я опишу обходной путь, который я применил.

В обработчик OK я добавил код, который фокусируется на панели, содержащей элемент управления, который я хочу проверить. Когда элемент управления редактирования данных теряет фокус, он запускает события Validating и Validated и привязывает данные обратно к классу модели. Таким образом, форма (которая, кстати, является общей для многих частей «мастера» и знает только о панели, на которую загружаются экраны) может принудительно проверить элемент управления.

Немного взлома, но это будет делать на данный момент.

person Michał Drozdowicz    schedule 19.11.2009
comment
Обновлен мой ответ с образцом кода. Как я уже говорил, я пытался использовать событие фокуса для проверки формы. Однако мне с ним не повезло. Тот факт, что нет простого способа проверить форму в компактном фреймворке, довольно странный. - person empi; 21.11.2009

Я думаю, чтобы инициировать события Validating и Validated, сосредоточив внимание на другом элементе управления, вам нужно установить для свойства Form AutoValidate значение AutoValidate.EnableAllowFocusChange.

Надеюсь, поможет. знак равно

person Zero    schedule 10.12.2009