This is a migrated thread and some comments may be shown as answers.

Unable to add/edit child elements in Self Referencing Hierarchy

5 Answers 163 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Chris
Top achievements
Rank 1
Chris asked on 02 Oct 2009, 04:29 PM
Hey everyone, I have a self referencing hierarchy and I am unable to configure it properly to allow editing or adding records to child nodes. If it is a top level parent both functions work perfecting. However, clicking on either the add or edit command links causes the entire child node to close and disappear. Clicking refresh on another node (but not the master table) cause the rows to reappear, including the edit/add row, but the content of those rows are empty.

I came across this post and followed it's instructions to no avail. It does not seem correct for self referencing hierarchies anyways. The relevant code from my project is below. Thanks in advance!

<telerik:RadAjaxManager ID="RadAjaxManager1" runat="server"
    <AjaxSettings> 
        <telerik:AjaxSetting AjaxControlID="TaxonomiesRadGrid"
            <UpdatedControls> 
                <telerik:AjaxUpdatedControl ControlID="TaxonomiesRadGrid" /> 
            </UpdatedControls> 
        </telerik:AjaxSetting> 
    </AjaxSettings> 
</telerik:RadAjaxManager> 
<telerik:RadGrid runat="server" ID="TaxonomiesRadGrid" AllowMultiRowSelection="true" 
    Skin="WebBlue" AutoGenerateColumns="false" Width="90%" GridLines="None" MasterTableView-DataSourceID="TaxonomiesRGSqlDataSource" 
    MasterTableView-DataKeyNames="taxonomyItemId, taxonomyParentId" MasterTableView-GroupsDefaultExpanded="true" 
    MasterTableView-GridLines="None" MasterTableView-GroupLoadMode="Client" MasterTableView-FilterExpression="taxonomyParentId IS NULL" 
    ClientSettings-AllowGroupExpandCollapse="true" OnItemDataBound="TaxonomiesRadGrid_ItemDataBound" 
    MasterTableView-SelfHierarchySettings-MaximumDepth="100" AllowAutomaticDeletes="true" 
    AllowAutomaticInserts="true" AllowAutomaticUpdates="true" OnItemUpdated="TaxonomiesRadGrid_ItemUpdated" 
    OnItemInserted="TaxonomiesRadGrid_ItemInserted" OnItemCreated="TaxonomiesRadGrid_ItemCreated" 
    OnInsertCommand="TaxonomiesRadGrid_InsertCommand" OnUpdateCommand="TaxonomiesRadGrid_UpdateCommand" 
    ShowStatusBar="true" OnDataBound="TaxonomiesRadGrid_DataBound" OnItemCommand="TaxonomiesRadGrid_ItemCommand"
    <MasterTableView HierarchyDefaultExpanded="false" HierarchyLoadMode="Client" CommandItemDisplay="Top" 
        CommandItemSettings-AddNewRecordText="Add a new Taxonomy Parent" EditMode="InPlace" 
        NoMasterRecordsText="No taxonomy items to display. Please select a taxonomy framework from above."
        <SelfHierarchySettings ParentKeyName="taxonomyParentId" KeyName="taxonomyItemId" /> 
        <Columns> 
            <telerik:GridBoundColumn DataField="taxonomyText" DataType="System.String" HeaderText="Taxonomy Description" 
                SortExpression="taxonomyText" UniqueName="taxonomyText"
            </telerik:GridBoundColumn> 
            <telerik:GridEditCommandColumn ButtonType="PushButton" ItemStyle-Width="120px" ItemStyle-HorizontalAlign="Right"
            </telerik:GridEditCommandColumn> 
            <telerik:GridClientDeleteColumn ButtonType="PushButton" ItemStyle-Width="50px" ItemStyle-BorderWidth="0px" 
                ItemStyle-HorizontalAlign="Center" ConfirmText="Are you sure you want to delete this taxonomy item and any items beneath it?"
            </telerik:GridClientDeleteColumn> 
        </Columns> 
    </MasterTableView> 
</telerik:RadGrid> 
<asp:SqlDataSource ID="TaxonomiesRGSqlDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:PrimarySQLConn %>" 
    SelectCommand="GetTaxonomyDetails" SelectCommandType="StoredProcedure" InsertCommand="InsertTaxonomyItem" 
    InsertCommandType="StoredProcedure" UpdateCommand="UpdateTaxonomyItem" UpdateCommandType="StoredProcedure" 
    OnUpdating="OnUpdating"></asp:SqlDataSource> 

Code behind:
private Hashtable _expandedState; 
private Hashtable _selectedState; 
 
protected void Page_Load(object sender, EventArgs e) 
    if (!IsPostBack) 
    { 
        //reset expanded states 
        this._expandedState = null
        this.Session["_ordersExpandedState"] = null
    } 
 
public void Page_PreRenderComplete(object sender, EventArgs e) 
    HideExpandColumnRecursive(TaxonomiesRadGrid.MasterTableView); 
#region Click & Command Events 
 
protected void ShowTaxonomyDetailsButton_Click(object sender, EventArgs e) 
    TaxonomiesRGSqlDataSource.SelectParameters.Clear(); 
    TaxonomiesRGSqlDataSource.SelectParameters.Add("id", TaxonomiesListBox.SelectedValue.ToString()); 
    TaxonomiesRadGrid.DataBind(); 
#endregion 
#region Grid Message 
 
private string gridMessage = null
 
private void SetMessage(string message) 
    gridMessage = message; 
 
protected void RadGrid1_DataBound(object sender, EventArgs e) 
    if (!string.IsNullOrEmpty(gridMessage)) 
    { 
        DisplayMessage(gridMessage); 
    } 
 
private void DisplayMessage(string text) 
    TaxonomiesRadGrid.Controls.Add(new LiteralControl(string.Format("<span style='color:red'>{0}</span>", text))); 
#endregion 
#region TaxonomiesRadGrid Events 
 
protected void TaxonomiesRadGrid_ItemInserted(object source, GridInsertedEventArgs e) 
    if (e.Exception != null
    { 
        e.ExceptionHandled = true
        DisplayMessage(" Taxonomy item cannot be inserted. Reason: " + e.Exception.Message); 
    } 
    else 
    { 
        DisplayMessage(" Taxonomy item inserted"); 
    } 
 
protected void TaxonomiesRadGrid_ItemUpdated(object source, Telerik.Web.UI.GridUpdatedEventArgs e) 
    if (e.Exception != null
    { 
        e.KeepInEditMode = false
        e.ExceptionHandled = true
        DisplayMessage(" Taxonomy item cannot be updated. Reason: " + e.Exception.Message); 
    } 
    else 
    { 
        DisplayMessage(" Taxonomy item updated"); 
    } 
 
protected void TaxonomiesRadGrid_ItemCreated(object sender, GridItemEventArgs e) 
    if (e.Item is GridHeaderItem && e.Item.OwnerTableView != TaxonomiesRadGrid.MasterTableView) 
    { 
        e.Item.Style["display"] = "none"
    } 
    else if (e.Item is GridCommandItem && e.Item.OwnerTableView != TaxonomiesRadGrid.MasterTableView) 
    { 
        ((Button)e.Item.Cells[0].FindControl("AddNewRecordButton")).Visible = false
        ((Button)e.Item.Cells[0].FindControl("RefreshButton")).Visible = false
 
        ((LinkButton)e.Item.Cells[0].FindControl("InitInsertButton")).Text = "Add a new taxonomy item to this parent"
    } 
    else if (e.Item is GridCommandItem && e.Item.OwnerTableView == TaxonomiesRadGrid.MasterTableView) 
    { 
        ((Button)e.Item.Cells[0].FindControl("AddNewRecordButton")).Visible = false
        ((Button)e.Item.Cells[0].FindControl("RefreshButton")).Visible = false
    } 
 
protected void TaxonomiesRadGrid_InsertCommand(object source, GridCommandEventArgs e) 
    if (e.Item.OwnerTableView == TaxonomiesRadGrid.MasterTableView) 
    { 
        GridDataItem parentItem = (GridDataItem)e.Item.OwnerTableView.ParentItem; 
        TaxonomiesRGSqlDataSource.InsertParameters.Clear(); 
        TaxonomiesRGSqlDataSource.InsertParameters.Add("taxonomyId", TaxonomiesListBox.SelectedValue.ToString()); 
        TaxonomiesRGSqlDataSource.InsertParameters.Add("parentId", DBNull.Value.ToString()); 
    } 
    else 
    { 
        GridDataItem parentItem = (GridDataItem)e.Item.OwnerTableView.ParentItem; 
        TaxonomiesRGSqlDataSource.InsertParameters.Clear(); 
        TaxonomiesRGSqlDataSource.InsertParameters.Add("taxonomyId", TaxonomiesListBox.SelectedValue.ToString()); 
        TaxonomiesRGSqlDataSource.InsertParameters.Add("parentId", parentItem.OwnerTableView.DataKeyValues[parentItem.ItemIndex]["taxonomyParentId"].ToString()); 
    } 
 
protected void TaxonomiesRadGrid_UpdateCommand(object source, GridCommandEventArgs e) 
    //GridEditableItem editedItem = e.Item as GridEditableItem; 
    //TaxonomiesRGSqlDataSource.UpdateParameters.Clear(); 
    //TaxonomiesRGSqlDataSource.UpdateParameters.Add("taxonomyItemId", editedItem.OwnerTableView.DataKeyValues[editedItem.ItemIndex]["taxonomyItemId"].ToString()); 
    //TaxonomiesRGSqlDataSource.UpdateParameters.Add("taxonomyText", "test"); 
#endregion 
 
public void HideExpandColumnRecursive(GridTableView tableView) 
    GridItem[] nestedViewItems = tableView.GetItems(GridItemType.NestedView); 
    foreach (GridNestedViewItem nestedViewItem in nestedViewItems) 
    { 
        foreach (GridTableView nestedView in nestedViewItem.NestedTableViews) 
        { 
            nestedView.Style["border"] = "0"
            Button MyExpandCollapseButton = (Button)nestedView.ParentItem.FindControl("ctl00"); 
            if (nestedView.Items.Count == 0) 
            { 
                if (MyExpandCollapseButton != null
                { 
                    MyExpandCollapseButton.Style["visibility"] = "hidden"
                } 
                nestedViewItem.Visible = false
            } 
            else 
            { 
                if (MyExpandCollapseButton != null
                { 
                    MyExpandCollapseButton.Style.Remove("visibility"); 
                } 
            } 
            if (nestedView.HasDetailTables) 
            { 
                HideExpandColumnRecursive(nestedView); 
            } 
        } 
    } 
#region Diagnostics 
 
protected void OnUpdating(object sender, EventArgs e) 
    EventArgs er = e; 
#endregion 
#region Child Editing 
 
//Save/load expanded states Hash from the session 
//this can also be implemented in the ViewState 
private Hashtable ExpandedStates 
    get 
    { 
        if (this._expandedState == null
        { 
            _expandedState = this.Session["_expandedState"as Hashtable; 
            if (_expandedState == null
            { 
                _expandedState = new Hashtable(); 
                this.Session["_expandedState"] = _expandedState; 
            } 
        } 
 
        return this._expandedState; 
    } 
 
//Clear the state for all expanded children if a parent item is collapsed 
private void ClearExpandedChildren(string parentHierarchicalIndex) 
    string[] indexes = new string[this.ExpandedStates.Keys.Count]; 
    this.ExpandedStates.Keys.CopyTo(indexes, 0); 
    foreach (string index in indexes) 
    { 
        //all indexes of child items 
        if (index.StartsWith(parentHierarchicalIndex + "_") || 
            index.StartsWith(parentHierarchicalIndex + ":")) 
        { 
            this.ExpandedStates.Remove(index); 
        } 
    } 
 
//Save/load selected states Hash from the session 
//this can also be implemented in the ViewState 
private Hashtable SelectedStates 
    get 
    { 
        if (this._selectedState == null
        { 
            _selectedState = this.Session["_selectedState"as Hashtable; 
            if (_selectedState == null
            { 
                _selectedState = new Hashtable(); 
                this.Session["_selectedState"] = _selectedState; 
            } 
        } 
 
        return this._selectedState; 
    } 
 
protected void TaxonomiesRadGrid_ItemCommand(object source, GridCommandEventArgs e) 
    //save the expanded/selected state in the session 
    if (e.CommandName == RadGrid.ExpandCollapseCommandName) 
    { 
        //Is the item about to be expanded or collapsed 
        if (!e.Item.Expanded) 
        { 
            //Save its unique index among all the items in the hierarchy 
            this.ExpandedStates[e.Item.ItemIndexHierarchical] = true
        } 
        else //collapsed 
        { 
            this.ExpandedStates.Remove(e.Item.ItemIndexHierarchical); 
            this.ClearExpandedChildren(e.Item.ItemIndexHierarchical); 
        } 
    } 
    //Is the item about to be selected  
    else if (e.CommandName == RadGrid.SelectCommandName) 
    { 
        //Save its unique index among all the items in the hierarchy 
        this.SelectedStates[e.Item.ItemIndexHierarchical] = true
    } 
    //Is the item about to be deselected  
    else if (e.CommandName == RadGrid.DeselectCommandName) 
    { 
        this.SelectedStates.Remove(e.Item.ItemIndexHierarchical); 
    } 
 
protected void TaxonomiesRadGrid_DataBound(object sender, EventArgs e) 
    //Expand all items using our custom storage 
    string[] indexes = new string[this.ExpandedStates.Keys.Count]; 
    this.ExpandedStates.Keys.CopyTo(indexes, 0); 
 
    ArrayList arr = new ArrayList(indexes); 
    //Sort so we can guarantee that a parent item is expanded before any of  
    //its children 
    arr.Sort(); 
 
    foreach (string key in arr) 
    { 
        bool value = (bool)this.ExpandedStates[key]; 
        if (value) 
        { 
            TaxonomiesRadGrid.Items[key].Expanded = true
        } 
    } 
 
    //Select all items using our custom storage 
    indexes = new string[this.SelectedStates.Keys.Count]; 
    this.SelectedStates.Keys.CopyTo(indexes, 0); 
 
    arr = new ArrayList(indexes); 
    //Sort to ensure that a parent item is selected before any of its children 
    arr.Sort(); 
 
    foreach (string key in arr) 
    { 
        bool value = (bool)this.SelectedStates[key]; 
        if (value) 
        { 
            TaxonomiesRadGrid.Items[key].Selected = true
        } 
    } 
 
protected void grdRebind_Click(object sender, EventArgs e) 
    TaxonomiesRadGrid.Rebind(); 
#endregion 


5 Answers, 1 is accepted

Sort by
0
Chris
Top achievements
Rank 1
answered on 05 Oct 2009, 03:33 PM
Anyone have any suggestions? Thanks!
0
Chris
Top achievements
Rank 1
answered on 06 Oct 2009, 08:15 PM
Bump... C'mon Telerik, this seems to be a bug. If it isn't, your documentation is sorely lacking. Please respond with an update. We have many developers who use Telerik here at the Federal Government....
0
Iana Tsolova
Telerik team
answered on 07 Oct 2009, 08:02 AM
Hello Chris,

I am afraid it is a known issue that automatic CRUD operations are not working with self-referencing grid. However, I am attaching a sample project how you could implement manually update, insert and delete operations.

I hope this helps.

Sincerely yours,
Iana
the Telerik team

Instantly find answers to your questions on the new Telerik Support Portal.
Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
0
David Limoges
Top achievements
Rank 1
answered on 07 Jun 2010, 11:10 PM
Hello Iana,

I know this is a rather old post, but I was wondering if you could answer a question on it.  Your example works great except for one small exception in my situation.

In my Database, I have Null values in my parent ID field if it is the root level.  In you example, you have "ParentID = 0" in the filterExpression property.  Once I change the link to my database and set the property to "ParentID IS NULL", i get an error that says "Expression of Type Boolean is Expected".

I have done some playing around with this an find that I can have it set to ParentID is Null if i have the AutoEventWireUP="false".  However, when the autoeventwireup is false, the Grid does not display as a Hierarchy.

Any suggestions for a fix?

Thanks,
0
Iana Tsolova
Telerik team
answered on 08 Jun 2010, 03:56 PM
Hello David,

Try setting the RadGrid EnableLinqExpressions property to false and see if the error persists.
Another option is to modify the FilterExpression as below:

RadGrid1.MasterTableView.FilterExpression = @"it[""ParentID""] = Convert.DBNull";

Additionally, you can refer to this article for more information on RadGrid FilterExpressions.

I hope this helps.

Sincerely yours,
Iana
the Telerik team

Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
Tags
Grid
Asked by
Chris
Top achievements
Rank 1
Answers by
Chris
Top achievements
Rank 1
Iana Tsolova
Telerik team
David Limoges
Top achievements
Rank 1
Share this question
or