How to create separate DetailTable on each row in a RadGrid?

让人想犯罪 __ 提交于 2019-12-25 08:11:20

问题


I have a telerik radgrid where columns and detail tables are declared like:

<telerik:RadGrid>
  <Columns>
    <telerik:GridBoundColumn/>
    <telerik:GridBoundColumn/>
  </Columns>
  <DetailTables>
    <telerik:GridTableView
      <Columns>
        <telerik:GridBoundColumn/>
        <telerik:GridBoundColumn/>
      </Columns>
    </telerik:GridTableView
  </DetailTables>
</telerik:RadGrid>

Which gives a nested grid like this:

Now, what I want is to be able to specify a detail table (those sub tables) per row, programmatically.

(I cannot be sure that the columns for the nested table that comes up when I expand the line fgvbvb will be the same as the columns when expanding the line xcxcv).

I have tried, without luck in the OnDataBound handler of the radgrid (in which I omitted <DetailTables>) to access the data structure for nested tables like this:

    protected void OnRadGridDataBound(object sender, EventArgs e)
    {
        foreach (GridDataItem item in grdActivitiesToCopy.MasterTableView.Items)
        {
            var dg = item.ChildItem.NestedTableViews[0];

        }
    }

This will overindex the array NestedTableViews because it is empty. Also, item.ChildItem.NestedTableViews has no setter.

How do I populate each row with a detail table one by one manually?


回答1:


According to Telerik:

RadGrid does not support mixing declarative grid columns with grid columns added dynamically at runtime. You should either create all the columns in the grid programmatically, or else define them all in the ASPX file. When creating Detail tables, it should be created in the PageInit event.

Creating a Hierarchical Grid Programmatically:

You should follow these basic steps in order to create hierarchical RadGrid programmatically in the code-behind (having a data source control for data content generation):

  1. Create the grid dynamically in the Page_Init handler of the page by calling its constructor.

  2. Specify the preferred settings for your grid instance through its properties.

  3. Create columns for the grid dynamically. Keep in mind that you have to first set their properties and then add them to the MasterTableView/GridTableView collection (discussed in the first paragraph of this same topic). Thus, their ViewState will be properly persisted (as LoadViewState is raised after the Init event of the page).

  4. Set the proper ParentTableRelations for the GridTableViews (along with their MasterKeyField and DetailKeyField attributes) and DataKeyNames for the MasterTableView/GridTableViews in the code-behind of the page.

  5. Assign data sources (through the DataSourceID attribute) for each table in the grid hierarchy.If you do not want to use declarative relations, generate the data in the NeedDataSource/DetailTableDataBind handlers of the grid. On DetailTableDataBind you can determine which data source should be related to the currently bound GridTableView by checking its Name/DataSourceID property. Here, the Name property must have a unique value for each detail table (this value has to be defined previously by the developer) and the DataSourceID is the ID of the DataSource control responsible for the corresponding detail table content generation.

Code Sample:

    RadGrid RadGrid1 = new RadGrid();
    RadGrid1.DataSourceID = "SqlDataSource1";
    RadGrid1.MasterTableView.DataKeyNames = new string[] { "CustomerID" };
    RadGrid1.Skin = "Default";
    RadGrid1.Width = Unit.Percentage(100);
    RadGrid1.PageSize = 15;
    RadGrid1.AllowPaging = true;
    RadGrid1.AutoGenerateColumns = false;
    //Add columns
    GridBoundColumn boundColumn;
    boundColumn = new GridBoundColumn();
    boundColumn.DataField = "CustomerID";
    boundColumn.HeaderText = "CustomerID";
    RadGrid1.MasterTableView.Columns.Add(boundColumn);
    boundColumn = new GridBoundColumn();
    boundColumn.DataField = "ContactName";
    boundColumn.HeaderText = "Contact Name";
    RadGrid1.MasterTableView.Columns.Add(boundColumn);

    //Detail table - Orders (II in hierarchy level)
    GridTableView tableViewOrders = new GridTableView(RadGrid1);
    tableViewOrders.DataSourceID = "SqlDataSource2";
    tableViewOrders.DataKeyNames = new string[] { "OrderID" };
    GridRelationFields relationFields = new GridRelationFields();
    relationFields.MasterKeyField = "CustomerID";
    relationFields.DetailKeyField = "CustomerID";
    tableViewOrders.ParentTableRelation.Add(relationFields);
    RadGrid1.MasterTableView.DetailTables.Add(tableViewOrders);

Please refer to this help article for more details: http://docs.telerik.com/devtools/aspnet-ajax/controls/grid/defining-structure/creating-a-radgrid-programmatically#creating-a-hierarchical-grid-programmatically




回答2:


First of all , because of the life cicle of a asp page. You can't access to a event on a detail table.

If you need to access detail tables , items etc ..
You need to add an method to the PreRender in the MasterTableView like this:

<MasterTableView   DataSourceID="myDataSource"
                   AllowMultiColumnSorting="True" 
                   DataKeyNames="Key1,Key2,KeyN" 
                   HierarchyDefaultExpanded="True"
                   OnPreRender="Unnamed_PreRender" >

The method will recursively iterate through the grid.
The way you do it can change depending on your HieararchyLoadMode.

So this is my way to do it, easiest way exist if you are on Client or Serverbind mode.

Traversing and load mode by the telerik doc .

I'm pretty sure you don't want to :

"populate each row with a detail table one by one manually"

You want to have Multiple table at a Sub Level in your grid and display the rigth one programmatically.

And this is can be done in two easy step:

1/. Create every Detail table in your apsx page.
Please refer to this documentation for more information : Several tables at a level

2/. Handle the display:

protected void Unnamed_PreRender(object sender, EventArgs e)
{
  if (!IsPostBack) myControler(MASTERGRID.MasterTableView);
}

 private void myControler(GridTableView gridTableView)
{
    GridItem[] nestedViewItems = gridTableView.GetItems(GridItemType.NestedView);

    foreach (GridNestedViewItem nestedViewItem in nestedViewItems)
    {
        foreach (GridTableView nestedView in nestedViewItem.NestedTableViews)
        {

            if (nestedView.Name == "mytable12" && nestedView.Items.Count == 0)
            { HideExpandColumn(nestedView, nestedView.ParentItem["ExpandColumn"]); }

            else if (nestedView.Name == "mytable23")
            {
                if (nestedView.Items.Count == 0)// 
                    HideExpandColumn(nestedView, nestedView.ParentItem["ExpandColumn"]);
                else
                { }
            }
            if (nestedView.HasDetailTables)
                { myControler(nestedView); }
        }
    }
}

private void HideExpandColumn(GridTableView _GNVI, TableCell _cell)
{
    if (_cell.Controls.Count > 0)
    {
        _cell.Controls[0].Visible = false;
        _cell.Text = " ";
    }
    _GNVI.Visible = false;
}

You can hide a detail table using :

HideExpandColumn(nestedView, nestedView.ParentItem["ExpandColumn"]);

Or you can hide the parent of the detail table you tested using the detail table that is in param of the controler :

HideExpandColumn(gridTableView, nestedView.ParentItem["ExpandColumn"]);

HideExpandColumn will hide the expand control that stay sometimes even if you hide th detail table.

Bonus: If you need to access to a control in a detail table. You can use this:

public static class ControlExtensions
{
public static Control FindIt(this Control control, string id)
{
    if (control == null) return null;
    Control ctrl = control.FindControl(id);
    if (ctrl == null)
    {
        foreach (Control child in control.Controls)
        {
            ctrl = FindIt(child, id);
            if (ctrl != null) break;
        }
    }
    return ctrl;
}
}

Calling it in your controler like this :

else if (nestedView.Name == "DetailPV")
                {
                    if (nestedView.Items.Count == 0)
                        HideExpandColumn(gridTableView, nestedView.ParentItem["ExpandColumn"]);
                    else
                    {

                        RadLabel ctrl = (RadLabel)this.FindIt("RadLabel11");
                        ctrl.Text += "<b>" + nestedView.Items.Count.ToString() + "</b>";
                    }


来源:https://stackoverflow.com/questions/39102879/how-to-create-separate-detailtable-on-each-row-in-a-radgrid

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!