I have a RadGrid with an unknown number of columns I would like to create. Actually I know the first column, which has a DataField of PermissionName
. I have a CSLA data source which returns a list of PermissionInfo
objects, each of which contains a list of RoleInfo
objects. How can I dynamically create a column in the RadGrid for each RoleInfo object when the PermissionInfo objects have varying numbers of RoleInfo
objects?
If any PermissionInfo object contains a specific RoleInfo object, I want to create a column with RoleInfo.RoleName as the header and True as the DataValue. If the RoleInfo
object is not present, then I would like to have the DataValue = false for that row and column.
Here is my RadGrid:
<telerik:RadGrid ID="rgPermissions" AllowPaging="false" AllowSorting="true" AutoGenerateColumns="false"
DataSourceID="dsPermissions" runat="server">
<MasterTableView DataKeyNames="PermissionId" DataSourceID="dsPermissions" EditMode="InPlace">
<Columns>
<telerik:GridBoundColumn DataField="PermissionName" HeaderText="Permission" ></telerik:GridBoundColumn>
</Columns>
</MasterTableView>
</telerik:RadGrid>
<csla:CslaDataSource ID="dsPermissions" runat="server" OnSelectObject="dsPermissions_SelectObject">
</csla:CslaDataSource>
Here are the properties in PermissionInfo
public int PermissionId { get; set; }
public string PermissionName { get; set; }
public RoleInfoList Roles { get; set; }
Here are the properties in RoleInfo
:
public int RoleId { get; set; }
public string RoleName { get; set; }
public string Title { get; set; }
In my page_load
method, I have also written a Factory Method to retrieve all Roles:
RoleInfoList roles = RoleInfoList.GetRoleList();
Here is what I ended up doing: I ended up ditching the CSLA data source and simply binding a DataTable instead. I removed the static GridBoundColumn from my RadGrid as it was creating an extra column, and calling the OnNeedDataSource event:
<telerik:RadGrid ID="rgPermissions" AllowPaging="false" AllowSorting="true" OnNeedDataSource="rgPermissions_NeedDataSource"
runat="server">
<MasterTableView DataKeyNames="Permission Name" AutoGenerateColumns="true" EditMode="InPlace">
<Columns>
<telerik:GridEditCommandColumn />
</Columns>
</MasterTableView>
</telerik:RadGrid>
Then I filled out my event handler, creating the DataTable using the CSLA factory methods:
protected void rgPermissions_NeedDataSource(object sender, Telerik.Web.UI.GridNeedDataSourceEventArgs e)
{
// Data Access
PermissionInfoList permissions = PermissionInfoList.GetPermissionInfoList();
RoleInfoList roles = RoleInfoList.GetRoleList();
// create datatable for permissions
DataTable permissionTable = CreatePermissionDataTable(roles);
foreach (PermissionInfo permission in permissions)
{
// Add permission name
DataRow dataRow = permissionTable.NewRow();
dataRow["Permission Name"] = permission.PermissionName;
AddRow(permission, permissionTable, dataRow, roles);
}
rgPermissions.DataSource = permissionTable;
}
I created a DataTable for Permission data:
private DataTable CreatePermissionDataTable(RoleInfoList roles)
{
DataTable permissions = new DataTable();
permissions.Columns.Add("Permission Name", typeof(string));
permissions.Columns["Permission Name"].ReadOnly = true;
foreach (RoleInfo role in roles)
{
permissions.Columns.Add(role.Title, typeof(Boolean));
}
return permissions;
}
and I did use LINQ to sift out the permissions from the role data:
private DataTable AddRow(PermissionInfo permission, DataTable permissions, DataRow dataRow, RoleInfoList roles)
{
// Add roles
foreach (RoleInfo role in roles)
{
dataRow[role.Title] = permission.Roles.Any(r => r.RoleId == role.RoleId);
}
permissions.Rows.Add(dataRow);
return permissions;
}