Как пометить ввод текстового поля как недействительный, используя прикрепленное поведение

У меня есть много TextBox на моем xaml, где я реализовал проверку Regex (из
Как определить ограничения TextBox). На мой взгляд, это принимает форму:

 <TextBox 
             h:ColorMaskingTextBoxBehavior.Mask="^(?:\d{5})(?:-\d{4})?$"
             Text="{Binding ZipCode}"
            Height="21" HorizontalAlignment="Left" Margin="152,207,0,0"  VerticalAlignment="Top" Width="96"
             />

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

После того, как все входные данные собраны, пользователь должен нажать "Сохранить", чтобы сохранить окно. Коды регулярных выражений могут быть задействованы, и кажется неправильным копировать их из xaml в модель представления, где выполняется Save.

Как прикрепленное поведение может пометить текстовое поле как недействительное, так что модели представления нужно только проверить флаг недопустимого перед сохранением окна? Моя первая мысль - связать свойство зависимостей Tag с текстовым полем, но мне интересно, есть ли лучший способ?

Любые идеи приветствуются.

ТИА

1 ответ

Решение

Я бы перенес всю валидацию в модель представления, вот для чего она нужна. Это не очень хорошая практика MVVM иметь логику приложения в представлении. Представления должны быть взаимозаменяемыми без необходимости перекодирования логики проверки. Затем вы можете изменить внешний вид TextBox, используя триггеры в стиле, который привязывается к свойствам в модели представления вместо использования прикрепленного поведения.

Некоторые люди используют интерфейс IDataErrorInfo.. Я не.

Создайте свойство модели представления, которое определяет, является ли ZipCodeIsValid:

public bool ZipCodeIsValid
{
    get
    {
        var zipCodeRegex = new Regex("^(?:\d{5})(?:-\d{4})?$");
        var zipCodeMatch = zipCodeRegex.Match(ZipCodeText);
        return zipCodeMatch.Success;    
    }
}

Каждый раз ZipCodeText изменения свойств, поднять уведомление об изменении свойства для события ZipCodeIsValid имущество.

Создайте стиль для вашего TextBox:

<Style TargetType="TextBox">
    <Setter Property="Foreground" Value="Black"/>
    <Style.Triggers>
        <DataTrigger Binding="{Binding ZipCodeIsValid}" Value="False">
             <Setter Property="Foreground" Value="Black"/>
        </DataTrigger>
    </Style.Triggers>
</Style>

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

Создайте класс с именем ValidationRegex со статическим строковым свойством с именем ZipCode:

public class ValidationRegex
{
    public static string ZipCode = "^(?:\d{5})(?:-\d{4})?$";
}

Используйте его с прикрепленным поведением:

<TextBox h:ColorMaskingTextBoxBehavior.Mask="{x:Static ValidationRegex.ZipCode}"/>

Используйте его в вашей модели представления:

public void Save()
{
    var zipCodeRegex = new Regex(ValidationRegex.ZipCode);
    var zipCodeMatch = zipCodeRegex.Match(ZipCodeText);
    if (!zipCodeMatch.Success)
    {
        throw new ValidationException("Zip code is invalid!");
    }
}
Другие вопросы по тегам