FindControl внутри RadGrid (Gridview) Редактировать и вставлять представления

У меня есть RadGrid (Gridview), в котором есть возможность редактировать и вставлять новые элементы.

В обоих этих параметрах у меня есть настраиваемый валидатор для проверки существующих значений, поэтому дубликаты не могут быть введены. На чем я застрял, так это на возможности использовать findcontrol для текстового поля, которое отображается только во время EDIT и INSERT.

Это отлично работает для INSERT, поскольку я вызываю GetInsertItem(), но при редактировании возникает ошибка, и я застрял на этом. Я хочу сделать это вне методов привязки данных и команд.

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

person the sandman    schedule 02.10.2012    source источник
comment
в чем ошибка, нулевое исключение?   -  person Hammad Khan    schedule 03.10.2012
comment
Вставка элемента доступна только тогда, когда сетка находится в режиме вставки.   -  person the sandman    schedule 03.10.2012
comment
Это только тогда, когда он запускается, пытаясь обновить в режиме редактирования. ошибки из GetInsertItem()   -  person the sandman    schedule 03.10.2012


Ответы (3)


Похоже, что 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");
    }
person Gregor Primar    schedule 02.10.2012
comment
Текстовое поле не отображается в представлении «Дизайн». - person the sandman; 03.10.2012
comment
Так и должно быть, если вы не создаете gridview во время выполнения. Перейдите в DesignView и отредактируйте шаблоны. В раскрывающемся списке выберите EditItemTemplate. Затем вы должны увидеть текстовое поле. - person Gregor Primar; 03.10.2012
comment
Хорошо, я нашел его, и похоже, что этот идентификатор уже был установлен. Вот скриншот: ссылка - person the sandman; 03.10.2012
comment
Это нормально, теперь просто используйте код из моего примера, и сервер должен найти это текстовое поле. - person Gregor Primar; 03.10.2012
comment
Я получаю ссылку на объект, не установленную на экземпляр объекта. ошибка. - person the sandman; 03.10.2012
comment
Не могли бы вы опубликовать файл aspx и cs? Вы можете изолировать контент по этой теме. - person Gregor Primar; 03.10.2012
comment
УХ ТЫ. Это сделало это. Как раз то, что мне нужно для доступа к значению. Спасибо Грегор, ты мужик! - person the sandman; 03.10.2012
comment
Грегор, на самом деле это не сработает, так как я только что узнал, что моя проверка не будет работать без этого идентификатора строки #, который является еще одним элементом управления рядом с текстовым полем. любая идея, как я мог получить это значение? я знаю, что мы не можем использовать аргументы в пользовательском валидаторе. действительно застрял здесь. Спасибо - person the sandman; 04.10.2012
comment
Проверьте новый отредактированный ответ. Надеюсь, в этот раз будет все, что вам нужно :) - person Gregor Primar; 04.10.2012
comment
Спасибо, Грегор, но RadGrid1.Rows недоступен и выдает ошибку. я продолжу пробовать несколько других вещей - person the sandman; 05.10.2012
comment
добавлена ​​награда, чтобы получить больше идей о том, как я могу получить эти значения изнутри cvAccountNumber_ServerValidate - person the sandman; 06.10.2012

Прежде всего, ваш код подвержен внедрению SQL, но это не ваш первоначальный вопрос.

Вы не можете пройти через GridDataItems, чтобы найти дубликаты. Вы не сможете найти его, если позже будете разбивать свою сетку на страницы.

Сначала вы можете использовать события InsertCommand и UpdateCommand RadGrid для простоты. Затем проверьте дубликат, используя 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
   }
}
person Win    schedule 12.10.2012
comment
Спасибо. Однако проблема здесь в том, что я не могу снова запустить пользовательский валидатор. radgrid уже думает, что страница действительна, а затем скрывает вставку, а не вставляет ее или нет. - person the sandman; 16.10.2012
comment
Я рад, что вы решили свою проблему. Если вы не возражаете, я хотел бы предложить вам использовать параметризованный запрос для предотвращения внедрения SQL. functionx.com/aspnet_csharp/articles/parameterized.htm - person Win; 17.10.2012

Вот что я хотел бы предложить и как решить эту проблему.

Поставьте точку останова в коде, где вы получаете ошибку.

Запустите программу Debug. Программа остановится в точке останова.

В Watch Windows добавьте свой объект и посмотрите, какие значения он содержит. Не бояться. Окно просмотра очень мощное. Вы можете добавить объект или любое его свойство, чтобы увидеть, какое значение он содержит. Вы специально хотите сосредоточиться на нулевом значении.

Как только вы определите источник нулевого исключения, исправьте этот синтаксис прямо в окне Watch и снова запустите программу.

person Hammad Khan    schedule 03.10.2012