Friday 9 December 2016

Bind a Error From model to Control ToolTip in WPF

In this post we are going to see how to bind the Error from model to Control ToolTip, For this we have to create a Model and assign the Data Annotation, Then that model should be derive from a ValidatableModelBase where we handle the errors list for model, 


    class EmployeeEdit:ValidatableViewModelBase
    {
        private Guid _id;

        private string _firstname;

        private string _lastname;

        private string _phone;

        private string _email;

        public Guid Id
        {
            get { return _id; }
            set { Set<Guid>(ref _id, value); }
        }

        [Required]
        public string FirstName
        {
            get { return _firstname; }
            set { Set<string>(ref _firstname, value); }
        }

        [Required]
        public string LastName
        {
            get { return _lastname; }
            set { Set<string>(ref _lastname, value); }
        }

        [Phone]
        public string Phone
        {
            get { return _phone; }
            set { Set<string>(ref _phone, value); }
        }

        [EmailAddress]
        public string Email
        {
            get { return _email; }
            set { Set<string>(ref _email, value); }
        }


    }




    public class ViewModelBase : INotifyPropertyChanged
    {
        protected virtual void Set<T>(ref T member, T val,
            [CallerMemberNamestring propertyName = null)
        {
            if (object.Equals(member, val)) return;

            member = val;
            PropertyChanged(thisnew PropertyChangedEventArgs(propertyName));
        }

        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChanged(thisnew PropertyChangedEventArgs(propertyName));
        }
        public event PropertyChangedEventHandler PropertyChanged = delegate { };
    }





   public class ValidatableViewModelBase : ViewModelBaseINotifyDataErrorInfo
    {
        private Dictionary<stringList<string>> _errorslist = 
                    new Dictionary<stringList<string>>();

        public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged = delegate { };

        public System.Collections.IEnumerable GetErrors(string prop)
        {
            if (_errorslist.ContainsKey(prop))
                return _errorslist[prop];
            else
                return null;
        }

        public bool HasErrors
        {
            get { return _errorslist.Count > 0; }
        }

        protected override void Set<T>(ref T member, T val, 
                 [CallerMemberNamestring propertyName = null)
        {
            base.Set<T>(ref member, val, propertyName);
            ValidateProperty(propertyName, val);
        }

        private void ValidateProperty<T>(string propname, T value)
        {
            var res = new List<ValidationResult>();
            ValidationContext ctx = new ValidationContext(this);
            ctx.MemberName = propname;

            Validator.TryValidateProperty(value, ctx, res);

            if (res.Any())
            {            
                _errorslist[propname] = res.Select(c => c.ErrorMessage).ToList();
            }
            else
            {
                _errorslist.Remove(propname);
            }
            ErrorsChanged(thisnew DataErrorsChangedEventArgs(propname));
        }


    }




View:
**************

  <UserControl.Resources>

        <conv:EdittoVisiblityConvertor x:Key="EditConvertor" />
       
        <Style TargetType="{x:Type TextBox}">
            <Style.Triggers>
                <Trigger Property="Validation.HasError" Value="true">
                    <Setter Property="ToolTip"
                            Value="{Binding
                        RelativeSource={x:Static RelativeSource.Self},
                        Path=(Validation.Errors).CurrentItem.ErrorContent}" />
                </Trigger>
            </Style.Triggers>
        </Style>
       
    </UserControl.Resources>



 <TextBox x:Name="firstNameTextBox" Grid.Column="1"
                 HorizontalAlignment="Left" Height="24" Margin="3,4,0,4"
                 Grid.Row="0"
                 Text="{Binding FirstName, ValidatesOnNotifyDataErrors=True}"
                 VerticalAlignment="Center" Width="120" Grid.ColumnSpan="3"/>




ViewModel
***********

    class AddEditEmployeeViewModel:ViewModelBase
    {
        private EmployeeEdit _employee;

        public EmployeeEdit Employee
        {
            get { return _employee; }
            set
            {
                Set<EmployeeEdit>(ref _employee, value);
            }
        }

       public RelayCommand SaveCommand;

       SaveCommand = new RelayCommand(OnSave, CanSave);

        private async void OnSave()
        {

        }

        private bool CanSave()
        {
            return !Employee.HasErrors;
        }

}




From this post you can learn how to Bind a Error from model to Control ToolTip.





No comments:

Post a Comment