FindControl inside RadGrid (Gridview) Edit and Insert views

28,469

Solution 1

It looks that GridView.FindControl inside validate event never works, how ever you can access string that needs to be validated like this:

This is how you validate target control value:

    protected void cvAccountNumber_ServerValidate(object source, ServerValidateEventArgs args)
    {
        string textToBeValidated = args.Value;
    }

And here is how you can access actual controls. GridView.FindControl will end up with nothing when using inside ServerValidate context, so you have to look inside edited/inserted row.

    protected void cvAccountNumber_ServerValidate(object source, ServerValidateEventArgs args)
    {
        //find your editing row...
        GridViewRow editedRow = RadGrid1.Rows[RadGrid1.EditIndex];
        //now serch row for your control...
        TextBox txtAccountNumber = (TextBox)editedRow.FindControl("txtAccountNumber");
        TextBox txtId = (TextBox)editedRow.FindControl("txtId");
    }

Solution 2

First of all your code is prone to SQL injection, but it's not your initial question.

You cannot loop through GridDataItems to find duplicate. You won't be able to find it if you later paginate your grid.

At first, you can use InsertCommand and UpdateCommand events of RadGrid for simplicity. Then check the duplicate using ADO.Net or whatever method you prefer.

protected void RadGrid1_InsertCommand(object source, GridCommandEventArgs e)
{
   try
   {
      var gridEditFormItem = (GridEditFormItem) e.Item;

      var txtAccountNumber = (TextBox)gridEditFormItem.FindControl("txtAccountNumber"); 
      var cbActive = (CheckBox)gridEditFormItem.FindControl("cbActive"); 

      // TODO: Check duplicate against database

      string SqlStr = "INSERT INTO [LBX_Portal_AccountNumbers] ([AccountNumber], [Site], [Active])" + 
        " VALUES ('" + txtAccountNumber.Text + "'" + ", '" + SiteName + "'" + ", '" + isActive + "')"; 

      SqlDataSource1.InsertCommand = SqlStr; 
      SqlDataSource1.Insert(); 

   }
   catch (Exception ex)
   {
      // Log Error
   }
}

protected void RadGrid1_UpdateCommand(object source, GridCommandEventArgs e)
{
   try
   {
      var gridEditFormItem = (GridEditFormItem) e.Item;

      int id = Convert.ToInt32(e.Item.OwnerTableView.DataKeyValues[e.Item.ItemIndex]["ID"]);
      var txtAccountNumber = (TextBox)gridEditFormItem.FindControl("txtAccountNumber"); 
      var cbActive = (CheckBox)gridEditFormItem.FindControl("cbActive"); 

      // TODO: Check duplicate against database

      string SqlStr = "UPDATE [LBX_Portal_AccountNumbers] SET [AccountNumber] = '" + txtAccountNumber.Text + 
         "', [Active] = '" + isActive + "'  WHERE [ID] = " + lblID.Text; 

      SqlDataSource1.UpdateCommand = SqlStr; 
      SqlDataSource1.Update(); 

   }
   catch (Exception ex)
   {
      // Log Error
   }
}
Share:
28,469
the sandman
Author by

the sandman

Updated on October 13, 2020

Comments

  • the sandman
    the sandman over 3 years

    I have a RadGrid (Gridview) that has the option to edit and insert new items.

    Within both those options i have a customvalidator to check for existing values so duplicates cannot be entered. What i am stuck on is the ability to use findcontrol for the textbox that only is shown during EDIT and INSERT.

    This works great for INSERT as i call GetInsertItem(), but that throws an error when editing and i am stuck on that. I want to do this outside of the databound and command methods.

    protected void cvAccountNumber_ServerValidate(object source, ServerValidateEventArgs args)
    {
        TextBox txtAccountNumber = (TextBox)RadGrid1.MasterTableView.GetInsertItem().FindControl("txtAccountNumber");
    
        List<GridDataItem> Items = (from item in RadGrid1.Items.Cast<GridDataItem>()
                                    where item["AccountNumberView"].Text == txtAccountNumber.Text
                                    select item).ToList();
    
        args.IsValid = Items.Count() == 0;
    }
    

    Here is an image of the edit screen. enter image description here

    ASPX:

    Sort By Status: <asp:DropDownList ID="dd_Status" runat="server" Width="150px" 
        onselectedindexchanged="dd_Status_SelectedIndexChanged" 
        AutoPostBack="True">
        <asp:ListItem Text="All" Value="0" Selected="True"></asp:ListItem>
        <asp:ListItem Text="Active" Value="True"></asp:ListItem>
        <asp:ListItem Text="Inactive" Value="False"></asp:ListItem>
    </asp:DropDownList>
    
    <br /><br />
    
    <telerik:RadGrid ID="RadGrid1" runat="server" Skin="Vista" Width="500px"
        GridLines="None" AllowFilteringByColumn="False" AllowSorting="True" OnExportCellFormatting="RadGrid1_ExportCellFormatting" DataSourceID="SqlDataSource1"
         AllowAutomaticDeletes="true" AllowAutomaticUpdates="True" AutoGenerateEditColumn="True"  AutoGenerateDeleteColumn="true" OnItemCommand="RadGrid1_ItemCommand" >
        <MasterTableView AutoGenerateColumns="False" DataKeyNames="ID" DataSourceID="SqlDataSource1" ItemStyle-HorizontalAlign="Left" CommandItemDisplay="TopAndBottom">
            <Columns>
                <telerik:GridTemplateColumn HeaderText="ID" SortExpression="ID" UniqueName="ID" Visible="false" ReadOnly="true"> 
                    <ItemTemplate> 
                        <asp:Label ID="lblIDView" runat="server" Text='<%# Bind("ID") %>'></asp:Label> 
                    </ItemTemplate> 
                </telerik:GridTemplateColumn>
                <telerik:GridTemplateColumn HeaderText="ID" SortExpression="IDEdit" UniqueName="IDEdit" Visible="false">
                    <ItemTemplate />
                    <EditItemTemplate>
                        <asp:Label ID="lblID" runat="server" Text='<%# Bind("ID") %>'></asp:Label> 
                    </EditItemTemplate>
                </telerik:GridTemplateColumn>
                <telerik:GridBoundColumn DataField="AccountNumber" HeaderText="Sapphire Account Number" 
                    SortExpression="AccountNumber" UniqueName="AccountNumberView" ReadOnly="true" ItemStyle-Width="400">
                </telerik:GridBoundColumn>
                <telerik:GridTemplateColumn HeaderText="Sapphire Account Number" SortExpression="AccountNumber" UniqueName="AccountNumber" Visible="false">
                    <ItemTemplate />
                    <EditItemTemplate>
                        <asp:Textbox ID="txtAccountNumber" runat="server" Text='<%# Bind("AccountNumber") %>' />
                        <asp:RequiredFieldValidator ID="rfvAccountNumber" ControlToValidate="txtAccountNumber"
                            ErrorMessage="Sapphire Account Number is required" runat="server" ForeColor="Red"></asp:RequiredFieldValidator>
                        <asp:CustomValidator ID="cvAccountNumber" runat="server" ErrorMessage="Sapphire Account Number already exists"
                            ControlToValidate="txtAccountNumber" ForeColor="Red" OnServerValidate="cvAccountNumber_ServerValidate"></asp:CustomValidator>
                    </EditItemTemplate>
                </telerik:GridTemplateColumn>
                <telerik:GridTemplateColumn HeaderText="Active" SortExpression="Active" UniqueName="Active" ItemStyle-Width="100" Visible="false">
                    <ItemTemplate />
                    <EditItemTemplate>
                        <asp:CheckBox ID="cbActive" runat="server" Checked='<%# GenerateBindString(Container.DataItem) %>' />
                    </EditItemTemplate>
                </telerik:GridTemplateColumn>
                <telerik:GridTemplateColumn HeaderText="Status" SortExpression="Active" UniqueName="Active" ItemStyle-Width="100"> 
                    <ItemTemplate> 
                        <asp:Label ID="lblActive" runat="server" Text='<%# Convert.ToBoolean(GenerateBindString(Container.DataItem)) == true ? "Active" : "Inactive" %>'></asp:Label> 
                    </ItemTemplate> 
                </telerik:GridTemplateColumn> 
             </Columns>
        </MasterTableView>
        <ValidationSettings CommandsToValidate="PerformInsert,Update" />
        <ClientSettings>
            <Selecting AllowRowSelect="True" />
        </ClientSettings>
    </telerik:RadGrid>
    
    <asp:SqlDataSource ID="SqlDataSource1" runat="server" 
        ConnectionString="<%$ ConnectionStrings:LBCust %>" 
        SelectCommand="SELECT * FROM [LBX_Portal_AccountNumbers] WHERE ([Site] = @Site) AND (Active=@Active OR @Active = '0') ORDER BY AccountNumber"
        DeleteCommand="DELETE FROM [LBX_Portal_AccountNumbers] WHERE [ID] = @ID" 
        InsertCommand="INSERT INTO [LBX_Portal_AccountNumbers] ([AccountNumber], [Site], [Active]) VALUES (@AccountNumber, @Site, @Active)" 
        UpdateCommand="UPDATE [LBX_Portal_AccountNumbers] SET [AccountNumber] = @AccountNumber,  [Active] = @Active WHERE [ID] = @ID">
        <SelectParameters>
            <asp:ControlParameter ControlID="dd_Status" Name="Active" 
                PropertyName="SelectedValue" Type="String" />
        </SelectParameters>
        <DeleteParameters>
            <asp:Parameter Name="ID" Type="Int32" />
        </DeleteParameters>
        <InsertParameters>
            <asp:Parameter Name="AccountNumber" Type="String" />
            <asp:Parameter Name="Site" Type="String" />
            <asp:Parameter Name="Active" Type="Boolean" />
        </InsertParameters>
        <UpdateParameters>
            <asp:Parameter Name="AccountNumber" Type="String" />
            <asp:Parameter Name="Active" Type="Boolean" />
        </UpdateParameters>
    </asp:SqlDataSource>
    

    CS:

    public partial class Admin_CustomerAccountManager : System.Web.UI.Page
    {
    public string SiteName = WebConfigurationManager.AppSettings["Site"].ToString();
    
    protected void Page_Load(object sender, EventArgs e)
    {
        Label LBXTitle = (Label)Master.FindControl("lbxTitle");
    
        LBXTitle.Text = "Customer Sapphire Account Number Manager";
    
        if (!this.IsPostBack)
        {
            SqlDataSource1.SelectParameters.Add("Site", DbType.String, SiteName);
        }
    }
    
    protected void dd_Status_SelectedIndexChanged(object sender, EventArgs e)
    {
        RadGrid1.DataBind();
    }
    
    protected bool GenerateBindString(object dataItem)
    {
        bool ret = false;
        // if column is null set checkbox.checked = false
    
        if ((DataBinder.Eval(dataItem, "Active")).ToString() == "")
            ret = false;
        else // set checkbox.checked to boolean value in Status column
            ret = (bool)DataBinder.Eval(dataItem, "Active");
    
        return ret;
    }
    
    protected void RadGrid1_ItemCommand(object source, Telerik.Web.UI.GridCommandEventArgs e)
    {
        Page.Validate();
        if (Page.IsValid)
        {
            if (e.CommandName == "PerformInsert")
            {
                GridEditFormItem gridEditFormItem = (GridEditFormItem)e.Item;
    
                Label lblID = (Label)gridEditFormItem.FindControl("lblID");
                TextBox txtAccountNumber = (TextBox)gridEditFormItem.FindControl("txtAccountNumber");
                CheckBox cbActive = (CheckBox)gridEditFormItem.FindControl("cbActive");
    
                bool isActive = true;
    
                string SqlStr = "INSERT INTO [LBX_Portal_AccountNumbers] ([AccountNumber], [Site], [Active])";
                SqlStr += " VALUES ('" + txtAccountNumber.Text + "'" + ", '" + SiteName + "'" + ", '" + isActive + "')";
    
                SqlDataSource1.InsertCommand = SqlStr;
                SqlDataSource1.Insert();
    
            }
    
            if (e.CommandName == "Update")
            {
                GridEditFormItem gridEditFormItem = (GridEditFormItem)e.Item;
    
                Label lblID = (Label)gridEditFormItem.FindControl("lblID");
                TextBox txtAccountNumber = (TextBox)gridEditFormItem.FindControl("txtAccountNumber");
                CheckBox cbActive = (CheckBox)gridEditFormItem.FindControl("cbActive");
    
                bool isActive = false;
    
                if (cbActive.Checked)
                    isActive = true;
                else
                    isActive = false;
    
                string SqlStr = "UPDATE [LBX_Portal_AccountNumbers] SET [AccountNumber] = '" + txtAccountNumber.Text;
                SqlStr += "', [Active] = '" + isActive + "'  WHERE [ID] = " + lblID.Text;
    
                SqlDataSource1.UpdateCommand = SqlStr;
                SqlDataSource1.Update();
            }
        }
    }
    
    protected void cvAccountNumber_ServerValidate(object source, ServerValidateEventArgs args)
    {
        TextBox txtAccountNumber = RadGrid1.FindControl("txtAccountNumber") as TextBox;
        List<GridDataItem> Items = (from item in RadGrid1.Items.Cast<GridDataItem>()
                                    where item["AccountNumberView"].Text == txtAccountNumber.Text
                                    select item).ToList();
    
        args.IsValid = Items.Count() == 0;
    }
    }