Question

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();
Was it helpful?

Solution 2

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;
}

OTHER TIPS

There are several ways; first, you can use the hierarchical grid approach, which Telerik natively supports (see this topic and subtopics). Alternatively, you could "flatten" the results you are trying to bind by doing a LINQ statement, and then binding the anonymous result.

var p in permissions
select new
{
    p.PermissionId,
    p.PermissionName,
    RolesList = String.Join(", ", p.Roles.Select(i => i.RoleName))
}

Note this approach is not LINQ friendly, as Join isn't translated to LINQ.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top