Home > OS >  DropDownList can't see the control in code behind
DropDownList can't see the control in code behind

Time:01-24

I have two drop downs, dependant on the end users area of business I'm wanting to disable one and hide it.

The ddls are in a gridview & I'm getting 'object reference not set to an instance of an object' & the ddl being null, I tested this outside of a gridview and it worked fine.

aspx


                    

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false" CellPadding="4" DataKeyNames="RowID, Status,Code"
    OnSelectedIndexChanged="GridView1_SelectedIndexChanged" ForeColor="#333333" Font-Names="Calibri" PageSize="10" GridLines="None" ShowFooter="True">
    <AlternatingRowStyle BackColor="White" />
        <Columns>
            <asp:BoundField ItemStyle-Width="50px" DataField="Person" HeaderText="Person" ItemStyle-HorizontalAlign="center" />
            <asp:BoundField ItemStyle-Width="100px" DataField="Code" HeaderText="Client Code" ItemStyle-HorizontalAlign="center" />
            <asp:BoundField ItemStyle-Width="300px" DataField="ClientName" HeaderText="Client" />
            <asp:BoundField ItemStyle-Width="150px" DataField="Status" HeaderText="Status Tracker" />
            <asp:TemplateField HeaderText="Update Status" ItemStyle-HorizontalAlign="center">
            <ItemTemplate>
                <asp:DropDownList ID="ddlClientStatus" Name="ddlClientStatus" runat="server"  AutoPostBack="True"  onselectedindexchanged="StatusSelected"  >
                    <asp:ListItem Selected="True" Value=""></asp:ListItem>
                    <asp:ListItem Value="Val1">1</asp:ListItem>
                    <asp:ListItem Value="Val2">2</asp:ListItem>
                    <asp:ListItem Value="Val3">3</asp:ListItem>
                    <asp:ListItem Value="Val4">4</asp:ListItem>
                    <asp:ListItem Value="Val5">5</asp:ListItem>
                </asp:DropDownList>
            </ItemTemplate>
                <ItemStyle Width="150px"/>

            </asp:TemplateField>
            <asp:TemplateField HeaderText="Update Status" ItemStyle-HorizontalAlign="center">
            <ItemTemplate>
                <asp:DropDownList ID="ddlClientStatusPL" Name="ddlClientStatusPL" runat="server"  AutoPostBack="True"  onselectedindexchanged="StatusSelected"  >
                    <asp:ListItem Selected="True" Value=""></asp:ListItem>
                    <asp:ListItem Value="Val6">6</asp:ListItem>
                    <asp:ListItem Value="Val7">7</asp:ListItem>
                    <asp:ListItem Value="Val8">8</asp:ListItem>
                    <asp:ListItem Value="Val9">9</asp:ListItem>
                    <asp:ListItem Value="Val10">10</asp:ListItem>
                </asp:DropDownList>
            </ItemTemplate>
                <ItemStyle Width="150px"/>

            </asp:TemplateField>
    </Columns>

cs

namespace Dashboard
{

    public partial class StatusTracker : System.Web.UI.Page
    {

protected void Page_Load(object sender, EventArgs e)
        {
              role = Request.QueryString["role"];

            if (role == "Sales")
            {
                ddlClientStatus.Enabled = false;
                ddlClientStatus.Visible = false;
                ddlClientStatusPL.Enabled = true;
            }
            else
            {
                ddlClientStatus.Enabled = true;
                ddlClientStatusPL.Enabled = false;
                ddlClientStatusPL.Visible = false;
            }


        } 
   }
}

I've also tried the below with no joy, still a null for the ddls.

DropDownList ddlClientStatus = (DropDownList)GridView1.FindControl("ddlClientStatus");
DropDownList ddlClientStatusPL = (DropDownList)GridView1.FindControl("ddlClientStatusPL"); 

I feel like I'm missing something really obvious.... Any help/pointers would be much appreciated!

CodePudding user response:

Let me try to solve your problem by replicating similar scenario. In this case, there is a GridView in the page which shows data of some persons. Each person have firstname, lastname and role.

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Role { get; set; }

}

Following is the code from .aspx.

<asp:GridView ID="dataGridView" runat="server" AutoGenerateColumns="false" CssClass= "table table-striped table-bordered table-condensed">
        <Columns>
            <asp:BoundField DataField="FirstName" HeaderText="First name" />
            <asp:BoundField DataField="LastName" HeaderText="Last name" />
            <asp:TemplateField HeaderText="Role">
                <ItemTemplate>
                    <asp:DropDownList ID="ddlRoles" runat="server">
                        <asp:ListItem Value="Admin" Text="Admin"></asp:ListItem>
                        <asp:ListItem Value="SuperAdmin" Text="Super Admin"></asp:ListItem>
                        <asp:ListItem Value="Lead" Text="Lead" ></asp:ListItem>
                        <asp:ListItem Value="Developer" Text="Developer" ></asp:ListItem>
                    </asp:DropDownList>
                </ItemTemplate>
            </asp:TemplateField>
             
        </Columns>
    </asp:GridView>

As you can see the grid view has two BoundFields and on TemplateField and the TemplateFields has a dropdownlist in it. The dropdownlist has 4 items added to it.

Following is the code in code behind which load persons data in the GridView.

public partial class _Default : Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if(!IsPostBack)
        {
            PopulateGridView();
        }
    }
    private void PopulateGridView()
    {
        var persons = new List<Person>();

        persons.Add(new Person { FirstName = "Blithe", LastName = "Taig", Role = "Developer" });
        persons.Add(new Person { FirstName = "Ewan", LastName = "Critoph", Role = "SuperAdmin" });
        persons.Add(new Person { FirstName = "Hyatt", LastName = "Atkinson", Role = "Lead" });
        persons.Add(new Person { FirstName = "Paloma", LastName = "Bauldry", Role = "Lead" });
        persons.Add(new Person { FirstName = "Eldon", LastName = "Lambert", Role = "Developer" });
        persons.Add(new Person { FirstName = "Ethyl", LastName = "Mugford", Role = "Lead" });
        persons.Add(new Person { FirstName = "Leupold", LastName = "Longmuir", Role = "SuperAdmin" });

        dataGridView.DataSource = persons;
        dataGridView.DataBind();
    }
}

With the above code, the Gridview is populated as following.

enter image description here

You can see that all the persons have role Admin selected in the gridview while they have different value set for Role in the code above. the dropdown list in the GridView Items do not get the values from the GridView DataSource by default. The values of DDL in each row need to be set by code.

For this I used RowDataBound event of the GridView. First I added OnRowDataBound="dataGridView_RowDataBound" attirbute in GridView inside aspx.

<asp:GridView ID="dataGridView" runat="server" AutoGenerateColumns="false" OnRowDataBound="dataGridView_RowDataBound" CssClass= "table table-striped table-bordered table-condensed">

And also created this event handler in the aspx.cs.

protected void dataGridView_RowDataBound(object sender, GridViewRowEventArgs e)
    {
        var dataItem = e.Row.DataItem as Person;

        if(dataItem != null)
        {
            var ddlRoles = (DropDownList)e.Row.FindControl("ddlRoles");
            if(ddlRoles != null)
            {
                ddlRoles.SelectedValue = dataItem.Role;
            }
        }
    }

With this change, the Role column in the GridView has now proper role selected in each row.

enter image description here

You can see in the code of dataGridView_RowDataBound how dropDown list is retrieved from the Row of Gridview by doing (DropDownList)e.Row.FindControl("ddlRoles").

Now coming to the similar feature you are implementing. There will be a query string parameter name role. And the gridview should have all the dropdownlist disabled which has that role selected.

Following is the code I wrote for disabling the dropdown.

private void DisableRole(string role)
    {
        // Loop thru GridView Rows.
        foreach(GridViewRow row in dataGridView.Rows)
        {
            // Try to find dropdownlist with id=ddlRoles from each row.
            var ddlRole = (DropDownList)row.FindControl("ddlRoles");
            // Disabled the dropdownlist if it is found the it has matching role selected
            if(ddlRole != null && ddlRole.SelectedItem.Value == role)
            {
                ddlRole.Enabled = false;
            }
        }
    }

Then called this method from Page_Load.

protected void Page_Load(object sender, EventArgs e)
    {
        if(!IsPostBack)
        {
            PopulateGridView();
        }

        var role = Request.QueryString["role"];

        if(!string.IsNullOrEmpty(role))
        {
            DisableRole(role);
        }
    }

With this change, when I browse URL http://localhost:53384/Default?role=Lead, the dropdowns with Lead selected in them are disabled.

enter image description here

In the code above I am iterating thru the Rows collection of GridView and finding Dropdownlist inside each row and trying to disable them.

The scenario I explained might be little different than yours. What I am trying to demonstrate is, if you need to access any control which is placed inside ItemTemplate of a GridView, you can only access it via GridViewRow. And you can loop thru the GridView.Rows collection wherever you need to.

I hope this will resole your doubts and help you resolve your issue.

CodePudding user response:

Since you are creating your drop down lists inside of a gridview, you need to wait until the gridview has rows populated.

When this happens, you can hook into gridview's RowDatabound event to set the visible and/or display properties of your dropdown lists.

<asp:GridView ID="dataGridView" runat="server" AutoGenerateColumns="false" CssClass= "table table-striped table-bordered table-condensed" OnRowDataBound="GridView1_RowDataBound">

protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e) handles
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        DropDownList ddlClientStatus = (DropDownList)e.Row.FindControl("ddlClientStatus");
        DropDownList ddlClientStatusPL =(DropDownList)e.Row.FindControl("ddlClientStatusPL");
        
        ddlClientStatus.Visible =  //do your logic to determine which should be visible / enabled
        ddlClientStatusPL.Visible = !ddlClientStatus.visible
     }
}
  • Related