5

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

在这两个选项中,我都有一个自定义验证器来检查现有值,因此无法输入重复项。我坚持的是能够将 findcontrol 用于仅在 EDIT 和 INSERT 期间显示的文本框。

当我调用 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;
}

这是编辑屏幕的图像。 在此处输入图像描述

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

3 回答 3

2

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

这是您验证目标控制值的方式:

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

以下是访问实际控件的方法。在 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");
    }
于 2012-10-02T21:16:48.707 回答
2

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

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

首先,为简单起见,您可以使用 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
   }
}
于 2012-10-12T21:28:29.657 回答
0

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

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

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

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

一旦您确定了它来自哪里的空异常,请在“监视”窗口中修复该语法并再次运行该程序。

于 2012-10-03T16:50:07.080 回答