Pregunta

Estoy intentando validar el formulario WPF con un objeto.La validación se activa cuando escribo algo en el cuadro de texto, pierdo el foco, vuelvo al cuadro de texto y luego borro lo que he escrito.Pero si simplemente cargo la aplicación WPF y salgo del cuadro de texto sin escribir ni borrar nada del cuadro de texto, entonces no se activa.

Aquí está la clase 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;
            }
        }
    }

Y aquí está el código 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>
¿Fue útil?

Solución

Si no es reacio a poner un poco de lógica en su código, puede manejar la situación real. Perdió el enfoque evento con algo como esto:

.xaml

<TextBox LostFocus="TextBox_LostFocus" ....

.xaml.cs

private void TextBox_LostFocus(object sender, RoutedEventArgs e)
{
     ((Control)sender).GetBindingExpression(TextBox.TextProperty).UpdateSource();
}

Otros consejos

Desafortunadamente esto es por diseño.La validación de WPF solo se activa si el valor en el control ha cambiado.

Increíble, pero cierto.Hasta ahora, la validación de WPF es el gran dolor proverbial: es terrible.

Sin embargo, una de las cosas que puede hacer es obtener la expresión vinculante de la propiedad del control e invocar manualmente las validaciones.Apesta, pero funciona.

Échale un vistazo al ValidatesOnTargetActualizado propiedad de ValidationRule.Se validará cuando los datos se carguen por primera vez.Esto es bueno si intentas capturar campos vacíos o nulos.

Actualizaría su elemento vinculante de esta manera:

<Binding 
    Source="{StaticResource CustomerKey}" 
    Path="LastName" 
    ValidatesOnExceptions="True" 
    ValidatesOnDataErrors="True" 
    UpdateSourceTrigger="LostFocus">
    <Binding.ValidationRules>
        <DataErrorValidationRule
            ValidatesOnTargetUpdated="True" />
    </Binding.ValidationRules>
</Binding>

Descubrí que la mejor manera de manejar esto fue en el evento LostFocus del cuadro de texto. Hago algo como esto.

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

Entonces ve un error

Pasé por el mismo problema y encontré una manera ultra simple de resolverlo:en el evento Cargado de su ventana, simplemente escriba txtLastName.Text = String.Empty.¡¡Eso es todo!!Dado que la propiedad de su objeto ha cambiado (se ha establecido en una cadena vacía), ¡la validación se activa!

El siguiente código recorre todos los controles y los valida.No necesariamente es la forma preferida, pero parece funcionar.Sólo hace TextBlocks y TextBoxes pero puedes cambiarlo fácilmente.

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();
        }

    }
}

Simplemente llame a Validar en su ventana o control y debería validarlos previamente por usted.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top