views:

305

answers:

2

I'm trying to change the IsEnabled property of a button if the validation on some of the textboxes in my form return true. So if there is errors, the IsEnabled property should be set to false.

For some reason I cannot get it to work. The IDataErrorInfo implementation is only called after my IsEmailValid property is called, so the Validation.GetHasError always returns false and my button is never disabled.

Can anybody help?

Code:

Textbox validated with IDataErrorInfo

<TextBox Style="{StaticResource textBoxInError}" Name="txtEmail" Grid.Column="1" Grid.Row="2" Width="150" Height="23" HorizontalAlignment="Right" VerticalAlignment="Center">
            <TextBox.Text>
                <Binding Path="Email" Mode="TwoWay"
                         ValidatesOnDataErrors="True"
                         UpdateSourceTrigger="LostFocus"
                         ></Binding>
            </TextBox.Text>
        </TextBox>

IDataErrorInfo Implementation:

 public string Error
        {
            get
            {
                return null;
            }
        }

        public string this[string name]
        {
            get
            {
                string result = null;
                #region Email
                if (name == "Email")
                {
                    if (!presenter.LenientValidateEmail(Email))
                    {                      
                         result = "Your email address is not valid";

                    }

                }
                #endregion

                #region Website

                #endregion
                return result;
            }
        }

Button binding on IsEnabled

<Button Name="btnUpdate" IsEnabled="{Binding IsValid}" HorizontalAlignment="Left" Grid.Column="3" Grid.RowSpan="2" Grid.Row="6" Height="23" Width="75" Click="btnUpdate_Click">Update
        </Button>

public bool IsValid
        {
            get
            {
                return IsEmailValid();
            }
        }



public string Email
        {
            get
            {
                return _email;
            }
            set
            {
                _email = value;
                OnPropertyChanged("Email"); // executes before IDataErrorInfo Implementation
            }
        }




 private bool IsEmailValid()
    {
        object el = FindName("txtEmail");


        if (el != null)
        {
            _isEmailValid = Validation.GetHasError((DependencyObject)el); // always false??

            if (_isEmailValid)
            {
                return false;
            }
            else
                return true;
        }
        return true;

    }

//PropertyChanged event handler:
    void ProfileView_PropertyChanged(object sender, PropertyChangedEventArgs e)
            {
                IsEmailValid();
            }
+1  A: 

When I understand your code extracts correctly, I think the problem is that the UI is not notified when an invalid email address has been entered. In ProfileView_PropertyChanged(...) you check whether the eMail is valid, and if it is invalid, IsEmailValid() should return false. However, nothing is done with this result; most important: the UI is not notified about the change of the IsValid property, and therefore, the button's IsEnabled state is not updated. Certainly, the return value of the IsValid property would change after an invalid eMail has been entered, but the UI does not request this new value.

The solution should be to raise the PropertyChanged event for the IsValid property in the ProfileView_PropertyChanged(...) method, like so:

void ProfileView_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    IsEmailValid();
    OnPropertyChanged("IsValid"); // <== this one is important!
}

You could also wrap the OnPropertyChanged(...) call into an if statement, depending on the result of IsEmailValid(), but that's up to you.

Actually, you do not even need the call to the IsEmailValid() method in there because it will be called immediately after the PropertyChanged event is raised. However, I did not want to remove that because I do not know whether this might introduce some other error in your application.

gehho
A: 

I've resolved it.

Using a dictionary to keep track of all errors generated by IDataErrorInfo and then in IsEmailValid(), validate the email address. Then add/remove error from dictionary if email is or is not valid!! :)

Tony