首页 > 解决方案 > ASP.NET GridView 不显示下拉列表

问题描述

我有一个 ASP.NET Web 应用程序,它连接到 SQL 数据库并在一个页面上填充多个网格视图,显示不同的数据集。其中两列是下拉列表,因为我希望用户能够选择不同的(类别和状态)。我可以让数据显示的唯一方法是,如果我在 gridview 本身中硬编码类别和状态名称,如下所示:

<asp:TemplateField SortExpression="rank" Visible="true" HeaderText="Area" >
    <HeaderStyle HorizontalAlign="Left" CssClass="col_med" />
    <ItemTemplate>
    <asp:DropDownList id="ddlRank" AutoPostBack="True" OnSelectedIndexChanged="Rank_Change" runat="server" CssClass="col_med" 
    SelectedValue='<%# Eval("rank") %>' TabIndex='<%# TabIndex %>'>
        <asp:ListItem Value=""> - </asp:ListItem>
        <asp:ListItem Value="1"> 1</asp:ListItem>
        <asp:ListItem Value="2"> 2</asp:ListItem>
        <asp:ListItem Value="3"> 3</asp:ListItem>
        <asp:ListItem Value="4"> 4</asp:ListItem>
        <asp:ListItem Value="5"> 5</asp:ListItem>
        <asp:ListItem Value="6"> 6</asp:ListItem>
    </asp:DropDownList>
    </ItemTemplate>
</asp:TemplateField>

我想要做的是从数据库中提取状态并使用

OnRowDataBound="OnRowDataBound"

将数据库中的数据拉到下拉列表中,如下所示:

protected void OnRowDataBound(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        //Find the DropDownList in the Row
        DataTable ddLine = DAL.listLine();
        ddLine = resort(ddLine, "line", "desc");
        //Find the DropDownList in the Row
        DataTable ddlArea = DAL.listArea();
        ddlArea = resort(ddlArea, "area", "desc");
    }
}

OnRowDataBound但是,当我尝试像这样实现和更改我的 gridview时,这不起作用,并且根本没有数据显示在我的 gridview 中:

<asp:BoundField HeaderText="Area" DataField="rank" />
    <asp:TemplateField HeaderText = "Area">
        <ItemTemplate>
            <asp:Label ID="lblArea" runat="server" Text='<%# Eval("rank") %>' Visible = "false" />
            <asp:DropDownList ID="ddlArea" runat="server">
            </asp:DropDownList>
        </ItemTemplate>
    </asp:TemplateField>

任何人都可以建议上述方法是否是我的方案的最佳实践,如果是,代码可能有什么问题导致我的数据不显示?

标签: c#asp.netgridview

解决方案


Ok, since a dropdown in each row? Two issues: One, you have to fill it in the item data bound event. Two, you ALSO have to then set the value to the correct value.

So, you need to do both goals.

And lets toss in the ability to tab around on each row, edit the values, and then have ONE save button. You can dump the save button, but say we have a city drop down list in that gridview. So we have this markup (and city will be the dropdown list).

So, our markup is this:

<div style="width:40%">

  <asp:GridView ID="MyGrid" runat="server" AutoGenerateColumns="false" CssClass="table table-hover">

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

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

        <asp:TemplateField HeaderText ="Hotel Name">
            <ItemTemplate><asp:TextBox ID="HotelName" runat="server" Text='<%# Eval("HotelName") %>'></asp:TextBox></ItemTemplate>
        </asp:TemplateField>


        <asp:TemplateField HeaderText ="City">
            <ItemTemplate>
            <asp:DropDownList  id="CityDrop" runat="server" datatextfield="City" datavaluefield="City" style="height:25px" ></asp:DropDownList>
            </ItemTemplate>
        </asp:TemplateField>

        <asp:Templatefield HeaderText ="Province">
            <ItemTemplate><asp:TextBox ID="Province" runat="server" Text='<%# Eval("Province") %>' ></asp:TextBox></ItemTemplate>
        </asp:Templatefield>
        
    </Columns>

  </asp:GridView>

<asp:Button ID="cmdSave" runat="server" Text="Save Edits" Width="124px" />
</div>

Ok, so the output looks like this:

enter image description here

So you can tab around - make changes. And then the one save button will write all changes back to the database.

You can remove the database save button code - but it not much code anyway.

And I DID persist the table - that just saved code. As noted, you can remove the persisting of the table if you don't want edits (dump the view state code).

As for the city combo box? I only load the city table one time - and only on the first page load - it persists JUST long enough at the form level for the item databound code to work.

The code that binds the combo box ALSO adds a blank row - since I wanted to allow a blank selection.

The code is thus this:

    DataTable MyTable = new DataTable();
    DataTable MyCity = new DataTable();

    protected void Page_Load(object sender, EventArgs e)
    {
        if (IsPostBack == false)
        {
            LoadGrid();
            ViewState["MyTable"] = MyTable;
        }
        else
                MyTable = (DataTable)ViewState["MyTable"];
    }

    public void LoadGrid()
    {
        using (SqlCommand cmdSQL = new SqlCommand("SELECT City from tblCity ORDER BY City",
            new SqlConnection(Properties.Settings.Default.TEST3)))
        {
            cmdSQL.Connection.Open();
            MyCity.Load(cmdSQL.ExecuteReader());


            cmdSQL.CommandText = "SELECT * from tblHotels ORDER BY HotelName";
            MyTable.Load(cmdSQL.ExecuteReader());
            MyGrid.DataSource = MyTable;
            MyGrid.DataBind();

        }
    }

    protected void MyGrid_RowDataBound(object sender, GridViewRowEventArgs e)
    {
        if (e.Row.RowType == DataControlRowType.DataRow)
        {
            DropDownList mydrop = (DropDownList)e.Row.FindControl("CityDrop");
            mydrop.DataSource = MyCity;
            mydrop.DataBind();
            mydrop.Items.Insert(0, new ListItem(string.Empty));     // add blank row
                                                                    // set drop down list to row value (use table to get this value)
            
            mydrop.Text = MyTable.Rows[e.Row.RowIndex]["City"].ToString();
        }
    }

    protected void cmdSave_Click(object sender, EventArgs e)
    {
        // move data from grid to table
        foreach (GridViewRow MyRowG in MyGrid.Rows)
        {
            DataRow OneRow = MyTable.Rows[MyRowG.RowIndex];
            TextBox tt;
            
            OneRow["FirstName"] = ((TextBox)MyRowG.FindControl("FirstName")).Text;
            OneRow["lastName"] = ((TextBox)MyRowG.FindControl("LastName")).Text;
            OneRow["HotelName"] = ((TextBox)MyRowG.FindControl("HotelName")).Text;
            OneRow["City"] = ((DropDownList)MyRowG.FindControl("CityDrop")).Text;
            OneRow["Province"] = ((TextBox)MyRowG.FindControl("Province")).Text;
        }

        // table now loaded - save back to databsse
        using (SqlCommand cmdSQL = new SqlCommand("SELECT * from tblHotels WHERE ID = 0",
                                   new SqlConnection(Properties.Settings.Default.TEST3)))
        {
            SqlDataAdapter da = new SqlDataAdapter(cmdSQL);
            SqlCommandBuilder daUpdate = new SqlCommandBuilder(da);

            da.Update(MyTable);
        }
    }
}

So, you have to load up each drop down list for each row, then set the value of that dropdown list to the correct value (you have to do both).

As noted, if your goal is to not have the user tab around, make changes - select the drop down etc? Then you can dump the save button code, and dump the viewstate code that persists the data table.


推荐阅读