I am looking for a solution for the following requirements/sceario.
I have factory object (like User Factory) which generate a binding list of business objects (like User). Each business object can store dynamic list of its attributes (in one case it might contains only 3 attributes and in another case it might contains 10 attributes. The attributes and their values are stored in Dictionary(of String, Object) and are exposed via single property called Field(columnname), where columnname is the dictionary key to access its value. The business object implements ICustomTypedProperty interface
I wish to bind the list of objects to a RadGrid, I know that binding is impossible since I cannot bind GridColumn to the Field property with a parameter. I believe that the right solution is to inherit the RadGrid control and the GridBoundColumn control, but I don't know how and when (which event to use) to bind cell value using the GetValue/SetValue methods (of the ICustomTypedProperty interface)
I will appreciate if you can provide me with an example (in VB) that works.
Avidan
16 Answers, 1 is accepted
The easiest approach would be to implement ICustomTypeDescriptor. This way you won't need to modify RadGrid in any way.
ICustomTypeDescriptor Interface (System.ComponentModel)
Regards,
Daniel
the Telerik team
My business objects do implements ICustomTypeDescriptor, I also followed the guidelines Tips when binding to custom collections. The problem is that I am actually cheating the binding control (in my case the RadGrid) by telling him that my object have a property which does not exist (i.e. Field(parm) as object) and I want to know how the Grid is using the GetValue/SetValue methods (of the ICustomTypedProperty interface) instaed of trying to find the virtual property?
Another alternative is to use Template columns in RadGrid,where the content of each column is a Label control that hook the ondatabinding event to use ICustomTypedProperty GetValue/SetValue methods , but with that solution I am unable to sort and filter grid items
Avidan
The problem is that I am actually cheating the binding control (in my case the RadGrid) by telling him that my object have a property which does not exist
Yes, this is the way the custom type descriptor should work in your scenario. This will allow you use the built-in sorting, filtering, grouping, etc. Since RadGrid doesn't know the real type of the data items in your datasource, the only way to retrieve the bindable properties is to use reflection. RadGrid extracts the property descriptors for the given types and uses these descriptors to fetch the corresponding values.
I want to know how the Grid is using the GetValue/SetValue methods (of the ICustomTypedProperty interface)
As explained above, RadGrid gets the custom property descriptor of the given properties and calls its GetValue / SetValue methods.
Another alternative is to use Template columns in RadGrid
I purposely directed you towards the ICustomTypeDesciptor - if you don't have valid data fields, most of the built-in functions won't work.
Best regards,
Daniel
the Telerik team
See the attached example; MyProduct is my business object, I'm using RadGrid advanced binding to a list of (MyProduct); All the field values are displayed correctlly, however when I try to filter/sort or groupby, I get the following error message "No property or field 'xxx' exists in type 'MyProduct'
No property or field 'NAME' exists in type 'MyProduct' Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. Exception Details: Telerik.Web.UI.ParseException: No property or field 'NAME' exists in type 'MyProduct' Source Error: An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below. Stack Trace: [ParseException: No property or field 'NAME' exists in type 'MyProduct'] Telerik.Web.UI.ExpressionParser.ParseMemberAccess(Type type, Expression instance) +1526 Telerik.Web.UI.ExpressionParser.ParseIdentifier() +549 Telerik.Web.UI.ExpressionParser.ParsePrimaryStart() +65 Telerik.Web.UI.ExpressionParser.ParsePrimary() +36 Telerik.Web.UI.ExpressionParser.ParseUnary() +365 Telerik.Web.UI.ExpressionParser.ParseMultiplicative() +54 Telerik.Web.UI.ExpressionParser.ParseAdditive() +54 Telerik.Web.UI.ExpressionParser.ParseComparison() +57 Telerik.Web.UI.ExpressionParser.ParseLogicalAnd() +49 Telerik.Web.UI.ExpressionParser.ParseLogicalOr() +49 Telerik.Web.UI.ExpressionParser.ParseExpression() +60 Telerik.Web.UI.ExpressionParser.ParseOrdering() +80 Telerik.Web.UI.GridDynamicQueryable.OrderBy(IQueryable source, String ordering, Object[] values) +420 Telerik.Web.UI.GridDataTableFromEnumerable.FillData35() +3922 Telerik.Web.UI.GridDataTableFromEnumerable.FillData() +1037 Telerik.Web.UI.GridResolveEnumerable.Initialize() +55 Telerik.Web.UI.GridResolveEnumerable.EnsureInitialized() +40 Telerik.Web.UI.GridResolveEnumerable.get_DataTable() +31 Telerik.Web.UI.GridEnumerableFromDataView..ctor(GridTableView owner, IEnumerable enumerable, Boolean CaseSensitive, Boolean autoGenerateColumns, GridColumnCollection presentColumns, String[] additionalField, Boolean retrieveAllFields) +222 Telerik.Web.UI.GridDataSourceHelper.CreateGridEnumerable(GridTableView owner, IEnumerable enumerable, Boolean caseSensitive, Boolean autoGenerateColumns, GridColumnCollection presentColumns, String[] additionalField, Boolean retrieveAllFields) +155 Telerik.Web.UI.GridDataSourceHelper.GetResolvedDataSource(GridTableView owner, Object dataSource, String dataMember, Boolean caseSensitive, Boolean autoGenerateColumns, GridColumnCollection presentColumns, String[] additionalField, Boolean retrieveAllFields) +556 Telerik.Web.UI.GridTableView.get_ResolvedDataSource() +219 Telerik.Web.UI.GridTableView.CreateChildControls(IEnumerable dataSource, Boolean useDataSource) +73 System.Web.UI.WebControls.CompositeDataBoundControl.PerformDataBinding(IEnumerable data) +57 System.Web.UI.WebControls.DataBoundControl.OnDataSourceViewSelectCallback(IEnumerable data) +114 System.Web.UI.DataSourceView.Select(DataSourceSelectArguments arguments, DataSourceViewSelectCallback callback) +31 System.Web.UI.WebControls.DataBoundControl.PerformSelect() +142 Telerik.Web.UI.GridTableView.PerformSelect() +38 System.Web.UI.WebControls.BaseDataBoundControl.DataBind() +73 Telerik.Web.UI.GridTableView.DataBind() +353 Telerik.Web.UI.GridSortCommandEventArgs.ExecuteCommand(Object source) +326 Telerik.Web.UI.RadGrid.OnBubbleEvent(Object source, EventArgs e) +191 System.Web.UI.Control.RaiseBubbleEvent(Object source, EventArgs args) +37 Telerik.Web.UI.GridItem.OnBubbleEvent(Object source, EventArgs e) +61 System.Web.UI.Control.RaiseBubbleEvent(Object source, EventArgs args) +37 Telerik.Web.UI.GridItem.OnBubbleEvent(Object source, EventArgs e) +165 System.Web.UI.Control.RaiseBubbleEvent(Object source, EventArgs args) +37 System.Web.UI.WebControls.LinkButton.OnCommand(CommandEventArgs e) +118 System.Web.UI.WebControls.LinkButton.RaisePostBackEvent(String eventArgument) +135 System.Web.UI.WebControls.LinkButton.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +10 System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +13 System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +175 System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1565 MyProduct Busines Object
Imports System Imports System.ComponentModel Imports System.Reflection Public Class MyProduct Inherits Object Implements ICustomTypeDescriptor ' MyProduct object has three virtual properties: ID, NAME and PRICE ' _values keep the object property values ' _field keep a collection of FieldPropertyDescriptors ' NOTICE: ' Whenever a programmer is trying to set a value which is not exits in _values array, ' a new FieldPropertyDescriptor is added to _fields Private _values As New Dictionary(Of String, Object) Private _fields As New PropertyDescriptorCollection(Nothing) Public Property Field(ByVal fieldname As String) As Object Get If _values.Keys.Contains(fieldname) Then Return _values(fieldname) Else Return Nothing End If End Get Set(ByVal value As Object) If _values.Keys.Contains(fieldname) Then _values(fieldname) = value Else _values.Add(fieldname, value) Me.AddFieldPropertyDescriptor(fieldname) End If End Set End Property#Region "Private Methods" Private Sub AddFieldPropertyDescriptor(ByVal fieldname As String) Dim fpd As FieldPropertyDescriptor Select Case fieldname Case "ID" Dim field As New Field("ID", "ProductID", System.Type.GetType("string", False, True), 10, False) fpd = New FieldPropertyDescriptor(field) _fields.Add(fpd) Case "NAME" Dim field As New Field("NAME", "Product Name", System.Type.GetType("string", False, True), 50, False) fpd = New FieldPropertyDescriptor(field) _fields.Add(fpd) Case "PRICE" Dim field As New Field("PRICE", "Product Price", System.Type.GetType("integer", False, True), 50, True) fpd = New FieldPropertyDescriptor(field) _fields.Add(fpd) Case Else ' do nothing End Select End Sub #End Region #Region "ICustomTypeDescriptor" Public Function GetAttributes() As System.ComponentModel.AttributeCollection Implements System.ComponentModel.ICustomTypeDescriptor.GetAttributes Return New System.ComponentModel.AttributeCollection(Nothing) End Function Public Function GetClassName() As String Implements System.ComponentModel.ICustomTypeDescriptor.GetClassName Return Nothing End Function Public Function GetComponentName() As String Implements System.ComponentModel.ICustomTypeDescriptor.GetComponentName Return Nothing End Function Public Function GetConverter() As System.ComponentModel.TypeConverter Implements System.ComponentModel.ICustomTypeDescriptor.GetConverter Return Nothing End Function Public Function GetDefaultEvent() As System.ComponentModel.EventDescriptor Implements System.ComponentModel.ICustomTypeDescriptor.GetDefaultEvent Return Nothing End Function Public Function GetDefaultProperty() As System.ComponentModel.PropertyDescriptor Implements System.ComponentModel.ICustomTypeDescriptor.GetDefaultProperty Return Nothing End Function Public Function GetEditor(ByVal editorBaseType As System.Type) As Object Implements System.ComponentModel.ICustomTypeDescriptor.GetEditor Return Nothing End Function Public Function GetEvents() As System.ComponentModel.EventDescriptorCollection Implements System.ComponentModel.ICustomTypeDescriptor.GetEvents Return New EventDescriptorCollection(Nothing) End Function Public Function GetEvents(ByVal attributes() As System.Attribute) As System.ComponentModel.EventDescriptorCollection Implements System.ComponentModel.ICustomTypeDescriptor.GetEvents Return New EventDescriptorCollection(Nothing) End Function Public Function GetProperties() As System.ComponentModel.PropertyDescriptorCollection Implements System.ComponentModel.ICustomTypeDescriptor.GetProperties Return GetProperties(Nothing) End Function Public Function GetProperties(ByVal attributes() As System.Attribute) As System.ComponentModel.PropertyDescriptorCollection Implements System.ComponentModel.ICustomTypeDescriptor.GetProperties Return _fields End Function Public Function GetPropertyOwner(ByVal pd As System.ComponentModel.PropertyDescriptor) As Object Implements System.ComponentModel.ICustomTypeDescriptor.GetPropertyOwner Return Me End Function#End Region End ClassI use custom PropertyDescriptor that provides field infromation using the Field object, code blocked are attached:
FieldPropertyDescriptor Object:
Imports System.ComponentModel Imports System.Reflection Public Class FieldPropertyDescriptor Inherits PropertyDescriptor Private _field As Field Public Sub New(ByVal field As Field) MyBase.New(field.Name, Nothing) _field = field End Sub #Region "PropertyDescriptor Overrides" #Region "Properties" Public Overrides ReadOnly Property Converter() As System.ComponentModel.TypeConverter Get Return MyBase.Converter End Get End Property Public Overrides ReadOnly Property DisplayName() As String Get Return _field.DisplayName End Get End Property Public Overrides ReadOnly Property IsReadOnly() As Boolean Get Return False End Get End Property Public Overrides ReadOnly Property Name() As String Get Return _field.Name End Get End Property Public Overrides ReadOnly Property PropertyType() As System.Type Get Return _field.Type End Get End Property #End Region #Region "Methods - Public" Public Overrides Function CanResetValue(ByVal component As Object) As Boolean Return False End Function Public Overrides ReadOnly Property ComponentType() As System.Type Get Return Me.PropertyType End Get End Property Public Overrides Function GetValue(ByVal component As Object) As Object Dim prod As MyProduct = TryCast(component, MyProduct) Return prod.Field(_field.Name) End Function Public Overrides Sub ResetValue(ByVal component As Object) Throw (New NotImplementedException()) End Sub Public Overrides Sub SetValue(ByVal component As Object, ByVal value As Object) Dim prod As MyProduct = TryCast(component, MyProduct) prod.Field(_field.Name) = value End Sub Public Overrides Function ShouldSerializeValue(ByVal component As Object) As Boolean Return False End Function #End Region #End Region End ClassField object:
Imports System Imports System.Collections.Generic Imports System.Text Public Class Field #Region "Data Members" Private _columnName As String Private _columnDisplayName As String Private _columnType As Type Private _length As Integer Private _allowNull As Boolean#End Region #Region "Constructors" Public Sub New() End Sub Public Sub New(ByVal Name As String, ByVal DisplayName As String, ByVal Type As Type, ByVal length As Integer, ByVal allowNull As Boolean) _columnName = Name _columnDisplayName = DisplayName _columnType = Type _length = length _allowNull = allowNull End Sub Public Sub New(ByVal field As Field) _columnName = field._columnName _columnDisplayName = field._columnDisplayName _columnType = field._columnType _length = field._length _allowNull = field._allowNull End Sub#End Region #Region "Properties" Public Property Name() As String Get Return _columnName End Get Set(ByVal value As String) _columnName = value End Set End Property Public Property DisplayName() As String Get Return _columnDisplayName End Get Set(ByVal value As String) _columnDisplayName = value End Set End Property Public Property Type() As Type Get Return _columnType End Get Set(ByVal value As Type) _columnType = value End Set End Property Public Property Length() As Integer Get Return _length End Get Set(ByVal value As Integer) _length = value End Set End Property Public Property AllowNull() As Boolean Get Return _allowNull End Get Set(ByVal value As Boolean) _allowNull = value End Set End Property#End Region End ClassPlease set EnableLinqExpressions="false" as shown below:
<telerik:RadGrid ID="RadGrid1" runat="server" EnableLinqExpressions="false">...</telerik:RadGrid>Let me know if the problem still persists.
Best regards,
Daniel
the Telerik team
Filtering by column does not throw any exception but the filter is not working.
When sorting by column the following exception is thrown:
Server Error in '/' Application. -------------------------------------------------------------------------------- Cannot find column NAME. Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. Exception Details: System.IndexOutOfRangeException: Cannot find column NAME. Source Error: An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below. Stack Trace: [IndexOutOfRangeException: Cannot find column NAME.] System.Data.DataTable.ParseSortString(String sortString) +4822718 System.Data.DataView.CheckSort(String sort) +32 System.Data.DataView.set_Sort(String value) +128 Telerik.Web.UI.GridEnumerableFromDataView.PerformTransformation() +3788 Telerik.Web.UI.GridEnumerableFromDataView.TransformEnumerable() +21 Telerik.Web.UI.GridTableView.GetEnumerator(Boolean useDataSource, GridEnumerableBase resolvedDataSource, ArrayList dataKeysArray) +105 Telerik.Web.UI.GridTableView.CreateControlHierarchy(Boolean useDataSource) +433 Telerik.Web.UI.GridTableView.CreateChildControls(IEnumerable dataSource, Boolean useDataSource) +498 System.Web.UI.WebControls.CompositeDataBoundControl.PerformDataBinding(IEnumerable data) +57 System.Web.UI.WebControls.DataBoundControl.OnDataSourceViewSelectCallback(IEnumerable data) +114 System.Web.UI.DataSourceView.Select(DataSourceSelectArguments arguments, DataSourceViewSelectCallback callback) +31 System.Web.UI.WebControls.DataBoundControl.PerformSelect() +142 Telerik.Web.UI.GridTableView.PerformSelect() +16 System.Web.UI.WebControls.BaseDataBoundControl.DataBind() +73 Telerik.Web.UI.GridTableView.DataBind() +221 Telerik.Web.UI.GridSortCommandEventArgs.ExecuteCommand(Object source) +126 Telerik.Web.UI.RadGrid.OnBubbleEvent(Object source, EventArgs e) +134 System.Web.UI.Control.RaiseBubbleEvent(Object source, EventArgs args) +37 Telerik.Web.UI.GridItem.OnBubbleEvent(Object source, EventArgs e) +38 System.Web.UI.Control.RaiseBubbleEvent(Object source, EventArgs args) +37 Telerik.Web.UI.GridItem.OnBubbleEvent(Object source, EventArgs e) +115 System.Web.UI.Control.RaiseBubbleEvent(Object source, EventArgs args) +37 System.Web.UI.WebControls.LinkButton.OnCommand(CommandEventArgs e) +118 System.Web.UI.WebControls.LinkButton.RaisePostBackEvent(String eventArgument) +135 System.Web.UI.WebControls.LinkButton.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +10 System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +13 System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +175 System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1565 when grouping by column the following exception is thrown:
Server Error in '/' Application. -------------------------------------------------------------------------------- Field NAME not found in the source table. Please check the expression syntax. Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. Exception Details: Telerik.Web.UI.GridGroupByException: Field NAME not found in the source table. Please check the expression syntax. Source Error: An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below. Stack Trace: [GridGroupByException: Field NAME not found in the source table. Please check the expression syntax.] Telerik.Web.UI.GridDataSetHelper.CreateGroupByTable(DataTable SourceTable, GridTableView view) +376 Telerik.Web.UI.GridEnumerableFromDataView.PerformTransformation() +2820 Telerik.Web.UI.GridEnumerableFromDataView.TransformEnumerable() +21 Telerik.Web.UI.GridTableView.GetEnumerator(Boolean useDataSource, GridEnumerableBase resolvedDataSource, ArrayList dataKeysArray) +105 Telerik.Web.UI.GridTableView.CreateControlHierarchy(Boolean useDataSource) +433 Telerik.Web.UI.GridTableView.CreateChildControls(IEnumerable dataSource, Boolean useDataSource) +498 System.Web.UI.WebControls.CompositeDataBoundControl.PerformDataBinding(IEnumerable data) +57 System.Web.UI.WebControls.DataBoundControl.OnDataSourceViewSelectCallback(IEnumerable data) +114 System.Web.UI.DataSourceView.Select(DataSourceSelectArguments arguments, DataSourceViewSelectCallback callback) +31 System.Web.UI.WebControls.DataBoundControl.PerformSelect() +142 Telerik.Web.UI.GridTableView.PerformSelect() +16 System.Web.UI.WebControls.BaseDataBoundControl.DataBind() +73 Telerik.Web.UI.GridTableView.DataBind() +221 Telerik.Web.UI.GridTableView.BindAllInHierarchyLevel() +52 Telerik.Web.UI.RadGrid.RaisePostBackEvent(String eventArgument) +5114 System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +13 System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +175 System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1565 Avidan
Can you please post the rest of the code so that we can construct a fully runnable demo based on your scenario?
Regards,
Daniel
the Telerik team
enclose aspx and it's code beind:
Aspx:
<body> <form id="form1" runat="server"> <telerik:RadScriptManager ID="RadScriptManager1" runat="server"> </telerik:RadScriptManager> <telerik:RadGrid ID="RadGrid1" runat="server" AllowFilteringByColumn="True" AllowPaging="True" AllowSorting="True" AutoGenerateColumns="False" GridLines="None" ShowGroupPanel="True" Skin="Outlook" AutoGenerateDeleteColumn="True" AutoGenerateEditColumn="True" EnableLinqExpressions ="false"> <MasterTableView> <RowIndicatorColumn> <HeaderStyle Width="20px"></HeaderStyle> </RowIndicatorColumn> <ExpandCollapseColumn> <HeaderStyle Width="20px"></HeaderStyle> </ExpandCollapseColumn> <Columns> <telerik:GridBoundColumn DataField="ID" HeaderText="ID" UniqueName="column" SortExpression="ID" > </telerik:GridBoundColumn> <telerik:GridBoundColumn DataField="NAME" HeaderText="Name" UniqueName="column1"> </telerik:GridBoundColumn> <telerik:GridBoundColumn DataField="PRICE" DataType="System.Int32" HeaderText="Price" UniqueName="column2"> </telerik:GridBoundColumn> </Columns> </MasterTableView> <ClientSettings AllowDragToGroup="True"> <Selecting AllowRowSelect="True" /> <Scrolling AllowScroll="True" UseStaticHeaders="True" /> </ClientSettings> </telerik:RadGrid> <div> </div> </form> </body>Code behind:
Protected Sub RadGrid1_NeedDataSource(ByVal source As Object, ByVal e As Telerik.Web.UI.GridNeedDataSourceEventArgs) Handles RadGrid1.NeedDataSource Dim list As New MyProductsList Me.RadGrid1.DataSource = list.GetLists End SubThank you for the sample code. Please download the attached project and let me know whether it works properly on your end.
Regards,
Daniel
the Telerik team
it works properly !!!
Now tell me your secrets, what have you done to make it work.
Avidan
public partial class Default : System.Web.UI.Page{ protected void Page_Init(object sender, EventArgs e) { LinqDataSource linqDataSource = new LinqDataSource(); linqDataSource.Selecting += new EventHandler<LinqDataSourceSelectEventArgs>(LinqDataSource_Selecting); linqDataSource.Selected += new EventHandler<LinqDataSourceStatusEventArgs>(LinqDataSource_Selected); this.RadGrid1.DataSource = linqDataSource; } void LinqDataSource_Selecting(object sender, LinqDataSourceSelectEventArgs e) { if (Cache["MyData"] != null) { e.Result = Cache["MyData"]; } else { MyProductList list = new MyProductList(); e.Result = list.GetLists().AsQueryable(); } } void LinqDataSource_Selected(object sender, LinqDataSourceStatusEventArgs e) { if (Cache["MyData"] == null && e.Result != null) { Cache["MyData"] = e.Result; } }}The problem now is that sorting and grouping produces the following error. Any thoughts on getting the example going with linq datasource caching without loosing the sorting and grouping abilities? is an alternative caching strategy required?
|
Could you please isolate the problem in a runnable project (as simple as possible) so that we can debug the code locally? You can attach the code to a regular support ticket.
Isolating a problem in a sample project
Thank you for your understanding.
Best regards,
Daniel
the Telerik team
Browse the vast support resources we have to jump start your development with RadControls for ASP.NET AJAX. See how to integrate our AJAX controls seamlessly in SharePoint 2007/2010 visiting our common SharePoint portal.
Could you point me to proper way of handling custom sorting in RadGrid?
With markup as following -
<telerik:RadGrid ID="someGrid" runat="server" AllowSorting="True" OnSortCommand="someGrid_SortCommand"> <MasterTableView> <Columns> <telerik:GridHyperLinkColumn SortExpression="someCustomSortExpression" DataTextField="someField"/> </Columns> </MasterTableView> </telerik:RadGrid>I keep receiving exception "Cannot find column someCustomSortExpression" or ("no property or field someCustomSortExpression found" if column was created dynamically, which is ultimately a goal)
Thanks!
<telerik:RadGrid ID="someGrid" runat="server" AllowSorting="True" OnSortCommand="someGrid_SortCommand"> <MasterTableView> <Columns> <telerik:GridHyperLinkColumn SortExpression="someField" DataTextField="someField"/> </Columns> </MasterTableView> </telerik:RadGrid>The SortExpression value should match the value of the field set through the DataTextField property of the hyperlink column.
-Kiara
Unfortunately, it makes no sense to use already defined property for SortExpression in this snippet, as topic specifically refers to "dynamic/undeclared properties"
Andrey.