微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

处理客户端和服务器端的 GridView 和自定义验证

如何解决处理客户端和服务器端的 GridView 和自定义验证

我不太确定如何解决这个问题。

我想做什么: 浏览具有多行的 gridview,如果某些文本框或下拉列表保留认值,则强制用户输入特定值。

我尝试了什么:

  1. 通过使用 javascript 中的 focusout 事件尝试了客户端要求。根据用户之前所做的选择,重点放在这些字段上,该部分有效。我的代码
var row = $(this).closest('tr');
var text = $(row).find("input[name*='txtCurriculum']").val('enter lesson/unit name here'); 
var ddl = $(row).find("select[name*='ddlCurrAdditions']");
$(ddl).focusout(function () {
    if (ddl.val == "-select curriculum name-") {
        $(ddl).focus();
        alert("select a curriculum name before moving on");
    }
});

$(text).focusout(function () {
    if (text.val == 'enter lesson/unit name here') {
        $(text).focus();
        alert('enter in a lesson or unit name before moving on');
    }
});

它从未正确发射。 ddl focusout 会触发,但在我退出并返回页面之前不会停止触发。文本焦点永远不会触发。

  1. 尝试使用自定义验证功能进行服务器端验证。
protected void cv1_ServerValidate(object source,ServerValidateEventArgs args)
{
    CustomValidator cv = ((CustomValidator)(source));
    GridViewRow gvr;

    //if (FormCGrid.Rows)
    foreach (GridViewRow row in FormCGrid.Rows)
    {
        //string ddl = ((DropDownList)row.FindControl("ddlCurrAdditions")).SelectedItem.Text;

        string txtC = ((TextBox)row.FindControl("txtCurriculum")).Text;
        bool ddl = ((DropDownList)row.FindControl("ddlCurrAdditions")).Visible;

        if (txtC == "enter lesson/unit name here")
        {
            args.IsValid = false;
            cv.ErrorMessage = string.Format("Please enter the Additional program name on row {0}",row.RowIndex);      
        }
        else if (ddl == true)
        {
            cv.ErrorMessage = string.Format("Enter your lesson or unit for the curriculum selected on row  {0}",row.RowIndex);
            args.IsValid = false;
        }
    }
}

我试图在这里遍历 gridview 的行,检查命名下拉列表的可见性(隐藏直到另一个下拉列表显示它,取决于那里选择的值)和认值的文本框,但这也不起作用.它根本没有开火。欢迎提出任何建议。

我对大多数编程/编码问题一般都没有问题,但我发现使用 asp.net gridview 时,我的所有技术都被抛到了窗外。

解决方法

好的,有两种方法可以做到这一点,在这里你可以很容易地使用 js。但是,让我们使用 100% 的服务器端代码。我认为坚持使用服务器端代码更容易。

接下来呢?我实际上强烈建议在您计划编辑数据时使用列表视图代替网格视图。原因很简单 - ListView 不需要为您想要在该网格显示中放置/拥有的每个 asp.net 控件一遍又一遍地要求那些“令人讨厌的”“项目模板”。现在公平地说,说 2-3 个控件 - 然后网格视图还可以,但是对于更多,我真的发现列表视图在这里开始大获全胜(不需要项目模板)。 listview 的“技巧”当然是在网页上设置一个数据源,让它生成标记,然后吹掉(删除)除项目模板之外的所有模板。然后删除页面上的datasource1项,并从列表视图中删除datasource1设置。

但是,让我们使用网格视图 - 因此这将是一些“更混乱”的东西

所以,我们要填写网格 - 并说我们想要一个城市组合框 - 必须被选中。让我们做一个基本的检查,说姓氏也必须输入。

所以,我们有一个城市组合框(数据库驱动)。并说让我们为酒店评级(1-5)添加下拉菜单 - 但这只有 5 种选择 - 所以我们在下拉列表中添加了标记。 (所以有两个组合示例来说明这是如何工作的)。

所以,假设我们有一个这样的网格,我们点击保存,我们得到了这个结果:

enter image description here

现在,我们当然会喜欢那个消息框区域。事实上,我们可以很容易地放入 jQuery.UI 并让右边那个可爱的 div 出现在一个对话框中(我们甚至可以从我们的服务器端代码中触发那个框 + jQuery.UI 对话框显示 - 但让我们尝试并保持简短 - 但我会喜欢那个错误消息区域)。

好的,首先是标记:

只是一个简单的网格,但由于那些“项目模板”而“有点乱” - (如果你没有弄清楚,我真的不喜欢那些模板东西!!! - 使用列表视图你不需要它们!! - 只需为网格添加纯粹干净的 asp.net 控件。无论如何:

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="ID">
    <Columns>

        <asp:BoundField DataField="ID" HeaderText="ID" InsertVisible="False" ReadOnly="True" SortExpression="ID" />
                
        <asp:TemplateField  HeaderText="HotelName" >
            <ItemTemplate><asp:TextBox id="HotelName" runat="server" Text='<%# Eval("HotelName") %>' /></ItemTemplate>
        </asp:TemplateField>

        <asp:TemplateField  HeaderText="FirstName" >
            <ItemTemplate><asp:TextBox id="FirstName" runat="server" Text='<%# Eval("FirstName") %>' /></ItemTemplate>
        </asp:TemplateField>

        <asp:TemplateField  HeaderText="LastName" >
            <ItemTemplate><asp:TextBox id="LastName" runat="server" Text='<%# Eval("LastName") %>' /></ItemTemplate>
        </asp:TemplateField>

        <asp:TemplateField HeaderText="City">
            <ItemTemplate>
                <asp:DropDownList ID="cboCity" runat="server" DataTextField="City" 
                    DataValueField = "City" Width="110px">
                </asp:DropDownList>
            </ItemTemplate>
        </asp:TemplateField>

        <asp:TemplateField HeaderText="Active">
            <ItemTemplate><asp:CheckBox id="Active" runat="server"  Checked = '<%# Eval("Active") %>'  /></ItemTemplate>
        </asp:TemplateField>

        <asp:TemplateField HeaderText="Rating">
            <ItemTemplate>
                <asp:DropDownList ID="cboRating" runat="server" SelectedValue = '<%# Eval("Rating") %>' >
                    <asp:ListItem Value="1">Poor</asp:ListItem>
                    <asp:ListItem Value="2">Just Ok</asp:ListItem>
                    <asp:ListItem Value="3">Ok</asp:ListItem>
                    <asp:ListItem Value="4">Good</asp:ListItem>
                    <asp:ListItem Value="5">Excellent</asp:ListItem>
                </asp:DropDownList>
            </ItemTemplate>
        </asp:TemplateField>
         
    </Columns>

</asp:GridView>
</div>

    <div id="ErrorDialog" style="display:normal;float:left;padding-left:30px;width:20%" runat="server">
        <asp:TextBox ID="txtErrors" runat="server" TextMode="MultiLine" Style="width:100%" Rows="20"   ></asp:TextBox>
    </div>

<div style="clear:both;padding-top:20px">
    <asp:Button ID="cmdSave" runat="server" Text="Save" />
    <asp:Button ID="cmdUnDo" runat="server" Text="UnDo" Style="margin-left:20px"/>
</div>

好的,现在开始吗?哎呀,这大约是我一次性发布的总最大标记 - 除了上面之外,我们接近了“不太好”的发布区域。

好的,让我们看看加载这个网格的代码。我们有这个代码:

public class EditHotelsG : System.Web.UI.Page
{
private DataTable rstTable = new DataTable();
private DataTable rstCity = new DataTable();

protected void Page_Load(object sender,System.EventArgs e)
{
    if (System.Web.UI.Page.IsPostBack == false)
    {
        ErrorDialog.Visible = false;

        LoadGrid();
        ViewState["rstTable"] = rstTable;
        ViewState["rstCity"] = rstCity;
    }
    else
    {
        rstTable = ViewState["rstTable"];
        rstCity = ViewState["rstCity"];
    }
}


public void LoadGrid()
{

    // load up our drop down list from database (city)
    string strSQL;

    strSQL = "SELECT City from tblCity Order by City";

    using (SqlCommand cmdSQL = new SqlCommand(strSQL,new SqlConnection(My.Settings.TEST3)))
    {
        cmdSQL.Connection.Open();

        rstCity.Load(cmdSQL.ExecuteReader);

        // now load up main grid view

        strSQL = "SELECT ID,FirstName,LastName,HotelName,City,Active,Rating from tblHotels ORDER BY HotelName";

        cmdSQL.CommandText = strSQL;

        rstTable.Load(cmdSQL.ExecuteReader);
        GridView1.DataSource = rstTable;
        GridView1.DataBind();
    }
}


protected void GridView1_RowDataBound(object sender,GridViewRowEventArgs e)
{

    // set combo box data source
    if (e.Row.RowType == DataControlRowType.DataRow)
    {

        // setup city drop down list

        DropDownList cboDrop = e.Row.FindControl("cboCity");
        cboDrop.DataSource = rstCity;
        cboDrop.DataBind();
        cboDrop.Items.Insert(0,new ListItem(string.Empty));     // add blank row

        cboDrop.Text = rstTable.Rows(e.Row.RowIndex).Item("City").ToString;
    }
}
}

好的,现在代码不多了。一个很好的部分是设置那个组合框。由于 cbo 框(下拉列表)是数据库驱动的,所以我们必须为每一行绑定 + 设置。因此,这花费了我们大量的编码时间。

但是请注意我们如何持久化数据库源(表)。我们这样做,因为我们想用更少的代码,一次性更新整个数据库。通过持久化该表,我们

Transfer data from Grid to table
Save the table to database in one shot

因此,这大大减少了我们的编码工作。

保存我们数据的代码,因此变成了这个宝石: (并注意我们还如何输入验证代码)。

protected void cmdSave_Click(object sender,EventArgs e)
{

// pull gride rows back to table.
bool bolDataOk = true;
txtErrors.Text = "";

foreach (GridViewRow rRow in GridView1.Rows)
{
    int RecordPtr = rRow.RowIndex;

    DataRow OneDataRow;
    OneDataRow = rstTable.Rows(RecordPtr);

    OneDataRow.Item("HotelName") = rRow.FindControl("HotelName") as TextBox.Text;
    OneDataRow.Item("FirstName") = rRow.FindControl("FirstName") as TextBox.Text;
    OneDataRow.Item("LastName") = rRow.FindControl("LastName") as TextBox.Text;
    OneDataRow.Item("City") = rRow.FindControl("cboCity") as DropDownList.Text;
    OneDataRow.Item("Active") = rRow.FindControl("Active") as CheckBox.Checked;
    OneDataRow.Item("Rating") = rRow.FindControl("cboRating") as DropDownList.SelectedValue;

    // check for missing City,or LastName
    if (IsDBNull(OneDataRow("City")) | OneDataRow("City") == "")
    {
        bolDataOk = false;
        if (txtErrors.Text != "")
            txtErrors.Text += Constants.vbCrLf;
        txtErrors.Text += "Missing City on row = " + (rRow.RowIndex + 1).ToString;
    }

    if (IsDBNull(OneDataRow("LastName")) | OneDataRow("LastName") == "")
    {
        bolDataOk = false;
        if (txtErrors.Text != "")
            txtErrors.Text += Constants.vbCrLf;
        txtErrors.Text += "Missing lastName on row = " + (rRow.RowIndex + 1).ToString;
    }
}

ErrorDialog.Visible = !(bolDataOk);

// now send table back to database with updates

if (bolDataOk)
{
    string strSQL = "SELECT ID,Rating from tblHotels WHERE ID = 0";
    using (SqlCommand cmdSQL = new SqlCommand(strSQL,new SqlConnection(My.Settings.TEST3)))
    {
        cmdSQL.Connection.Open();
        SqlDataAdapter daupdate = new SqlDataAdapter(cmdSQL);
        SqlCommandBuilder cmdBuild = new SqlCommandBuilder(daupdate);

        daupdate.Update(rstTable);
    }
}
}

现在,再一次,上面的代码片段有点长 - 并且是 SO 的代码片段的最大大小。我可能会考虑将上述最后一段代码分解为 2 个甚至 3 个例程。

但是,总而言之,上面展示了很多技巧和方法。

如前所述,我将发布如何使用客户端代码进行验证,但是使用一次数据库更新保存整个网格的总体想法?好吧,我会将这个技巧与列表视图、网格视图一起使用,即使我正在做客户端 js 验证?我仍然会使用上面的大部分设计模式。

还有取消按钮?好吧,我从未完成那部分 - 但它只会调用与第一页加载相同的代码(回发 - 错误,您只需从数据库源重新绑定网格以用于取消按钮。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。