Home > Blockchain >  Hide entire datalist item based on a property
Hide entire datalist item based on a property

Time:11-03

I have a datalist which is populated with values from a database. When the user clicks a checkbox, I want to loop through all of the datalist items and hide all of the items that have the property isActive = false (which is displayed as "Disabled" in a text label). The item template consists of a table that contains multiple other items, buttons etc, which have not been included below. I therefore want to hide all elements that are found under the itemtemplate of a specific item.

My idea was to just hide the entire table by accessing its id, and then setting the table's visible property to false. This is currently not doing anything when I run the code. Any help will appreciated!

 <asp:CheckBox runat="server" Text="Filter by active postings" OnCheckedChanged="filterByActive"/>
  <asp:DataList ID="postingsDataList" runat="server" OnItemCommand="itemCommand" >   

      <ItemTemplate>  
          <div class="postingRow">
              
      <table class="postingTable" id="posting">    
          
        <tr>  
               <td>     
               <asp:Label ID="lblActive"  runat="server" Text=<%#Eval("isActive").ToString().Equals("True") ? "Active   &#9989" : "Disabled   &#10060"%>/>  
          </td>  
        </tr>        
      </table>  

        </div>
        </ItemTemplate>  
  
    </asp:DataList>  

Code Behind:

 protected void filterByActive (object sender, EventArgs e)
        {
            int count = postingsDataList.Items.Count;
            CheckBox check = (CheckBox)sender;
            if (check.Checked == true)
            {              
                for (int i = 0; i < count; i  )
                {
                    Label lblActive = postingsDataList.Items[i].FindControl("lblActive") as Label;
                    string isActive = lblActive.Text.ToString();
                    if (isActive.Equals("Disabled   &#10060"))
                    {
                        Table tbl = postingsDataList.Items[i].FindControl("posting") as Table;
                        tbl.Visible = false;
                    }   
                }
            }
            else
            {
                for (int i = 0; i < count; i  )
                {
                    Label lblActive = postingsDataList.Items[i].FindControl("lblActive") as Label;
                    string isActive = lblActive.Text.ToString();
                    if (isActive.Equals("Active   &#9989"))
                    {
                        Table tbl = postingsDataList.Items[i].FindControl("posting") as Table;
                        tbl.Visible = true;
                    }
                }
            }
        }
    }

CodePudding user response:

Ok, I suggest you do this:

Persist your table - thus you don't have to hit sql server again. (but, you could - not the end of the world).

I don't have your data, but I have a simple list of hotels - and there is a Active column for the Hotel. So, lets filter the data based on checking the check box, not have to hit the database server again. And EVEN BETTER is if we un-check the box, we can display all records we had.

We assume of course this is not a lot of data.

Ok, so we have this for our markup:

(really does not matter a whole lot)

  <asp:DataList ID="DataList1" runat="server" DataKeyField="ID" RepeatColumns="4" RepeatDirection="Horizontal" >
    <ItemTemplate>
      <div style="border-style:solid;color:black;width:300px;">
        <div style="padding:5px;text-align:right">
            <p>Hotel Name: <asp:TextBox ID="HotelName" runat="server" Text ='<%# Eval("HotelName") %>' /></p>
            <p>First Name: <asp:TextBox ID="FirstName" runat="server" Text ='<%# Eval("FirstName") %>' /></p>
            <p>Last Name: <asp:TextBox ID="LastName" runat="server" Text ='<%# Eval("LastName") %>'    /></p>
            <p>City: <asp:TextBox ID="City" runat="server" Text ='<%# Eval("City") %>'  /></p>
            <p>Province: <asp:TextBox ID="Province" runat="server" Text ='<%# Eval("Province") %>'  /></p>
            Active: <asp:CheckBox ID="Active" runat="server" Checked = '<%# Eval("Active") %>'/>
        </div>
    </div>
</ItemTemplate>
</asp:DataList>

Now, our code to load could be this:

    DataTable rstData = new DataTable();
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            LoadData();
            ViewState["MyData"] = rstData;
        }
        else
            rstData = (DataTable)ViewState["MyData"];
    }

    void LoadData()
    {
        using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
        {
            string strSQL = "SELECT top 10 * from tblHotels ORDER BY HotelName";
            using (SqlCommand cmdSQL = new SqlCommand(strSQL, conn))
            {
                conn.Open();
                rstData.Load(cmdSQL.ExecuteReader());
                DataList1.DataSource = rstData;
                DataList1.DataBind();
            }
        }
    }

And now we have this:

enter image description here

Now, our filter show/hide becomes JUST this:

   protected void ckFilter_CheckedChanged(object sender, EventArgs e)
    {
        // filter based on check box

        if (ckFilter.Checked)
            rstData.DefaultView.RowFilter = "Active = 1";
        else
            rstData.DefaultView.RowFilter = "";

        DataList1.DataSource = rstData;
        DataList1.DataBind();
    }

And BETTER is if I un-check the check box, all the data is re-displayed. And we don't have to re-hit the database to do this!!!

Now, we COULD also just hide/show each row, and then un-hide if for some reason you don't want to persist the data table as I did per above.

Checking on the box filters to this:

enter image description here

As noted, if I un-check the box, then I get all the data back - all without hitting the database again.

Edit:=========================================

Note that if you NOT using the above horizontal across, but just rows down?

Then you can just as well format to hide/show the rows, and you do NOT have to persist the data table.

You can apply formatting say by doing this:

    protected void ckFilter_CheckedChanged(object sender, EventArgs e)
    {
        foreach (DataListItem gRow in DataList1.Items)
        {
            // get checkbox
            CheckBox ckActive = (CheckBox)gRow.FindControl("Active");
            // get div
            HtmlGenericControl Myiv = (HtmlGenericControl)gRow.FindControl("myrow");       
            string MyFormat = "normal";
            if (ckFilter2.Checked)
            {
                // only show active ones
                if (ckActive.Checked)
                    MyFormat = "normal";
                else
                    MyFormat = "none";
            }
            Myiv.Style["display"] = MyFormat;
        }
    }

So the above does work fine. BUT the restriction is that you can't have a set of horizontal across data items like my original screen shot (it actually still works but in fact hide each panel with a blank space).

So, if your as noted using vertical layout (and it looks to be that you are).

Note for above, I added a simple ID to the "div", and runat server like this:

<ItemTemplate>
 <div id="myrow" runat="server" 
   style="border-style:solid;color:black;width:300px;">

Then skip my first example. You can loop the data list rows, and hide, or un-hide. And even more amazing is that if you un-hide - then the rows all do re-appear and persist correct.

I had pulled a working example - but I was trying to figure out why I had to persist the data - the reason was the "horizontail" across settings.

But, as above shows, no real need to persist the data source table - you can process the data list rows, and hide/show each one conditionals, and you can do this without a data re-bind.

  • Related