Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Silverlight - INotifyDataErrorInfo and complex property binding

I have a view model implementing INotifyDataErrorInfo. I am binding a textbox to one of the view model properties like this:

<TextBox Text="{Binding SelfAppraisal.DesiredGrowth, Mode=TwoWay, ValidatesOnNotifyDataErrors=True,NotifyOnValidationError=True}"  Height="200" 
                         TextWrapping="Wrap"/>

The data binding works, but the UI is not responding when I add validation errors like this:

// validation failed
foreach (var error in vf.Detail.Errors)
{
    AddError(SelfAppraisalPropertyName + "." + error.PropertyName, error.ErrorMessage);
}

After running GetErrors("SelfAppraisal.DesiredGrowth") in the immidiate window, I can see: Count = 1
[0]: "Must be at least 500 characters. You typed 4 characters."

I've made sure that the concatenation when adding an error matches the binding expression on the textbox, but the UI doesn't show messages as it was before I switched to using a complex type.

What am I doing wrong? Does validation with INotifyDataErrorInfo support this?

Update

My viewmodel, which implements INotifyDataErrorInfo does raise ErrorsChanged when adding/removing errors.

protected void RaiseErrorsChanged(string propertyName)
    {
        if (ErrorsChanged != null)
        {
            ErrorsChanged(this, new DataErrorsChangedEventArgs(propertyName));
        }
    }
like image 887
Ronnie Overby Avatar asked Nov 04 '22 19:11

Ronnie Overby


1 Answers

The TextBox is watching the SelfAppraisal object for error notifications. It appears that you are adding the error to the object with the SelfAppraisal property. Try adding the error to the SelfAppraisal object:

foreach (var error in vf.Detail.Errors)
{
    SelfAppraisal.AddError(error.PropertyName, error.ErrorMessage);
}

This will raise the event on the instance that the SelfAppraisal property. The TextBox looks for an error with the DesiredGrowth name as it is bound to that property.

Perhaps it helps to state that the TextBox is not watching the root object for an error with a property name of SelfAppraisal.DesiredGrowth.

UPDATE: Use the ViewModel pattern to your benefit. Create a property on your VM:

public string SelfAppraisalDesiredGrowth
{
    get { return SelfAppraisal != null ? SelfAppraisal.DesiredGrowth : null; }
    set
    {
        if (SelfAppraisal == null)
        {
            return;
        }

        if (SelfAppraisal.DesiredGrowth != value)
        {
            SelfAppraisal.DesiredGrowth = value;
            RaisePropertyChanged("SelfAppraisalDesiredGrowth");
        }
    }
}

Bind to this property:

<TextBox Text="{Binding SelfAppraisalDesiredGrowth, Mode=TwoWay, ValidatesOnNotifyDataErrors=True,NotifyOnValidationError=True}"  Height="200" TextWrapping="Wrap"/>

Use the VM property when validating:

// validation failed
foreach (var error in vf.Detail.Errors)
{
    AddError(SelfAppraisalPropertyName + error.PropertyName, error.ErrorMessage);
}
like image 118
Ed Chapel Avatar answered Nov 09 '22 16:11

Ed Chapel