New to Telerik UI for WinFormsStart a free 30-day trial

How to filter RadGridView by custom types

Updated over 1 year ago

Environment

Product VersionProductAuthor
2018.3.1016RadGridView for WinFormsDesislava Yordanova

Description

By design, the filter operators in the RadGridView's columns depend on the data type that is being stored in that column. That is why when you have a complex object, IsNull, IsNotNull and Custom options are shown. However, you can handle this case and implement the logic for filtering the custom types.

Solution

Consider the case that you have a Person class that has an int Id property, a string Name property and a custom type property YearOfBirth that is a wrapper of the integer value for the year.

Custom classes

C#

        public class Person
        {
            public int Id { get; set; }

            public string Name { get; set; }

            public YearOfBirth YearOfBirth { get; set; }

            public Person(int id, string name, YearOfBirth year)
            {
                this.Id = id;
                this.Name = name;
                this.YearOfBirth = year;
            }
        }

        public class YearOfBirth 
        {
            public int Year { get; set; }

            public YearOfBirth(int year)
            {
                this.Year = year;
            }

            public override string ToString()
            {
                return this.Year.ToString();
            }
        }

The grid is bound to a collection of Person objects:

Populate the grid

C#

            List<Person> people = new List<Person>();
            people.Add(new Person(1, "Nancy Davolio", new YearOfBirth(1985)));
            people.Add(new Person(2, "Robert King", new YearOfBirth(1968)));
            people.Add(new Person(3, "Steven Buchanan", new YearOfBirth(1974)));
            people.Add(new Person(4, "Janet Leverling", new YearOfBirth(1982)));
            people.Add(new Person(5, "Andrew Fuller", new YearOfBirth(1978)));
            people.Add(new Person(6, "John Brown", new YearOfBirth(1974)));
            people.Add(new Person(7, "James Orleans", new YearOfBirth(2005)));
            people.Add(new Person(8, "Khan Asparuh", new YearOfBirth(681)));

            this.radGridView1.DataSource = people; 
            this.radGridView1.EnableFiltering = true;

If you try to filtering by the YearOfBirth property, you will notice that the IsNull, IsNotNull and Custom filter options are shown.

filter-grid-by-custom-type 001

In order to allow filter by your custom YearOfBirth type you should perform the following steps:

1. Set the DataType property of the column to typeof(int) since we will filter by the numeric value of the custom class.

2. Your custom class YearOfBirth should implement the IConvertible interface.

3. Create a custom TypeConverter in order to convert the custom YearOfBirth type to string and vice versa.

C#

        public RadForm1()
        {
            InitializeComponent();

            List<Person> people = new List<Person>();
            people.Add(new Person(1, "Nancy Davolio", new YearOfBirth(1985)));
            people.Add(new Person(2, "Robert King", new YearOfBirth(1968)));
            people.Add(new Person(3, "Steven Buchanan", new YearOfBirth(1974)));
            people.Add(new Person(4, "Janet Leverling", new YearOfBirth(1982)));
            people.Add(new Person(5, "Andrew Fuller", new YearOfBirth(1978)));
            people.Add(new Person(6, "John Brown", new YearOfBirth(1974)));
            people.Add(new Person(7, "James Orleans", new YearOfBirth(2005)));
            people.Add(new Person(8, "Khan Asparuh", new YearOfBirth(681)));

            this.radGridView1.DataSource = people;
            this.radGridView1.EnableFiltering = true;
            this.radGridView1.AutoSizeColumnsMode = Telerik.WinControls.UI.GridViewAutoSizeColumnsMode.Fill;

            this.radGridView1.Columns.Last().DataType = typeof(int);
        }

        public class Person
        {
            public int Id { get; set; }

            public string Name { get; set; }

            public YearOfBirth YearOfBirth { get; set; }

            public Person(int id, string name, YearOfBirth year)
            {
                this.Id = id;
                this.Name = name;
                this.YearOfBirth = year;
            }
        }

        [TypeConverter(typeof(YearTypeConverter))]
        public class YearOfBirth : IConvertible
        {
            public int Year { get; set; }

            public YearOfBirth(int year)
            {
                this.Year = year;
            }

            public override string ToString()
            {
                return this.Year.ToString();
            }

            public TypeCode GetTypeCode()
            {
                return TypeCode.Object;
            }

            public bool ToBoolean(IFormatProvider provider)
            {
                return false;
            }

            public byte ToByte(IFormatProvider provider)
            {
                return 0;
            }

            public char ToChar(IFormatProvider provider)
            {
                return ' ';
            }

            public DateTime ToDateTime(IFormatProvider provider)
            {
                return DateTime.MinValue;
            }

            public decimal ToDecimal(IFormatProvider provider)
            {
                return (Decimal)this.Year;
            }

            public double ToDouble(IFormatProvider provider)
            {
                return (Double)this.Year;
            }

            public short ToInt16(IFormatProvider provider)
            {
                return (Int16)this.Year;
            }

            public int ToInt32(IFormatProvider provider)
            {
                return (Int32)this.Year;
            }

            public long ToInt64(IFormatProvider provider)
            {
                return (Int64)this.Year;
            }

            public sbyte ToSByte(IFormatProvider provider)
            {
                return 0;
            }

            public float ToSingle(IFormatProvider provider)
            {
                return (Single)this.Year;
            }

            public string ToString(IFormatProvider provider)
            {
                return this.Year.ToString();
            }

            public object ToType(Type conversionType, IFormatProvider provider)
            {
                return this.ToString();
            }

            public ushort ToUInt16(IFormatProvider provider)
            {
                return (ushort)this.Year;
            }

            public uint ToUInt32(IFormatProvider provider)
            {
                return (UInt32)this.Year;
            }

            public ulong ToUInt64(IFormatProvider provider)
            {
                return (ulong)this.Year;
            }
        }

        public class YearTypeConverter : TypeConverter
        {
            public override bool CanConvertTo(ITypeDescriptorContext context, System.Type destinationType)
            {
                if (destinationType == typeof(string))
                {
                    return true;
                }
                return base.CanConvertTo(context, destinationType);
            }

            public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType)
            {
                YearOfBirth c = value as YearOfBirth;
                if (destinationType == typeof(string) && c != null)
                {
                    return c.ToString();
                }
                return base.ConvertTo(context, culture, value, destinationType);
            }

            public override bool CanConvertFrom(ITypeDescriptorContext context, System.Type sourceType)
            {
                if (sourceType == typeof(string))
                {
                    return true;
                }
                return base.CanConvertFrom(context, sourceType);
            }

            public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
            {
                if (value != null)
                {
                    if (value.ToString() == string.Empty)
                    {
                        return null;
                    }
                    int year = 0;
                    if (int.TryParse(value.ToString(), out year))
                    {
                        return new YearOfBirth(year);
                    }
                }

                return base.ConvertFrom(context, culture, value);
            }
        }

Now, you can filter by your custom property as if it is a numeric field:

filter-grid-by-custom-type 002

This article demonstrates just a sample approach how you can handle filtering by custom types. You can extend this example and cover any custom scenario that you have.

See Also