Проверка данных в Silverlight 4 - PullRequest
6 голосов
/ 12 марта 2011

У меня есть контроль в SL4.Я хочу проверить данные по нажатию кнопки.Большая проблема, как правило, SL4 дает проверку с использованием свойства привязки.

как пример, приведенный в этом примере

http://weblogs.asp.net/dwahlin/archive/2010/08/15/validating-data-in-silverlight-4-applications-idataerrorinfo.aspx

<TextBox Text="{Binding Name,Mode=TwoWay,ValidatesOnDataErrors=true}" 
    Height="23" 
    Width="120"
    HorizontalAlignment="Left" 
    VerticalAlignment="Top"    />

НО Я ХОЧУ ПОКАЗАТЬ СООБЩЕНИЕ ОБ ОШИБКЕЭТО ....

enter image description here

используя мой собственный код, как при нажатии кнопки, я проверяю (textbox1.text == null), затем устанавливаю этот стиль ошибки на textbox1

Ответы [ 2 ]

9 голосов
/ 12 марта 2011

Одним из способов отсрочки проверки является установка свойства UpdateSourceTrigger=Explicit в привязках. Если вы сделаете это, привязки не обновят исходные объекты и, следовательно, не вызовут ошибок проверки, пока вы явно не скажете привязкам сделать это. Когда нажата ваша кнопка, вы принудительно обновляете привязки, используя следующую строку для каждого элемента управления:

someTextBox.GetBindingExpression(TextBox.TextProperty).UpdateSource();

Затем ваши установщики свойств выдают исключения для недопустимых данных.

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

Кроме того, принудительное обновление привязок должно выполняться в коде позади элемента управления. Если вы также используете команду с кнопкой, вы можете столкнуться с проблемой. Кнопки могут иметь как обработчик события Command, так и обработчик Click, и оба будут выполняться при нажатии кнопки, но я не знаю порядок, в котором это происходит, или даже если порядок можно гарантировать. Быстрый эксперимент показал, что обработчик событий был выполнен перед командой, но я не знаю, является ли это неопределенным поведением. Поэтому существует вероятность того, что команда будет запущена до того, как будут обновлены привязки.


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

'sapient' опубликовал полное решение, включая код , на форумах Silverlight (поиск сообщения от 07-08-2009 16:56). Короче говоря, он / она создает вспомогательный объект со свойством, метод получения которого генерирует исключение, привязывает свойство Tag текстового поля к этому вспомогательному объекту и затем принудительно обновляет привязку.

код sapient был написан до выхода Silverlight 4. Мы «обновим» его / ее код до Silverlight 4. Класс ControlValidationHelper станет следующим:

public class ControlValidationHelper : IDataErrorInfo
{
    public string Message { get; set; }

    public object ValidationError { get; set; }

    public string Error
    {
        get { throw new NotImplementedException(); }
    }

    public string this[string columnName]
    {
        get { return Message; }
    }
}

Достаточно легко запустить быстрое демо-приложение, чтобы попробовать это. Я создал следующие три элемента управления:

    <TextBox x:Name="tbx" Text="{Binding Path=Text, ValidatesOnDataErrors=True, NotifyOnValidationError=True, Mode=TwoWay}" />
    <Button Click="ForceError_Click">Force error</Button>
    <Button Click="ClearError_Click">Clear error</Button>

Свойство Text и обработчики событий для двух кнопок находятся в выделенном коде и имеют следующий вид:

    public string Text { get; set; }

    private void ForceError_Click(object sender, RoutedEventArgs e)
    {
        var helper = new ControlValidationHelper() { Message = "oh no!" };
        tbx.SetBinding(Control.TagProperty, new Binding("ValidationError")
        {
            Mode = BindingMode.TwoWay,
            NotifyOnValidationError = true,
            ValidatesOnDataErrors = true,
            UpdateSourceTrigger = UpdateSourceTrigger.Explicit,
            Source = helper
        });
        tbx.GetBindingExpression(Control.TagProperty).UpdateSource();
    }

    private void ClearError_Click(object sender, RoutedEventArgs e)
    {
        BindingExpression b = tbx.GetBindingExpression(Control.TagProperty);
        if (b != null)
        {
            ((ControlValidationHelper)b.DataItem).Message = null;
            b.UpdateSource();
        }
    }

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

Один потенциальный недостаток этого подхода возникает, если вы используете ValidationSummary . ValidationSummary перечислит все ошибки проверки по ValidationError, а не по имени каждого свойства.

3 голосов
/ 13 марта 2011

Хотя мой ответ не был расценен как предпочтительный, я все же уверен, что шаблон MVVM - лучший выбор для выполнения проверки.

В моем коде вы должны использовать средство проверки модели из этогопост о валидации и любом фреймворке mvvm, например MVVM Light.

Гораздо проще добавить правила валидации, используя модель представления и классы валидатора модели:

public class PersonViewModel : ViewModelBase, INotifyDataErrorInfo
{
    private ModelValidator _validator = new ModelValidator();

    public PersonViewModel()
    {
        this._validator.AddValidationFor(() => this.Age)
            .Must(() => this.Age > 0)
            .Show("Age must be greater than zero");
    }
}

И выможет проверить модель, если и только если пользователь явно нажмет кнопку:

    #region INotifyDataErrorInfo

    public IEnumerable GetErrors(string propertyName)
    {
        return this._validator.GetErrors(propertyName);
    }

    public bool HasErrors
    {
        get { return this._validator.ErrorMessages.Count > 0; }
    }

    public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged = delegate { };

    protected void OnErrorsChanged(string propertyName)
    {
        ErrorsChanged(this, new DataErrorsChangedEventArgs(propertyName));
        this.RaisePropertyChanged("HasErrors");
    }
    #endregion

    public bool Validate()
    {
        var result = this._validator.ValidateAll();
        this._validator.PropertyNames.ForEach(OnErrorsChanged);
        return result;
    }

Как все могут видеть, здесь нет ничего сложного, всего лишь 20-30 строк кода.

Более тогоподход MVVM гораздо более гибкий, и вы можете повторно использовать некоторые распространенные сценарии проверки для нескольких моделей представлений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...