0
votes

I'm new in WPF/XAML and I need help. I didn't found a response to my question in the existing questions/answers or I failed in using them. I have a wpf application with several textboxes, checkboxes and comboboxes : all are binded to properties of my Object. I have also a cancel and a validate buttons. To not update the properties bind to my textboxes (and etc...), I used UpdateSourceTrigger ="Explicit". I would like to use a ValidationRule when Focus is lost on my email address text box but I don't know how to do.

My XAML is :

<TextBox Margin="5 0 5 0" x:Name="txtBox_mailSender"  
                                     Validation.ErrorTemplate="{StaticResource ValidationTemplate}">
                            <TextBox.Text>
                                <Binding Path="SenderMailAddress"
                                         UpdateSourceTrigger="Explicit">
                                    <Binding.ValidationRules>
                                        <local:EmailAddressValidator />
                                    </Binding.ValidationRules>
                                </Binding>
                            </TextBox.Text>
                        </TextBox>

My EmailAddressValidator :

public class EmailAddressValidator : ValidationRule
{
    //public override ValidationResult Validate(object value, CultureInfo cultureInfo)
    //{
    //  Regex mailAddressRegex = new Regex(@"^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}" +
    //        @"\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\" +
    //        @".)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$");

    //  if(!mailAddressRegex.IsMatch((string)value))
    //  {
    //      return new ValidationResult(false, $"Adresse E-mail invalide.");
    //  }
    //  return new ValidationResult(true, null);
    //}

    public override ValidationResult Validate(object value, CultureInfo cultureInfo)
    {
        try
        {
            new MailAddress(value.ToString());

        }
        catch (Exception)
        {
            return new ValidationResult(false, "Adresse E-mail invalide.");
        }

        return new ValidationResult(true, null);
    }
}

My Control Template (Validation Template) but I think it's not necessary since the red border is good for me :

<ControlTemplate x:Key="ValidationTemplate">
    <DockPanel>
        <TextBlock Foreground="Red" >!</TextBlock>
        <AdornedElementPlaceholder/>
    </DockPanel>
</ControlTemplate>

I tried with the LostFocus event but I don't know how to transform the textbox into a "textbox with errors".

An extract of my object with the e-mail property :

public class MyObject
{
    public String SenderMailAddress
            {
                set
                {
                    if (SenderMailAddress != value)
                    {
                        _senderMailAddress = value;
                        OnSpecificModification();
                    }
                }
                get
                {
                    return _senderMailAddress;
                }
            }
            private String _senderMailAddress = "";
 }

Thank you for your help.

2
Why don't you want to update the source property when the validation rule succeeds?mm8
@mm8 Just in case the user doesn't want to update the changes by clicking the cancel button. In this case, he can reuse the old settings. I have a lot of properties thus it will be boring for the user to redo a lot of settings.DevA
Then you should implement IEditableObject in your view model and change UpdateSourceTrigger to PropertyChanged.mm8

2 Answers

0
votes

To use UpdateSourceTrigger="Explicit" you need to set the binding as "TwoWay" or "OneWayToSource". Then you need to call the UpdateSource on the binding. Maybe in a LostFocus event handler on the TextBox or when you press the ValidateButton. This is when the validation will occur and the Object property will be updated if the validation is passed.

Set TwoWay:

<Binding Path="SenderMailAddress" Mode="TwoWay"

UpdateSource:

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

I think your validationTemplate works. Observe the tiny exclamation point in front of the textbox.

You should look into the MVVM pattern. This will give you a lot more control and separation of your program.

0
votes

Finally, I used :

private void txtBox_mailSender_LostFocus(object sender, RoutedEventArgs e)
    {
        txtBox_mailSender.GetBindingExpression(TextBox.TextProperty).ValidateWithoutUpdate();

    }

and in my textbox

UpdateSourceTrigger="Explicit"

without specifying the binding mode.

With ValidateWithoutUpdate(), the validation rules are performed without updating the source as I wanted because I have a Validate Button in which I update the source with

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

I found this answer thanks to RolandJS and because I took a look at all the possible expressions after GetBindingExpression(TextBox.TextProperty)..

Thank you to everyone for your help ! Have a good day! Mine will be better now :-)