C# RadGrid (Gridview) 中的 FindControl 编辑和插入视图

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12698058/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 00:08:52  来源:igfitidea点击:

FindControl inside RadGrid (Gridview) Edit and Insert views

c#asp.netgridviewradgridrad-controls

提问by the sandman

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

我有一个 RadGrid (Gridview),可以选择编辑和插入新项目。

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.

在这两个选项中,我有一个 customvalidator 来检查现有值,因此无法输入重复项。我所坚持的是能够对仅在编辑和插入期间显示的文本框使用 findcontrol。

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.

当我调用 GetInsertItem() 时,这对 INSERT 非常有用,但是在编辑时会引发错误,我一直在坚持。我想在数据绑定和命令方法之外执行此操作。

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:

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:

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

采纳答案by Gregor Primar

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

看起来验证事件中的 GridView.FindControl 永远不会工作,您如何访问需要像这样验证的字符串:

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.

以下是访问实际控件的方法。在 ServerValidate 上下文中使用时,GridView.FindControl 将一无所获,因此您必须查看已编辑/插入的行。

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

回答by Hammad Khan

This is what I would suggest and how to takle this issue.

这就是我的建议以及如何解决这个问题。

Put a break point in the code where you are getting error.

在出现错误的代码中放置一个断点。

Run the program that is Debug. The program will stop at the break point.

运行调试程序。程序将在断点处停止。

In the Watch Windows add your object and see what values it contains. Do not be afraid. Watch Window is very powerful. You can add an object or any of its property to see what value it contains. You specifically want to focus on null value.

在监视窗口中添加您的对象并查看它包含哪些值。不要害怕。Watch Window 非常强大。您可以添加一个对象或其任何属性以查看它包含的值。您特别想关注空值。

Once you identify the null exception where it is coming from, fix that syntax right in the Watch window and run the program again.

一旦确定了空异常的来源,就在 Watch 窗口中修复该语法并再次运行程序。

回答by Win

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

首先,您的代码容易受到 SQL 注入,但这不是您最初的问题。

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

您不能通过 GridDataItems 循环查找重复项。如果您稍后对网格进行分页,您将无法找到它。

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

首先,为了简单起见,您可以使用 RadGrid 的 InsertCommand 和 UpdateCommand 事件。然后使用ADO.Net或您喜欢的任何方法检查重复项。

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