5

新しい項目を編集および挿入するオプションがある RadGrid (Gridview) があります。

これらの両方のオプション内に、既存の値をチェックするカスタムバリデーターがあるため、重複を入力できません。私が立ち往生しているのは、EDITおよびINSERT中にのみ表示されるテキストボックスにfindcontrolを使用する機能です。

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

そして、これが実際のコントロールにアクセスする方法です。GridView.FindControlは、ServerValidateコンテキスト内で使用すると何も表示されないため、編集/挿入された行の内部を確認する必要があります。

    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

これが私が提案するものであり、この問題に取り組む方法です。

エラーが発生しているコードにブレークポイントを配置します。

Debug であるプログラムを実行します。プログラムはブレークポイントで停止します。

ウォッチ ウィンドウにオブジェクトを追加し、含まれている値を確認します。恐れることはありません。ウォッチ ウィンドウは非常に強力です。オブジェクトまたはそのプロパティを追加して、含まれている値を確認できます。特に null 値に焦点を当てたいとします。

null 例外の発生元を特定したら、[ウォッチ] ウィンドウでその構文を修正し、プログラムを再度実行します。

于 2012-10-03T16:50:07.080 に答える