And I am assigning datakeys to mastertable view in page_load().
RadGrid.MasterTableView.DataKeyNames = new string[] { "column1, column2" };
Its giving error, the column neither a DataColumn nor a DataRelation for table xxx. Please guide how to assign datakeys programatically to mastertable view and grid view.
Thank you,
Madhavi
9 Answers, 1 is accepted

I am looking to dynamically change datakeynames to the master grid and detail grid. Can anybody share ideas, how to approach it.
Thanks
Try to do that on Page_Init instead. Please keep in mind that if you will change the columns structure dynamically, you should follow the steps provided in the following article:
http://docs.telerik.com/devtools/aspnet-ajax/controls/grid/defining-structure/changing-the-grid-structure-dynamically-on-postback
Hope this helps.
Regards,
Eyup
Telerik

Hi Eyup,
In my scenario, column structure of the grids is constant. I am trying to change the datakeynames assigned to both mastertable and detailtable dynamically based on user selection. I am trying the following procedure. Please let me know if I am approaching in correct way.
In aspx file , I declared the grid and their columns statically as below
<t:RadGrid ID="rgLEV" runat="server" Width="1200px" AllowSorting="True" GridLines="None" ShowFooter="True" AutoGenerateColumns="False" EnableViewState= "false" AutoGenerateHierarchy="false" Skin="Web20" CssClass="rgDataDiv"
GroupingEnabled="true" ShowGroupPanel="true" OnGroupsChanging="rgLEV_GroupsChanging" AllowMultiRowSelection="true"
HeaderStyle-Wrap="false" ItemStyle-Wrap="false"
OnNeedDataSource="rgLEV_NeedDataSource"
OnPreRender="rgLEV_PreRender"
OnItemCommand="rgLEV_ItemCommand"
OnUpdateCommand="rgLEV_UpdateCommand"
OnItemCreated="rgLEV_ItemCreated"
OnDetailTableDataBind="rgLEV_DetailTableDataBind"
OnItemDataBound="rgLEV_ItemDataBound"
OnExportCellFormatting="rgLEV_ExportCellFormatting" >
<ClientSettings AllowDragToGroup="True" AllowColumnsReorder="True"
ReorderColumnsOnClient="True">
<Selecting AllowRowSelect="true" EnableDragToSelectRows="true" />
</ClientSettings>
<GroupingSettings RetainGroupFootersVisibility="true"/>
<MasterTableView Name="MasterTableView" AutoGenerateColumns="false" EnableColumnsViewState="false" EditMode="EditForms" CommandItemDisplay="Top" NoMasterRecordsText="No records to display."
ExpandCollapseColumn-ButtonType="ImageButton" ShowGroupFooter="true"
ExpandCollapseColumn-CollapseImageUrl="Images/SingleMinus.gif" ExpandCollapseColumn-ExpandImageUrl="Images/SinglePlus.gif"
HierarchyLoadMode="ServerOnDemand" ExpandCollapseColumn-HeaderButtonType="LinkButton" GroupLoadMode="Client">
<CommandItemTemplate>
<div> ........ </div>
</CommandItemTemplate>
<Columns> ........ </Columns>
<DetailTables>
<t:GridTableView Name="gtvDetail1" ShowFooter="False" EnableColumnsViewState = "false" AutoGenerateColumns="true" NoDetailRecordsText="No records to display." Width="500px" BorderWidth="1"
HierarchyLoadMode="ServerBind" >
<Columns>
<t:GridBoundColumn DataField="LD_APPROVED_BY" HeaderText="Approved By" ItemStyle-Wrap="false" ReadOnly="true" />
<t:GridDateTimeColumn DataField="LD_APPROVED_DT" HeaderText="Approved Date" ItemStyle-Wrap="false" ReadOnly="true" />
</Columns>
</t:GridTableView>
</DetailTables>
<ExpandCollapseColumn HeaderButtonType="PushButton" HeaderText="Expand/Collapse All" HeaderStyle-Width="50px" /> <EditFormSettings>
<EditColumn ButtonType="ImageButton" />
</EditFormSettings>
</MasterTableView>
<GroupPanel Visible="True">
</GroupPanel>
<ClientSettings AllowDragToGroup="True" Selecting-AllowRowSelect="true" AllowExpandCollapse="true" >
</ClientSettings>
<ExportSettings ExportOnlyData="true" IgnorePaging="true" OpenInNewWindow="true" HideStructureColumns="true" FileName="Labor Verification" >
<Excel Format="Html" />
</ExportSettings>
</RadGrid>
---------------------------------------------------------------------------------------------------------
And in code behind,
I am assigning datakeynames dynamically in Page_Init() like you said. and accessing the datakeynames in DetailTableDataBind().
protected void Page_Init(object sender, EventArgs e)
{
if (!IsPostBack)
{
GridTableView gtv = rgLEV.MasterTableView.DetailTables[0];
GridRelationFields relationField2 = new GridRelationFields();
if (Version >= 15)
{
rgLEV.MasterTableView.DataKeyNames = new string[] { "LABOR_IDENT, LD_STATUS" };
gtv.DataKeyNames = new string[] { "LABOR_IDENT, LD_STATUS" };
GridRelationFields relationField1 = new GridRelationFields();
gtv.ParentTableRelation.Add(relationField1);
relationField1.MasterKeyField = "LABOR_IDENT";
relationField1.DetailKeyField = "LABOR_IDENT";
}
else
{
rgLEV.MasterTableView.DataKeyNames = new string[] { "WORK_DT_SEQ, LD_STATUS" };
gtv.DataKeyNames = new string[] { "WORK_DT_SEQ, LD_STATUS" };
GridRelationFields relationField1 = new GridRelationFields();
gtv.ParentTableRelation.Add(relationField1);
relationField1.MasterKeyField = "WORK_DT_SEQ";
relationField1.DetailKeyField = "WORK_DT_SEQ";
}
GridRelationFields relationField2 = new GridRelationFields();
gtv.ParentTableRelation.Add(relationField2);
relationField2.MasterKeyField = "LD_STATUS";
relationField2.DetailKeyField = "LD_STATUS";
}
protected void rgLEV_DetailTableDataBind(object sender, GridDetailTableDataBindEventArgs e)
{
GridDataItem gdi = e.DetailTableView.ParentItem as GridDataItem;
string intSeq;
string expression;
if (e.DetailTableView.Name == "gtvDetail1")
{
if (CommonFunctions.GetAMVersion >= 1520.0)
{
intSeq = gdi.GetDataKeyValue("LABOR_IDENT").ToString();
expression = "LABOR_IDENT = '" + intSeq + "'";
}
else
{
intSeq = gdi.GetDataKeyValue("WORK_DT_SEQ").ToString();
expression = "WORK_DT_SEQ = '" + intSeq + "'";
}
e.DetailTableView.DataSource = LoadGridDetail(false, false).Tables["LaborApproval"].Select(expression, "LD_APPROVED_DT asc");
}
}
With this logic, The mastergrid is able to bind to different datakeynames . But in DetailTableDataBind, I am not able to access the datakeynames ( always null).
Do you this this logic will work, or do you suggest to completely build the grid dynamically .
Thank you

Any Ideas, simple way of changing datakeynames to the grid, Please..
Thank you
You don't have to define GridRelationFields when binding the grid programmatically:
http://demos.telerik.com/aspnet-ajax/grid/examples/data-binding/programmatic-hierarchy/defaultcs.aspx
I believe both LABOR_IDENT and WORK_DT_SEQ are fields present in the master table database. Why don't you simply use the following approach?
<
MasterTableView
...
DataKeyNames
=
"LABOR_IDENT,WORK_DT_SEQ"
>
Also, the programmatic declaration of the data key fields should be modified as follows:
rgLEV.MasterTableView.DataKeyNames =
new
string
[] {
"LABOR_IDENT"
,
"LD_STATUS"
};
Another solution you can try is get the required values by accessing the Text of the cells, instead of using GetDataKeyValue() method:
protected
void
RadGrid1_DetailTableDataBind(
object
sender, GridDetailTableDataBindEventArgs e)
{
GridDataItem parentItem = e.DetailTableView.ParentItem
as
GridDataItem;
GridColumn col = parentItem.OwnerTableView.GetColumnSafe(
"ShipName"
);
if
(col !=
null
)
{
TableCell cell = parentItem[col.UniqueName];
string
value = cell.Text;
}
...
}
Please make the suggested modifications and let me know about the result.
Regards,
Eyup
Telerik

Hi Eyup,
Thank you for your suggestions. I have tried with approach one, programmatic declaration of data key fields in page_init, with my RadGrid structure/columns statically declared. But it didn't work, datakeyvalues were not getting assigned to the grid or detailgrid.
protected void Page_Init(object sender, EventArgs e)
{
if (!IsPostBack)
{
if (GetVersion >= 15)
{
rgLEV.MasterTableView.DataKeyNames = new string[] { "LABOR_IDENT", "LD_STATUS" };
rgLEV.MasterTableView.DetailTables[0].DataKeyNames = new string[] { "LABOR_IDENT", "LD_STATUS" };
}
else
{
rgLEV.MasterTableView.DataKeyNames = new string[] { "WORK_DT_SEQ", "LD_STATUS" };
rgLEV.MasterTableView.DetailTables[0].DataKeyNames = new string[] { "WORK_DT_SEQ", "LD_STATUS" };
}
}
}
And I also checked how the grid would display, if I removed the assignment of datakeys from page_init. The grid displayed fine, with datakeyvalues being null. It looks like the Page_Init code, has no effect to the grid.
I thought grid setting EnableViewState=false & EnableColumnViewState=false & AutoGenerateColumns=false and assigning datakeys dynamically in page_init would work. But no luck. Looks like we need to declare the whole grid dynamically.

I have tried another way, created two nondisplay columns for the datakey's in the grid.
<t:GridBoundColumn DataField="LABOR_IDENT" UniqueName="LD" Display="false" HeaderText="" ReadOnly="true" />
<t:GridBoundColumn DataField="WORK_DT_SEQ" UniqueName="WDSeq" Display="false" HeaderText ="" ReadOnly="true" />
And I am accessing them in the detialtable as follows
protected void rgLEV_DetailTableDataBind(object sender, GridDetailTableDataBindEventArgs e)
{
GridDataItem gdi = e.DetailTableView.ParentItem as GridDataItem;
string intSeq;
string expression;
if (e.DetailTableView.Name == "gtvDetail1")
{
if (CommonFunctions.GetAMVersion >= 1520.0)
{
intSeq = gdi["LD"].Text;
expression = "LABOR_IDENT = '" + intSeq + "'";
}
else
{
intSeq = gdi["WDSeq"].Text;
expression = "WORK_DT_SEQ = '" + intSeq + "'";
}
e.DetailTableView.DataSource = xxxx;
}
So far, It works fine, able to get detail grid displayed.
Thank you Eyup.
But is it possible to dynamically assign datakeys to the static grid. If possible, can you share some sample code.
Thank you.
I'm glad you've found out an alternative solution using the provided directions.
As for your initial approach, I suggest that you prepare a very basic runnable web site demonstrating the problematic behavior and open a formal support ticket to send it to us.
Regards,
Eyup
Telerik

Obviously there was no answer within the last 7 years.
Here is a workaround which works fine if you can limit the possible number and names of the primary key columns to 2 or 3.
In my case I have to types of tables, one type with "ID" as PK, the other have a column named "RecordIdentifier" as PK.
I declare both for the gridview:
<MasterTableView Name="MainTable" DataKeyNames="ID, RecordIdentifier" EditMode="InPlace" ...
In NeedDataSource I check if the table has the one or the other PK:
If currentPKName.Text = "ID" Then
sql = "select Null as RecordIdentifier, * from " & currentTable.Text
Else
sql = "select Null as ID, * from " & currentTable.Text
End If
and add the missing column with a Null value to the select.
Thus The gridview always has his expected key columns and I can deal with the two different cases in the code.