Filter a Custom Type
If you want to filter a column that is data-bound to a custom type, you need to make sure that your custom type meets certain criteria. We will use the type Person as an example.
Example 1: The Person class
public class Person
{
private readonly string name;
private int age;
public string Name
{
get { return this.name; }
}
public int Age
{
get { return this.age; }
set { this.age = value; }
}
public Person(string name)
{
this.name = name;
}
}The first thing that you need to do is implement the generic IEquatable interface. It has a single method called Equals. Next, you need to override Object.Equals(Object) and Object.GetHashCode. MSDN states that if you implement generic IEquatable, you have to also override the base class implementations of Object.Equals(Object) and Object.GetHashCode so that their behavior is consistent with that of the generic IEquatable.Equals method.
Implement IEquatable
Example 2: IEquatable implementation
public class Person : IEquatable<Person>
{
private readonly string name;
private int age;
public string Name
{
get { return this.name; }
}
public int Age
{
get { return this.age; }
set { this.age = value; }
}
public Person(string name)
{
this.name = name;
}
bool IEquatable<Person>.Equals(Person other)
{
if (other == null)
{
return false;
}
return StringComparer.Ordinal.Equals(this.Name, other.Name);
}
}Override Object.Equals(Object) and Object.GetHashCode
If you do override Object.Equals(Object), your overridden implementation is also called in calls to the static Equals(System.Object, System.Object) method on your class. This ensures that all invocations of the Equals method return consistent results. Furthermore, the GetHashCode method will be used by the framework when the distinct values need to be discovered.
Example 3: Equals and GetHashCode overrides
public override bool Equals(object obj)
{
return ((IEquatable<Person>)this).Equals(obj as Person);
}
public override int GetHashCode()
{
return this.Name.GetHashCode() ^ this.Age.GetHashCode();
}Override ToString
Next, you need to override the ToString method of your type so that distinct values and grid cells display a friendly representation of your class. Here is what the class might look like:
Example 4: ToString override
public override string ToString()
{
return this.Name;
}Define a TypeConverter for String Conversions
Next you will need to define a TypeConverter for string conversions. When RadGridView encounters a custom type it will use a plain TextBox for the field filter editors. The strings that user enters have to be converted to your custom type and vice versa. This can be achieved by specifying a TypeConverter on your class.
Example 5: Custom TypeConverter
public class PersonConverter : System.ComponentModel.TypeConverter
{
public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(string))
{
return true;
}
return base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
{
var stringValue = value as string;
if (stringValue != null)
{
return new Person(stringValue);
}
return base.ConvertFrom(context, culture, value);
}
public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, Type destinationType)
{
if (destinationType == typeof(string))
{
return true;
}
return base.CanConvertTo(context, destinationType);
}
public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(string))
{
return ((Person)value).ToString();
}
return base.ConvertTo(context, culture, value, destinationType);
}
}Do not forget to add the TypeConverter attribute on your class definition and point it to the custom TypeConverter that you just created.
Example 6: Adding the TypeConverter attribute
[TypeConverter(typeof(PersonConverter))]
public class Person : IEquatable<Person>
{
// ...
}If the plain TextBox does not suit your needs, you can provide your own field filter editor by overriding the GridViewDataColumn.CreateFieldFilterEditor method as described here. You will no longer need a TypeConverter if your custom field filter editor is able to produce instances of your custom type.
Override the Comparison Operators (Optional)
If you want to see the comparison filter operators (Is Less Than, etc.) you should override your custom type's comparison operators.
Example 7: Comparison operators override
public static bool operator <(Person left, Person right)
{
return left.Age < right.Age;
}
public static bool operator <=(Person left, Person right)
{
return left.Age <= right.Age;
}
public static bool operator >(Person left, Person right)
{
return left.Age > right.Age;
}
public static bool operator >=(Person left, Person right)
{
return left.Age >= right.Age;
}