Showing posts with label c#. Show all posts
Showing posts with label c#. Show all posts

Wednesday, September 14, 2011

Custom Validation Attributes


while using data annotation we face difficulty for adding validation for Min and max value or for Start date and End Date. 
Validation attributes for min and Max, Startdate and Enddate
i have created Custom validation attributes which will deal with min and max values and datetime as well.

Lessthan validation attribtue 

[AttributeUsage(AttributeTargets.Property)]
  public class Lessthan : ValidationAttribute
    {
        private readonly string _dependentFieldName;
        private readonly bool _considerEqualValue;
        private PropertyType _propertyType;

        #region Constructors
        public Lessthan(string propertyName)
            : this(PropertyType.Numeric)
        {
            _dependentFieldName = propertyName;
        }

        public Lessthan(string propertyName, bool considerEqualValue)
            : this(propertyName, PropertyType.Numeric)
        {
            _considerEqualValue = considerEqualValue;
        }

        public Lessthan(string propertyName, PropertyType propertyType)
            : this(propertyType)
        {
            _dependentFieldName = propertyName;
        }

        public Lessthan(string propertyName, bool considerEqualValue, PropertyType propertyType)
            : this(propertyName, propertyType)
        {
            _considerEqualValue = considerEqualValue;
        }

        private Lessthan(PropertyType propertyType)
        {
            _propertyType = propertyType;
        }
        #endregion

        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            if (value == null)
                return new ValidationResult(base.ErrorMessage);
            PropertyInfo dependentProperty = validationContext.ObjectType.GetProperty(_dependentFieldName);
            if (dependentProperty == null)
                throw new ValidationException("No property found " + _dependentFieldName);
            switch (_propertyType)
            {
                case PropertyType.Numeric:

                    double currentAttributeValue;
                    if (!double.TryParse(value.ToString(), out currentAttributeValue))
                    {
                        throw new ValidationException("Numeric Value Expected");
                    }
                    double _dependentFieldValue;
                    var dval = dependentProperty.GetValue(validationContext.ObjectInstance, null);
                    if (dval == null)
                        return new ValidationResult(base.ErrorMessage);
                    if (!double.TryParse(dval.ToString(), out _dependentFieldValue))
                    {
                        throw new ValidationException("Numeric Value Expected for" + _dependentFieldName);
                    }

                    if (currentAttributeValue < _dependentFieldValue)
                        return ValidationResult.Success;

                    if (_considerEqualValue && currentAttributeValue <= _dependentFieldValue)
                        return ValidationResult.Success;
                    return new ValidationResult(base.ErrorMessage);

                case PropertyType.DateTime:

                    DateTime currentValue;
                    if (!DateTime.TryParse(value.ToString(), out currentValue))
                    {
                        throw new ValidationException("DateTime type Expected");
                    }
                    DateTime _dependentFieldDTValue;
                    var dtval = dependentProperty.GetValue(validationContext.ObjectInstance, null);
                    if (dtval == null)
                        return new ValidationResult(base.ErrorMessage);
                    if (!DateTime.TryParse(dtval.ToString(), out _dependentFieldDTValue))
                    {
                        throw new ValidationException("DateTime type Expected" + _dependentFieldName);
                    }

                    if (currentValue < _dependentFieldDTValue)
                        return ValidationResult.Success;

                    if (_considerEqualValue && currentValue <= _dependentFieldDTValue)
                        return ValidationResult.Success;
                    return new ValidationResult(base.ErrorMessage);
                default:
                    return ValidationResult.Success;
            }

        }
    }




Greater than validation attribute

[AttributeUsage(AttributeTargets.Property)]
    public class Greaterthan : ValidationAttribute
    {
        private readonly string _dependentFieldName;
        private readonly bool _considerEqualValue;
        private PropertyType _propertyType;

        public Greaterthan(string propertyName)
            : this(PropertyType.Numeric)
        {
            _dependentFieldName = propertyName;
        }

        public Greaterthan(string propertyName, PropertyType propertyType)
            : this(propertyType)
        {
            _dependentFieldName = propertyName;
        }

        public Greaterthan(string propertyName, bool considerEqualValue)
            : this(propertyName)
        {
            _considerEqualValue = considerEqualValue;
        }

        public Greaterthan(string propertyName, bool considerEqualValue, PropertyType propertyType)
            : this(propertyName, propertyType)
        {
            _considerEqualValue = considerEqualValue;
        }

        private Greaterthan(PropertyType propertyType)
        {
            _propertyType = propertyType;
        }

        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            if (value == null)
                return new ValidationResult(base.ErrorMessage);
            PropertyInfo dependentProperty = validationContext.ObjectType.GetProperty(_dependentFieldName);
            if (dependentProperty == null)
                throw new ValidationException("No property found " + _dependentFieldName);

            switch (_propertyType)
            {
                case PropertyType.Numeric:
                    double currentAttributeValue;
                    if (!double.TryParse(value.ToString(), out currentAttributeValue))
                        throw new ValidationException("Numeric Value Expected");

                    double _dependentFieldValue;
                    var dval = dependentProperty.GetValue(validationContext.ObjectInstance, null);
                    if (dval == null)
                        return new ValidationResult(base.ErrorMessage);
                    if (!double.TryParse(dval.ToString(), out _dependentFieldValue))
                    {
                        throw new ValidationException("Numeric Value Expected for" + _dependentFieldName);
                    }

                    if (currentAttributeValue > _dependentFieldValue)
                        return ValidationResult.Success;

                    if (_considerEqualValue && currentAttributeValue >= _dependentFieldValue)
                        return ValidationResult.Success;

                    return new ValidationResult(base.ErrorMessage);
                case PropertyType.DateTime:
                    DateTime currentValue;
                    if (!DateTime.TryParse(value.ToString(), out currentValue))
                        throw new ValidationException("DateTime Type Expected");

                    DateTime _dependentValue;
                    var dtval = dependentProperty.GetValue(validationContext.ObjectInstance, null);
                    if (dtval == null)
                        return new ValidationResult(base.ErrorMessage);
                    if (!DateTime.TryParse(dtval.ToString(), out _dependentValue))
                    {
                        throw new ValidationException("DateTime Type Expected for" + _dependentFieldName);
                    }

                    if (currentValue > _dependentValue)
                        return ValidationResult.Success;

                    if (_considerEqualValue && currentValue == _dependentValue)
                        return ValidationResult.Success;

                    return new ValidationResult(base.ErrorMessage);
                default:
                    return ValidationResult.Success;
            }

        }
    }

Monday, July 25, 2011

WPF: Build Responsive UI (Threading)

I am going to explain how to build responsive user Interface. Implementing threading in WPF.. and this post may help the people who is getting "The calling thread cannot access this object because a different thread owns it" exception

The most frequent problem or situation wpf developers face is Blocked UI.
This solution also works for "calling thread cannot access this object because a different thread owns it" exception.
when we are pooling some data to/from the server wpf UI will get hangs which will question the capability of WPF.

here i will try to explain how to use thread to overcome this.

In the following code i am creating new instance for task factory and starting a new task.
so all the code we pass in the factory will run in the background..

TaskFactory tFactory = new TaskFactory();
tFactory.StartNew(() =>
{
// DO YOUR SERVER CALLS or SOMETHING which you want to run in the background
});


After looking the above the first question comes in mind is Can i update UI from this task or thread.?
and the answer is NO You can't update UI from the background thread.
for updating UI you have to take the control to the Dispatcher thread.
some thing like this.

TaskFactory tFactory = new TaskFactory();
tFactory.StartNew(() =>
{
// DO YOUR SERVER CALLS or SOMETHING which you want to run in the background
System.Windows.Application.Current.Dispatcher.BeginInvoke((Action)delegate()
{
// UI Related stuff
});
});


We learned how to execute a task in background and how to update UI from that thread.

Now let us discuss about how to execute the task and some other code synchronously.

Consider this scenario.
we have to get some data from the server and after that we have play with data.
means our next action is completely dependent on the callback or completion of Task.

in this case we can use task factory ContinueWith method like following

TaskFactory tFactory = new TaskFactory();
tFactory.StartNew(() =>
{
// DO YOUR SERVER CALLS or SOMETHING which you want to run in the background
System.Windows.Application.Current.Dispatcher.BeginInvoke((Action)delegate()
{
// UI Related stuff
});
}).ContinueWith(t =>
{
if (t.IsFaulted)
{
throw t.Exception;
}
System.Windows.Application.Current.Dispatcher.BeginInvoke((Action)delegate()
{
// do some thig after task completion
});
});


Now i am putting all the three scenario in one place with simple example

ObservableCollection images = new ObservableCollection();
TaskFactory tFactory = new TaskFactory();
tFactory.StartNew(() =>
{
for (int i = 0; i < 50; i++)
{
//GET IMAGE Path FROM SERVER
System.Windows.Application.Current.Dispatcher.BeginInvoke((Action)delegate()
{
// UPDATE PROGRESS BAR IN UI
});

images.Add(("");
}

}).ContinueWith(t =>
{
if (t.IsFaulted)
{
// EXCEPTION IF THREAD IS FAULT
throw t.Exception;
}
System.Windows.Application.Current.Dispatcher.BeginInvoke((Action)delegate()
{
//PROCESS IMAGES AND DISPLAY
});
});


AppDomain.CurrentDomain.SetData("SQLServerCompactEditionUnderWebHosting", true);