Проверка WPF не срабатывает при первом потерянном фокусе TextBox - PullRequest
13 голосов
/ 19 сентября 2008

Я пытаюсь проверить форму WPF для объекта. Проверка запускается, когда я набираю что-то в текстовом поле, теряю фокус, возвращаюсь в текстовое поле и затем стираю все, что я написал. Но если я просто загружаю приложение WPF и вкладываю текстовое поле, не записывая и не стирая что-либо из текстового поля, то оно не запускается.

Вот класс Customer.cs:

public class Customer : IDataErrorInfo
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }

        public string Error
        {
            get { throw new NotImplementedException(); }
        }
        public string this[string columnName]
        {
            get
            {
                string result = null;

                if (columnName.Equals("FirstName"))
                {
                    if (String.IsNullOrEmpty(FirstName))
                    {
                        result = "FirstName cannot be null or empty"; 
                    }
                }
                else if (columnName.Equals("LastName"))
                {
                    if (String.IsNullOrEmpty(LastName))
                    {
                        result = "LastName cannot be null or empty"; 
                    }
                }
                return result;
            }
        }
    }

А вот код WPF:

<TextBlock Grid.Row="1" Margin="10" Grid.Column="0">LastName</TextBlock>
<TextBox Style="{StaticResource textBoxStyle}" Name="txtLastName" Margin="10"
         VerticalAlignment="Top" Grid.Row="1" Grid.Column="1">
    <Binding Source="{StaticResource CustomerKey}" Path="LastName"
             ValidatesOnExceptions="True" ValidatesOnDataErrors="True"
             UpdateSourceTrigger="LostFocus"/>         
</TextBox>

Ответы [ 6 ]

18 голосов
/ 28 августа 2009

Если вы не против того, чтобы оставить немного логики в своем коде, вы можете обработать фактическое событие LostFocus примерно так:

.xaml

<TextBox LostFocus="TextBox_LostFocus" ....

.xaml.cs

private void TextBox_LostFocus(object sender, RoutedEventArgs e)
{
     ((Control)sender).GetBindingExpression(TextBox.TextProperty).UpdateSource();
}
8 голосов
/ 19 сентября 2008

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

Невероятно, но верно. До сих пор валидация WPF - это большая пресловутая боль - это ужасно.

Одна из вещей, которую вы можете сделать, однако, это получить выражение привязки из свойства элемента управления и вручную вызвать проверки. Это отстой, но это работает.

5 голосов
/ 27 мая 2009

Взгляните на ValidatesOnTargetUpdated свойство ValidationRule. Он будет проверяться при первой загрузке данных. Это хорошо, если вы пытаетесь поймать пустые или нулевые поля.

Вы бы обновили свой обязательный элемент следующим образом:

<Binding 
    Source="{StaticResource CustomerKey}" 
    Path="LastName" 
    ValidatesOnExceptions="True" 
    ValidatesOnDataErrors="True" 
    UpdateSourceTrigger="LostFocus">
    <Binding.ValidationRules>
        <DataErrorValidationRule
            ValidatesOnTargetUpdated="True" />
    </Binding.ValidationRules>
</Binding>
1 голос
/ 16 декабря 2011

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

    private void dbaseNameTextBox_LostFocus(object sender, RoutedEventArgs e)
    {
        if (string.IsNullOrWhiteSpace(dbaseNameTextBox.Text))
        {
            dbaseNameTextBox.Text = string.Empty;
        }
    }

Тогда он видит ошибку

0 голосов
/ 15 апреля 2011

Следующий код перебирает все элементы управления и проверяет их. Не обязательно предпочтительный способ, но, кажется, работает. Это только делает TextBlocks и TextBoxes, но вы можете легко изменить его.

public static class PreValidation
{

    public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
    {
        if (depObj != null)
        {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
                if (child != null && child is T)
                {
                    yield return (T)child;
                }

                foreach (T childOfChild in FindVisualChildren<T>(child))
                {
                    yield return childOfChild;
                }
            }
        }
    }


    public static void Validate(DependencyObject depObj)
    {
        foreach(var c in FindVisualChildren<FrameworkElement>(depObj))
        {
            DependencyProperty p = null;

            if (c is TextBlock)
                p = TextBlock.TextProperty;
            else if (c is TextBox)
                p = TextBox.TextProperty;

            if (p != null && c.GetBindingExpression(p) != null) c.GetBindingExpression(p).UpdateSource();
        }

    }
}

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

0 голосов
/ 04 апреля 2009

Я прошел через ту же проблему и нашел очень простой способ решения этой проблемы: в событии Loaded вашего окна просто введите txtLastName.Text = String.Empty. Это оно!! Так как свойство вашего объекта изменилось (было установлено пустую строку), проверка запускается!

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