Hey folks.
The past 2 months i was implementing an application using the telerik controls.
Awesome control set by the way. Love them.
But there is a slight disadvantage as i thought. The setup of columns for the RadGridView.
There is the possibility to use AutoGenerateColumns or just set them up in your .xaml.
For your information i am using a MVVM implementation. The problem for me, i have views which are basicly the same.
They only differ in some additional columns for the grid.
I have come up that AutoGenerateColumns is just an awesome feature to give a simple ViewItem into a list an set the list as ItemsSource, now my columns just show up. Adding some annotations to the properties is just a cool way to give them special behavior.
But what about custom annotations? E.g. disable distinct filters and to so on. Fortunatly RadGridView supports basic annotations (System.ComponentModel.DataAnnotations) which is good, but not perfect.
To enhance this, i have come up to implement CustomAttributes.
Here you can see my simple CustomAttribute class:
As you can see i have added an abstract method UpdateColumn() this method will be implemented in each attribute you like to use.
This is used to updated the column which your own logic. As seen here, a simple ShowDistinctFilterAttribute:
Now things gettin' serious. We need to intercept the autogenerating of columns.
We need a class derived from RadGridView. Giving you this:
You might ask why this class is a generic type. Well since we are using reflection to get our custom attributes. We need to now which type our items are using. RadGridView itself is a bit "well sealed" of getting the datetype of a column item so i come up with this solution. I am skipping the explanation how this code works, i hope the comment lines are enough for this :)
Now you simply need to derive from this BaseGridView<T> to create the grid you need.
And the GridViewItem you might want to use with our own attribute:
Now only create a list to set your ItemsSource
Hope i could help some of you out there :)
Greets.
The past 2 months i was implementing an application using the telerik controls.
Awesome control set by the way. Love them.
But there is a slight disadvantage as i thought. The setup of columns for the RadGridView.
There is the possibility to use AutoGenerateColumns or just set them up in your .xaml.
For your information i am using a MVVM implementation. The problem for me, i have views which are basicly the same.
They only differ in some additional columns for the grid.
I have come up that AutoGenerateColumns is just an awesome feature to give a simple ViewItem into a list an set the list as ItemsSource, now my columns just show up. Adding some annotations to the properties is just a cool way to give them special behavior.
But what about custom annotations? E.g. disable distinct filters and to so on. Fortunatly RadGridView supports basic annotations (System.ComponentModel.DataAnnotations) which is good, but not perfect.
To enhance this, i have come up to implement CustomAttributes.
Here you can see my simple CustomAttribute class:
/// <summary>
/// Abstract class for custom attributes.
/// This class is used to filter only our custom attribute using reflection.
/// </summary>
public
abstract
class
CustomAttribute : System.Attribute
{
/// <summary>
/// Updates a given colum using the implementers logic.
/// </summary>
/// <param name="column">The <see cref="GridViewColumn"/> to update.</param>
public
abstract
void
UpdateColumn(GridViewColumn column);
}
As you can see i have added an abstract method UpdateColumn() this method will be implemented in each attribute you like to use.
This is used to updated the column which your own logic. As seen here, a simple ShowDistinctFilterAttribute:
/// <summary>
/// Enables or disabled the distinct filter functionality of a <see cref="GridViewColumn"/>
/// </summary>
public
class
ShowDistinctFilterAttribute : CustomAttribute
{
public
bool
DistinctFilters {
get
;
private
set
; }
public
ShowDistinctFilterAttribute(
bool
b)
{
DistinctFilters = b;
}
/// <summary>
/// Updates a given colum using the implementers logic.
/// </summary>
/// <param name="column">The <see cref="GridViewColumn"/> to update.</param>
public
override
void
UpdateColumn(GridViewColumn column)
{
column.ShowDistinctFilters = DistinctFilters;
}
}
Now things gettin' serious. We need to intercept the autogenerating of columns.
We need a class derived from RadGridView. Giving you this:
public
class
BaseGridView<TViewItemType> : RadGridView
{
/// <summary>
/// Raises the AutoGeneratingColumn event.
/// </summary>
protected
override
void
OnAutoGeneratingColumn(GridViewAutoGeneratingColumnEventArgs e)
{
/**
* This method gets overridden to update the autogenerated columns
* with our own custom attributes. The update itself it handled
* in the attribute class itself using the UpdateColumn() method.
*/
// first we need the type of the current viewitem.
var viewItemType =
typeof
(TViewItemType);
// next up we are getting the property
// this property should have some attributes assigned to it.
var property = viewItemType.GetProperty(e.ItemPropertyInfo.Name);
// first off, check if the property even exists
if
(property !=
null
)
{
// now we only get custom attributes of a certain type
// each attribute we want will derive from CustomAttribute class
var attribs = property.GetCustomAttributes(
typeof
(CustomAttribute),
true
);
// check if custom attributes are assigned to the current property
if
(attribs.Any())
{
// iterate through a casted list
// this is needed to get reference to the UpdateColumn() method.
foreach
(var attrib
in
attribs.Cast<CustomAttribute>().ToArray())
{
// update our column
attrib.UpdateColumn(e.Column);
}
}
}
// call base functionality
base
.OnAutoGeneratingColumn(e);
}
}
You might ask why this class is a generic type. Well since we are using reflection to get our custom attributes. We need to now which type our items are using. RadGridView itself is a bit "well sealed" of getting the datetype of a column item so i come up with this solution. I am skipping the explanation how this code works, i hope the comment lines are enough for this :)
Now you simply need to derive from this BaseGridView<T> to create the grid you need.
public
class
CustomerGridView : BaseGridView<GridViewItem>
{
}
And the GridViewItem you might want to use with our own attribute:
public
class
GridViewItem
{
/// <summary>
/// Gets or sets the the awesome attribute.
/// </summary>
[ShowDistinctFilter(
false
)]
public
string
Attribute
{
get
{
return
"Awesome attribute"
; }
set
{ }
}
}
Now only create a list to set your ItemsSource
radGridView.ItemsSource =
new
List<GridViewItem> {
new
GridViewItem() };
Hope i could help some of you out there :)
Greets.