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

Radgrid GridTemplateColumn Problems Databinding on Postback

5 Answers 319 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Jon
Top achievements
Rank 1
Jon asked on 06 May 2013, 09:17 PM
Hi guys,

Having an issue databinding with an Edit in Place grid, when one dropdown's values need to update on postback from the SelectedIndexChanged of another.

I'll put in some of the code at the bottom, I can post more if need be.  (This is a client's code base I'm working with, so I've scrubbed contextual info.  Please forgive typos or generic-ness in the code!)

Here's the summary:

I'm using LinqDataSources to populate dropdown1 & dropdown2. Originally they were each GridDropDownColumns, all was great.  Then, I found out a requirement that the second dropdown needs to be filtered by a foreign key in the db based on on the selection of dropdown1.

So, I changed both columns to a GridTemplateColumn, no prob.  I found references to http://www.telerik.com/help/aspnet-ajax/grid-with-combobox.html which discusses the first part.  The binding works fine without any autopostbacks on the dropdown1.

Then I added a SelectedIndexChanged as pasted below - works great, the selected value of dropdown1 is maintained in my private int, and the LinqDataSources gets the correct enumeration back.

However, with the (SelectedValue='<%#Bind("Value2") %>') on dropdown2, when the post back occurs, I get an error:
Databinding methods such as Eval(), XPath(), and Bind() can only be used in the context of a databound control.

I found this (http://www.telerik.com/community/forums/aspnet-ajax/grid/databinding-methods-such-as-eval-xpath-and-bind-can-only-be-used-in-the-context-of-a-databound-control.aspx) and a few others saying the same, but that solution doesn't bind on save.

I've seen a post (I think reference on this forum) to a nested set of dropdowns, but that example was where only the second of the two dropdown values needed to be stored.  Both values here are needed, so I don't believe I can place both dropdowns in the same column & manipulate.

I also tried decoupling the binding. I was able to populate the dropdown2 on the RadGrid1_ItemDataBound, and I could even get the update save bound by using the LinqDataSource's Updating event and hitting the dropdown2 using the RadGrid's EditItems. However, I'm unable to get the dropdown2's value on the LDS's Insert to modify the saved object.  Doesn't feel like the right solution, but it almost worked.  I couldn't figure out how to save/modify my data object on insert & update using the ItemInserted/ItemUpdated events.

Any help would be appreciated!

<telerik:GridTemplateColumn UniqueName="Column1" HeaderText="Insurance">
    <ItemTemplate>
        <asp:Label ID="lblColumn1" runat="server" Text= '<%# ((MyObject)Container.DataItem).Value1 %> '></asp:Label>
    </ItemTemplate>
    <EditItemTemplate>
        <telerik:RadComboBox runat="server" ID="RcbDropdown1" DataTextField="Table1Name" DataValueField="Table1ID" DataSourceID="ldsTable1" NoWrap="True" SelectedValue='<%#Bind("Value1") %>' OnSelectedIndexChanged="RcbDropdown1_SelectedIndexChanged" AutoPostBack="True" OnDataBound="RcbDropdown1_DataBound" >
        </telerik:RadComboBox>
    </EditItemTemplate>
</telerik:GridTemplateColumn>
<telerik:GridTemplateColumn UniqueName="Column2" HeaderText="Insurance Payer">
    <ItemTemplate>
        <asp:Label ID="lblColumn2" runat="server" Text= '<%# ((MyObject)Container.DataItem).Value2 %> '></asp:Label>
    </ItemTemplate>
    <EditItemTemplate>
        <telerik:RadComboBox runat="server" ID="RcbDropdown2" DataTextField="Table2Name" DataValueField="Table2ID" DataSourceID="ldsTable2" SelectedValue='<%#Bind("Value2") %>' OnDataBound="RcbDropdown1_DataBound" OnDataBinding="RcbDropdown1_DataBinding">
        </telerik:RadComboBox>
    </EditItemTemplate>
</telerik:GridTemplateColumn>

private int myvalue1 { get; set; }
 
protected void RcbDropdown1_SelectedIndexChanged(object sender, RadComboBoxSelectedIndexChangedEventArgs e)
{
 
    myvalue1 = Maybe.ToInt32(e.Value);
    var dropdown1 = (RadComboBox)sender;
    var item = (GridEditableItem)rcb.NamingContainer;
    var dropdown2 = (RadComboBox)item.FindControl("RcbDropdown2");
    if (dropdown2 != null)
    {
        dropdown2.DataSourceID = "ldsTable2";
        dropdown2.DataTextField = "Table2Name";
        dropdown2.DataValueField = "Table2ID";
        dropdown2.DataBind();
    }
}
 
protected void ldsTable2_Selecting(object sender, LinqDataSourceSelectEventArgs e)
{
    var results = new List<MySecondObject>();
 
    if (myvalue1.HasValue)
    {
        results = {Repo Call with Enumeration Results filtering by myvalue1}
    }
    e.Result = results;
}

5 Answers, 1 is accepted

Sort by
0
Daniel
Telerik team
answered on 09 May 2013, 06:02 PM
Hello Jon,

Could you please share the declaration of your RadGrid with us? How this control is supposed to bind? Using automatic operations with LinqDataSource? I need to get a better insight of your setup, but I think in some cases where there are custom requirements in place it might be better to go with fully manual crud operations binding directly to the context instead of trying to workaround every bit that doesn't work out-of-the-box.

Best regards,
Daniel
the Telerik team
If you want to get updates on new releases, tips and tricks and sneak peeks at our product labs directly from the developers working on the RadControls for ASP.NET AJAX, subscribe to their blog feed now.
0
Jon
Top achievements
Rank 1
answered on 15 May 2013, 02:46 PM
Hi Daniel - sure, here's the code. Got the okay to share this from my client, so it will probably make a lot more sense what I'm trying. Thanks!

<telerik:RadGrid ID="rgrdAgencyEdiGateways" DataSourceID="ldsAgencyEdiGateways" AllowSorting="True" AllowPaging="True" AllowFilteringByColumn="False" AutoGenerateColumns="False" AllowAutomaticUpdates="True" AllowAutomaticInserts="True" AllowAutomaticDeletes="true" runat="server" Skin="Windows7" OnItemDeleted="rgrdAgencyEdiGateways_ItemDeleted" OnItemInserted="rgrdAgencyEdiGateways_ItemInserted" OnItemUpdated="rgrdAgencyEdiGateways_ItemUpdated" Visible="false" OnItemCommand="rgrdAgencyEdiGateways_ItemCommand"
OnItemDataBound="rgrdAgencyEdiGateways_ItemDataBound" ondatabinding="rgrdAgencyEdiGateways_DataBinding" ondatabound="rgrdAgencyEdiGateways_DataBound" >
    <MasterTableView DataSourceID="ldsAgencyEdiGateways" DataKeyNames="AgencyEDIGatewaysID" CommandItemDisplay="Top" EditMode="InPlace">
        <Columns>
            <telerik:GridEditCommandColumn ButtonType="ImageButton" UniqueName="EditCommandColumn" EditImageUrl="/images/edit16x16.gif" CancelImageUrl="/images/delete16x16.gif" InsertImageUrl="/images/save16x16.png" UpdateImageUrl="/images/save16x16.png" HeaderStyle-CssClass="actions-column" ItemStyle-Width="25" ItemStyle-CssClass="actions-column" FooterStyle-CssClass="actions-column" Resizable="false" Reorderable="false">
            </telerik:GridEditCommandColumn>
            <telerik:GridButtonColumn ConfirmText="Delete this Agency EDI Gateway?" ConfirmDialogType="RadWindow" ConfirmTitle="Delete" ButtonType="ImageButton" CommandName="Delete" Text="Delete" UniqueName="DeleteColumn" ItemStyle-Width="25" ImageUrl="/images/trash16x16.png" Resizable="false" Reorderable="false" HeaderStyle-CssClass="actions-column" ItemStyle-CssClass="actions-column" FooterStyle-CssClass="actions-column">
            </telerik:GridButtonColumn>
            <telerik:GridBoundColumn DataField="AgencyEDIGatewaysID" UniqueName="AgencyEDIGatewaysID" HeaderText="Agency EDI Gateways ID" Visible="false" ReadOnly="true">
            </telerik:GridBoundColumn>
            <telerik:GridDropDownColumn UniqueName="AgencyID" ListTextField="Agency1" ListValueField="AgencyId" DataSourceID="ldsAgencies" HeaderText="Agency" DataField="AgencyId" DropDownControlType="RadComboBox" Visible="false">
            </telerik:GridDropDownColumn>
            <telerik:GridTemplateColumn UniqueName="InsuranceID" HeaderText="Insurance">
                <ItemTemplate>
                    <asp:Label ID="lblInsuranceName" runat="server" Text= '<%# ((AgencyEDIGateway)Container.DataItem).Insurance.Name %> '></asp:Label>
                </ItemTemplate>
                <EditItemTemplate>
                    <telerik:RadComboBox runat="server" ID="RcbInsurance" DataTextField="Name" DataValueField="InsuranceID" DataSourceID="ldsInsurance" NoWrap="True" SelectedValue='<%#Bind("InsuranceID") %>' OnSelectedIndexChanged="RcbInsurance_SelectedIndexChanged" AutoPostBack="True" OnDataBound="RcbInsurance_DataBound" >
                    </telerik:RadComboBox>
                </EditItemTemplate>
            </telerik:GridTemplateColumn>
            <telerik:GridTemplateColumn UniqueName="InsurancePayersID" HeaderText="Insurance Payer">
                <ItemTemplate>
                    <asp:Label ID="lblInsurancePayerName" runat="server" Text= '<%# ((AgencyEDIGateway)Container.DataItem).InsurancePayer != null ? ((AgencyEDIGateway)Container.DataItem).InsurancePayer.InsPayerName : string.Empty %> '></asp:Label>
                </ItemTemplate>
                <EditItemTemplate>
                    <telerik:RadComboBox runat="server" ID="RcbInsurancePayer" DataTextField="InsPayerName" DataValueField="InsurancePayersId" DataSourceID="ldsInsurancePayer" OnDataBound="RcbInsurancePayer_DataBound" OnDataBinding="RcbInsurancePayer_DataBinding">
                    </telerik:RadComboBox>
                </EditItemTemplate>
            </telerik:GridTemplateColumn>
            <telerik:GridDropDownColumn UniqueName="EDIGatewayID" ListTextField="GatewayName" ListValueField="EDIGatewayID" DataSourceID="ldsEdiGateway" HeaderText="EDI Gateway" DataField="EDIGatewayID" DropDownControlType="RadComboBox">
            </telerik:GridDropDownColumn>
            <telerik:GridBoundColumn DataField="SubmitterID" UniqueName="SubmitterID" HeaderText="Submitter ID" ConvertEmptyStringToNull="false">
            </telerik:GridBoundColumn>
            <telerik:GridBoundColumn DataField="SubmitterName" UniqueName="SubmitterName" HeaderText="Submitter Name" ConvertEmptyStringToNull="false">
            </telerik:GridBoundColumn>
            <telerik:GridBoundColumn DataField="SubmitterLogin" UniqueName="SubmitterLogin" HeaderText="Submitter Login" ConvertEmptyStringToNull="false">
            </telerik:GridBoundColumn>
            <telerik:GridBoundColumn DataField="SubmitterPwd" UniqueName="SubmitterPwd" HeaderText="Submitter Pwd" ConvertEmptyStringToNull="false">
            </telerik:GridBoundColumn>
        </Columns>
    </MasterTableView>
    <PagerStyle AlwaysVisible="true" />
</telerik:RadGrid>
<telerik:RadWindowManager ID="RadWindowManager1" runat="server" />
<asp:LinqDataSource ID="ldsAgencyEdiGateways" runat="server" ContextTypeName="IntegritySupport.Domain.Repository.MursysDbDataContext" EnableDelete="True" EnableInsert="True" EnableUpdate="True" EntityTypeName="" OrderBy="SubmitterName" TableName="AgencyEDIGateways" OnSelecting="ldsAgencyEdiGateways_Selecting" onupdating="ldsAgencyEdiGateways_Updating" oninserting="ldsAgencyEdiGateways_Inserting" >
</asp:LinqDataSource>
<asp:LinqDataSource ID="ldsAgencies" runat="server" ContextTypeName="MyProject.Domain.Repository.MyDataContext" EntityTypeName="" OrderBy="Agency1" TableName="Agencies">
</asp:LinqDataSource>
<asp:LinqDataSource ID="ldsInsurance" runat="server" ContextTypeName="MyProject.Domain.Repository.MyDataContext" EntityTypeName="" OrderBy="Name" TableName="Insurances">
</asp:LinqDataSource>
<asp:LinqDataSource ID="ldsInsurancePayer" runat="server" ContextTypeName="MyProject.Domain.Repository.MyDataContext" EntityTypeName="" OrderBy="InsPayerName" TableName="InsurancePayers" onselecting="ldsInsurancePayer_Selecting">
</asp:LinqDataSource>
<asp:LinqDataSource ID="ldsEdiGateway" runat="server" ContextTypeName="MyProject.Domain.Repository.MyDataContext" EntityTypeName="" OrderBy="GatewayName" TableName="EDIGateways">
</asp:LinqDataSource>

And some of the code behind:

protected void rgrdAgencyEdiGateways_ItemDataBound(object sender, Telerik.Web.UI.GridItemEventArgs e)
{
    if (e.Item is GridEditableItem && e.Item.IsInEditMode)
    {
        var item = (GridEditableItem)e.Item;
        var rcbInsurancePayer = (RadComboBox)item["InsurancePayersID"].FindControl("RcbInsurancePayer");
        if (rcbInsurancePayer != null && item.DataItem is AgencyEDIGateway)
        {
            rcbInsurancePayer.SelectedValue = ((AgencyEDIGateway)item.DataItem).InsurancePayersID.ToString();
        }
    }
}
 
protected void RcbInsurance_SelectedIndexChanged(object sender, RadComboBoxSelectedIndexChangedEventArgs e)
{
 
    insuranceId = Maybe.ToInt32(e.Value);
    var rcbInsurance = (RadComboBox)sender;
    var item = (GridEditableItem)rcbInsurance.NamingContainer;
    var rcbInsurancePayer = (RadComboBox)item.FindControl("RcbInsurancePayer");
    if (rcbInsurancePayer != null)
    {
        rcbInsurancePayer.DataSourceID = "ldsInsurancePayer";
        rcbInsurancePayer.DataTextField = "InsPayerName";
        rcbInsurancePayer.DataValueField = "InsurancePayersId";
        rcbInsurancePayer.DataBind();
    }
}
 
 
protected void ldsInsurancePayer_Selecting(object sender, LinqDataSourceSelectEventArgs e)
{
    var results = new List<InsurancePayer>();
 
    if (insuranceId.HasValue)
    {
        results = AgencyEdiGatewayRepositoryInstance.GetInsurancePayersByInsuranceId(insuranceId.Value).ToList();
    }
    e.Result = results;
}
 
 
protected void ldsAgencyEdiGateways_Updating(object sender, LinqDataSourceUpdateEventArgs e)
{
    ((AgencyEDIGateway)e.NewObject).InsurancePayersID = GetInsurancePayerId();
}
 
private long? GetInsurancePayerId()
{
    foreach (GridDataItem item in rgrdAgencyEdiGateways.EditItems)
    {
        var rcbInsurancePayer = item.FindControl("RcbInsurancePayer") as RadComboBox;
        if (rcbInsurancePayer != null)
        {
            return Maybe.ToInt64(rcbInsurancePayer.SelectedValue);
        }
    }
    return null;
}
0
Jon
Top achievements
Rank 1
answered on 28 May 2013, 05:24 PM
Heard from support, turns out I had to not use the Automatic Inserts/updates/deletes from the LinqDataSource.  I found an example and followed, and ended up with the following code, which works. 

I still don't link having to scrape the EditItems in the update mode but it's ok. What I really don't like is having to set an AutoPostBack on my second dropdown to set a session variable, just to be able to get the value in my InsertCommand.  I'm not able to find anything like and "InsertItems" equivalent to "EditItems" or something simple to access that data.
If anyone can tell me that last bit, it'd be appreciated.

private int? insuranceId
{
    get
    {
        return Maybe.ToInt32(Session["EdiInsuranceId"]);
    }
    set
    {
        Session["EdiInsuranceId"] = value.ToString();
    }
}
 
private int? insurancePayerId
{
    get
    {
        return Maybe.ToInt32(Session["EdiInsurancePayerId"]);
    }
    set
    {
        Session["EdiInsurancePayerId"] = value.ToString();
    }
}
 
protected void RcbInsurance_DataBound(object sender, EventArgs e)
{
    var cbox = ((RadComboBox)sender);
    insuranceId = Maybe.ToInt32(cbox.SelectedValue);
}
 
protected void RcbInsurance_SelectedIndexChanged(object sender, RadComboBoxSelectedIndexChangedEventArgs e)
{
    insuranceId = Maybe.ToInt32(e.Value);
    var rcbInsurance = (RadComboBox)sender;
    var item = (GridEditableItem)rcbInsurance.NamingContainer;
    var rcbInsurancePayer = (RadComboBox)item.FindControl("RcbInsurancePayer");
    if (rcbInsurancePayer != null)
    {
        rcbInsurancePayer.DataSourceID = "ldsInsurancePayer";
        rcbInsurancePayer.DataTextField = "InsPayerName";
        rcbInsurancePayer.DataValueField = "InsurancePayersId";
        rcbInsurancePayer.DataBind();
    }
}
 
protected void RcbInsurancePayer_DataBinding(object sender, EventArgs e)
{
    var rcbInsurancePayer = ((RadComboBox)sender);
    rcbInsurancePayer.DataTextField = "InsPayerName";
    rcbInsurancePayer.DataValueField = "InsurancePayersId";
    rcbInsurancePayer.DataSourceID = "ldsInsurancePayer";
}
 
protected void RcbInsurancePayer_DataBound(object sender, EventArgs e)
{
    var rcbInsurancePayer = ((RadComboBox)sender);
    rcbInsurancePayer.Items.Insert(0, new RadComboBoxItem("", ""));
 
    insurancePayerId = Maybe.ToInt32(rcbInsurancePayer.SelectedValue);
}
 
protected void RcbInsurancePayer_SelectedIndexChanged(object sender, RadComboBoxSelectedIndexChangedEventArgs e)
{
    insurancePayerId = Maybe.ToInt32(e.Value);
}
 
 
protected void rgrdAgencyEdiGateways_UpdateCommand(object sender, GridCommandEventArgs e)
{
    var item = e.Item as GridEditableItem;
    if (item == null)
    {
        return;
    }
    var agencyEdiGatewaysId = Maybe.ToInt64(item.GetDataKeyValue("AgencyEDIGatewaysID").ToString());
    if (!agencyEdiGatewaysId.HasValue || !AgencyId.HasValue)
    {
        return;
    }
    var agencyEdiGateway = AgencyEdiGatewayRepositoryInstance.GetAgencyEdiGatewayById(agencyEdiGatewaysId.Value);
    item.UpdateValues(agencyEdiGateway);
    agencyEdiGateway.AgencyID = AgencyId.Value;
    agencyEdiGateway.InsurancePayersID = GetInsurancePayerIdInUpdateMode();
    AgencyEdiGatewayRepositoryInstance.SaveAgencyEdiGateway(agencyEdiGateway);
}
 
protected void rgrdAgencyEdiGateways_InsertCommand(object sender, GridCommandEventArgs e)
{
    try
    {
        var item = e.Item as GridEditableItem;
        if (item == null || !AgencyId.HasValue)
        {
            return;
        }
        var values = new Hashtable();
        item.ExtractValues(values);
        var agencyEdiGateway = new AgencyEDIGateway();
        item.UpdateValues(agencyEdiGateway);
        agencyEdiGateway.AgencyID = AgencyId.Value;
        agencyEdiGateway.InsurancePayersID = insurancePayerId;
        AgencyEdiGatewayRepositoryInstance.SaveAgencyEdiGateway(agencyEdiGateway);
    }
    catch (Exception ex)
    {
        SetMessage("agencyEdiGateway cannot be inserted. Reason: " + ex.InnerException.Message);
    }
}
 
protected void rgrdAgencyEdiGateways_DeleteCommand(object sender, GridCommandEventArgs e)
{
    try
    {
        var item = e.Item as GridEditableItem;
        if (item == null)
        {
            return;
        }
        var agencyEdiGatewaysId = Maybe.ToInt64(item.GetDataKeyValue("AgencyEDIGatewaysID").ToString());
        if (!agencyEdiGatewaysId.HasValue)
        {
            return;
        }
        AgencyEdiGatewayRepositoryInstance.DeleteAgencyEdiGateway(agencyEdiGatewaysId.Value);
    }
    catch (Exception ex)
    {
        SetMessage("agencyEdiGateway not deleted. Reason: " + ex.InnerException.Message);
    }
}
 
 
private long? GetInsurancePayerIdInUpdateMode()
{
    foreach (GridDataItem item in rgrdAgencyEdiGateways.EditItems)
    {
        var rcbInsurancePayer = item.FindControl("RcbInsurancePayer") as RadComboBox;
        if (rcbInsurancePayer != null)
        {
            return Maybe.ToInt64(rcbInsurancePayer.SelectedValue);
        }
    }
    return null;
}
0
Daniel
Telerik team
answered on 29 May 2013, 06:37 AM
Hello Joe,

There is a GetInsertItem method on the GridTableView object. You can use it like this:
var insertItem = RadGrid1.MasterTableView.GetInsertItem();

Best regards,
Daniel
Telerik
If you want to get updates on new releases, tips and tricks and sneak peeks at our product labs directly from the developers working on the RadControls for ASP.NET AJAX, subscribe to their blog feed now.
0
Jon
Top achievements
Rank 1
answered on 29 May 2013, 01:53 PM
That's what I was looking for, thanks! Pulled out the 2nd dropdown value in the same way as update, extracting from the dropdown in the insertItem controls.

Pasting my final code update for these methods.

protected void rgrdAgencyEdiGateways_UpdateCommand(object sender, GridCommandEventArgs e)
{
    // Get the Editable Item and verify
    var item = e.Item as GridEditableItem;
    if (item == null)
    {
        return;
    }
 
    // Verify the item's primary key
    var agencyEdiGatewaysId = Maybe.ToInt64(item.GetDataKeyValue("AgencyEDIGatewaysID").ToString());
    if (!agencyEdiGatewaysId.HasValue || !AgencyId.HasValue)
    {
        return;
    }
 
    // Get the original item from the repo
    var agencyEdiGateway = AgencyEdiGatewayRepositoryInstance.GetAgencyEdiGatewayById(agencyEdiGatewaysId.Value);
 
    // Update the item and save
    item.UpdateValues(agencyEdiGateway);
    agencyEdiGateway.AgencyID = AgencyId.Value;
    agencyEdiGateway.InsurancePayersID = GetInsurancePayerIdInUpdateMode();
    AgencyEdiGatewayRepositoryInstance.SaveAgencyEdiGateway(agencyEdiGateway);
}
 
protected void rgrdAgencyEdiGateways_InsertCommand(object sender, GridCommandEventArgs e)
{
    try
    {
        // Get the inserted item & extract values
        var insertItem = rgrdAgencyEdiGateways.MasterTableView.GetInsertItem();
        if (insertItem == null || !AgencyId.HasValue)
        {
            return;
        }
        var values = new Hashtable();
        insertItem.ExtractValues(values);
 
        //Create a new EdiGateway & update from the inserted item
        var agencyEdiGateway = new AgencyEDIGateway();
        insertItem.UpdateValues(agencyEdiGateway);
 
        // Use the current selected agencyId
        agencyEdiGateway.AgencyID = AgencyId.Value;
 
        // Extract the InsurancePayerId from the insertItems' controls since this dropdown isn't bound.
        var comboBox = (RadComboBox)insertItem.FindControl("RcbInsurancePayer");
        agencyEdiGateway.InsurancePayersID = Maybe.ToInt64(comboBox.SelectedValue);
 
        // Save the item
        AgencyEdiGatewayRepositoryInstance.SaveAgencyEdiGateway(agencyEdiGateway);
    }
    catch (Exception ex)
    {
        SetMessage("agencyEdiGateway cannot be inserted. Reason: " + ex.InnerException.Message);
    }
}
Tags
Grid
Asked by
Jon
Top achievements
Rank 1
Answers by
Daniel
Telerik team
Jon
Top achievements
Rank 1
Share this question
or