Panel visibility asp.net - asp.net

Forgive me as this is my first post and I am far from being IT savvy but I have been working on a project for my new job...
I am using Visual Studio 2017 and a asp.net Web form template.
I have several panels that I have set visibility to false and have set each panel to become only visible if a certain option is selected from a checkbox list.
I have managed to successfully code the visibility HOWEVER I want to allow the user to view more than one panel when more than one item is selected from the checkbox list... unfortunately it looks as though only one panel becomes visible at a time. I am assuming that they are overlapping .
I have tried putting each panel in a table to act as sort of a placeholder but with no success.
Any advice would be much appreciated 🙏
aspx.vb
Protected Sub ListBox1_Changed(ByVal sender As Object, ByVal e As EventArgs) Handles ListBox1.SelectedIndexChanged
If ListBox1.SelectedValue = "AA" Then
Panel1.Visible = True
Else
Panel1.Visible = False
If ListBox1.SelectedValue = "BB" Or ListBoxLivewell.SelectedValue = "CC" Or ListBoxLivewell.SelectedValue = "DD" Then
Panel2.Visible = True
Else
Panel2.Visible = False
End If

I suggest you create blank test page, and try this:
Markup:
<asp:CheckBox ID="CheckBox1" runat="server" Text="Panel1" AutoPostBack="true" />
<asp:CheckBox ID="CheckBox2" runat="server" Text="Panel2" AutoPostBack="true" />
<asp:CheckBox ID="CheckBox3" runat="server" Text="Panel3" AutoPostBack="true" />
<asp:Panel ID="Panel1" runat="server">
<h2>Panel 1</h2>
</asp:Panel>
<asp:Panel ID="Panel2" runat="server">
<h2>Panel 2</h2>
</asp:Panel>
<asp:Panel ID="Panel3" runat="server">
<h2>Panel 3</h2>
</asp:Panel>
code behind:
Protected Sub CheckBox1_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox1.CheckedChanged
' we could use this one line
' Panel1.Visible = CheckBox1.Checked
' or
If CheckBox1.Checked Then
Panel1.Visible = True
Else
Panel1.Visible = False
End If
End Sub
Protected Sub CheckBox2_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox2.CheckedChanged
Panel2.Visible = CheckBox2.Checked
End Sub
Protected Sub CheckBox3_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox3.CheckedChanged
Panel3.Visible = CheckBox3.Checked
End Sub
We get this:
Do note, since the page just loaded, then NONE of my check box code has run. And in fact if I check ONE box, I get this:
So, in fact to hide the Panel 1, I can now un-check the first box, and get this:
Note how the panels are in a way "out of sync", since I don't really check, or do anything with the panels on startup, and thus they don't reflect the correct status.
In fact, untill I check, and un-check all 3, then at that point, they all work ok.
So, probably better would be to do this.
On the first page load (and ONLY ONLY first load), I would do this:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
ShowPans()
End If
End Sub
Sub ShowPans()
Panel1.Visible = CheckBox1.Checked
Panel2.Visible = CheckBox2.Checked
Panel3.Visible = CheckBox3.Checked
End Sub
So, now on first page load - I hide/show the panels based on check box code, and now everything starts out "synced" up correctly
Do try a test blank page with above, but hiding and showing the panels should work.
Do note, that in MANY cases it is better to hide/show the panels and NOT use visibile. The reason for this is that any control marked as visibile = false IS NOT SENT to the browser. If you have some client side JavaScript running, or doing things, they will NOT be able to see, nor reference those panels.
So, in many cases, it is FAR better to hide, and NOT use Visible=false. As noted, this is VERY much a requement if you using client side JavaScript to manipulate such controls.
As a result, our code would now become this:
Protected Sub CheckBox1_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox1.CheckedChanged
If CheckBox1.Checked Then
Panel1.Style("display") = "normal"
Else
Panel1.Style("display") = "none"
End If
End Sub
Protected Sub CheckBox2_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox2.CheckedChanged
If CheckBox2.Checked Then
Panel2.Style("display") = "normal"
Else
Panel2.Style("display") = "none"
End If
End Sub
Protected Sub CheckBox3_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox3.CheckedChanged
' same as above 2 - but short hand code
Panel3.Style("display") = IIf(CheckBox3.Checked, "normal", "none")
End Sub
Now, you ONLY need to do the above if you using say JavaScript client side - I just wanted to make clear that using Visible can often be a issue, since as noted visible = false means the control is NOT sent nor rendered browser side - I spent a hard day of bugs learning this when I then started to write a lot of JavaScript.
Since, so far, this looks to be 100% server side code, so you can use .Visible.
but, do cook up a quick tiny test web page - play with above - make sure it works, and then try again on your code.

Related

ASP.NET CheckBox not checked on postback without weird hack

I have a GridView with a checkbox column. On clicking a button, all rows with the checkbox checked should be removed. I somehow stumbled upon a strange and hacky solution, and I have no idea why it works. I already searched through related SO questions already.
Related code:
Protected Sub Page_Init(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Init
' I have no idea why this is needed for the checkboxes to work...
Dim x = imageGridView.Rows
End Sub
Protected Sub RemoveButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles removeButton.Click
For Each row As GridViewRow In imageGridView.Rows
Dim selectCheckBox As CheckBox = DirectCast(row.Cells(0).FindControl("selectCheckBox"), CheckBox)
If selectCheckBox.Checked Then
Dim fileName As String = row.Cells(1).Text
ImageList.Remove(ImageList.FindLast(Function(r) r.FileName = fileName))
End If
Next
imageGridView.DataSource = ImageList
imageGridView.DataBind()
End Sub
Aspx:
<asp:GridView ID="imageGridView" runat="server">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:CheckBox ID="selectCheckBox" runat="server" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
The line Dim x = imageGridView.Rows is needed for the rows to be removed. I found this after trying my RemoveButton_Click code in the Page_Init sub, then removing code until it didn't work anymore. Dim x = imageGridView is not enough, and it doesn't work to do the same thing in Page_Load.
My checkboxes are never disabled.
So, simply put, why is it necessary for me to reference imageGridView.Rows in the Page_Init for my code to work?
That is an interesting behavior. I reproduce the problem if I bind the data to the GridView in Page_Load on every postback. In that situation, the check boxes lose their selection state on postback, but not if we refer to imageGridView.Rows in Page_Init, as you observed.
The solution is to bind the data inside an If Not IsPostBack conditional block:
Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
imageGridView.DataSource = ImageList
imageGridView.DataBind()
End If
End Sub
In that case, however, we must NOT refer to imageGridView.Rows in Page_Init. Doing so causes the check boxes to lose their selection state (!?!).
From the source code of the GridView (assuming that this source is reliable), I notice that accessing the Rows collection triggers a call to EnsureChildControls which then calls CreateChildControls. I haven't been able to step into the .NET code to see what happens at that point. Calling these methods in the Page_Init event handler may come earlier than expected in the life cycle of the GridView.
By the way, accessing the HeaderRow and the FooterRow properties also triggers a call to EnsureChildControls, and has the same effect on the selection status of the check boxes.

Datapager always marks page 1

I'm facing a problem with two Datapagers associated with a Listview. This is my page:
<asp:DataPager ID="PagerTop" runat="server" PagedControlID="pp" QueryStringField="page" PageSize="30"></asp:DataPager>
<asp:ListView ID="pp" runat="server" ItemPlaceholderID="holder" EnableViewState="true" OnPagePropertiesChanging="PagePropertiesChanging">
...
</asp:ListView>
<asp:DataPager ID="PagerBottom" runat="server" PagedControlID="pp" QueryStringField="page" PageSize="30"></asp:DataPager>
and the code behind is as follows
Private Sub Page_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreRender
Dim MyData As List(Of Product)
MyData = ResultsManager.GetResults()
pp.DataSource = MyData
pp.DataBind()
End Sub
Private Sub PagePropertiesChanging(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.PagePropertiesChangingEventArgs)
PagerTop.SetPageProperties(e.StartRowIndex, e.MaximumRows, False)
PagerBottom.SetPageProperties(e.StartRowIndex, e.MaximumRows, False)
pp.DataBind()
End Sub
When I change the page, the listview is updated and shows the results corresponding with the indicated page, and PagerTop shows the selected page. That's how they are supposed to work. But PagerBottom is stucked on page 1 and never changes!
It doesn't matter which pager I click, PagerTop always works and PagerBottom always stays at page 1.
I'm running out of brilliant ideas... what can be wrong here?
a very good example is given here
http://www.c-sharpcorner.com/uploadfile/nipuntomar/datapager-in-Asp-Net-3-5/
just place another data pager with different id without any change. i have tried and worked fine for me.

session variable set by checkbox not being stored/shared from page to page

I have a listview that's showing a long list. Each item has the ability to be 'hidden' or not. I want a checkbox to either show all the list, or not to show the hidden ones. The idea is that users will hide the older items they don't want to see any more, but may want to see at some point. I want to store the value of this decision in a session variable so if the user navigates to another page, then comes back, the ShowAllCheckbox will pre-populate to what the user has previously decided. Everything is working good, except i can't get the session variable to keep. It keeps going back to False. This is what I have:
aspx page:
Show Hidden: <asp:Checkbox ID="ShowHiddenCheckbox" runat="server" AutoPostBack="True" OnCheckedChanged="ShowHiddenCheckboxChange" />
...
<asp:ListView ...>
<!-- this list works fine, and pulls the correct records -->
aspx.vb page:
Protected Sub ShowHiddenCheckBoxChange(ByVal sender As Object, ByVal e As EventArgs)
' toggle the values
Dim CheckBoxField As CheckBox = TryCast(sender, CheckBox)
If CheckBoxField.Checked Then
Session("ShowHiddenRotations") = False
Else
Session("ShowHiddenRotations") = True
End If
End Sub
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
'if i navigate to another page, and come back to this one, this comes back as "False". I don't understand how it could be reset to False.
Response.Write( "Session: " & Session("ShowHiddenRotations") )
'when page loads check if session variable has been set to show/hide the hidden rotations
If Session("ShowHiddenRotations") Then
If Session("ShowHiddenRotations") = True Then
'update sql query on select statement to show the hidden rotations
'update checkbox to show it as checked
ShowHiddenCheckBox.Checked = True
Else
ShowHiddenCheckBox.Checked = False
End If
Else
'not checked by default (ie don't show hidden)
ShowHiddenCheckBox.Checked = False
End If
End Sub
The Session variable always reverts back to False when i navigate to another page and come back to this one. My understanding of session variables was that they would pass their values from one page to another until the user closes the browser. Maybe there's another way of doing this, or something simple I'm missing. Any help is much appreciated! Thanks!
Is session-state enabled on your site? It can be disabled in a couple of different way, on a page level or even in web.config.
You should also be aware the Page_Load event fires for every request, before the check-box auto-postback happens.
I'm also a little confused as to what you're trying to store: I assume every row has a check-box, but it seems you're trying to store the set/not-set value in a single session variable. How do you differentiate which have been selected, and which ones hasn't? :)
Update:
Okay, let's try a clean the code up a little bit. First create a property to access the session value:
Private Property ShowHiddenRotations As Boolean
Get
If Not Session("ShowHiddenRotations") Is Nothing Then
Return CType(Session("ShowHiddenRotations"), Boolean)
Else
Return False
End If
End Get
Set(value As Boolean)
Session("ShowHiddenRotations") = value
End Set
End Property
If you're using that value on other pages, I would recommend moving it to a seperate class.
Then we can reduce your other code to something closer to this:
Protected Sub ShowHiddenCheckBoxChange(ByVal sender As Object, ByVal e As EventArgs)
ShowHiddenRotations = ShowHiddenCheckbox.Checked
End Sub
And ...
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If not Page.IsPostBack
' Load your data, better stick it in a seperate sub...
ShowHiddenCheckBox.Checked = ShowHiddenRotations
else
' This section is executed BEFORE any control methods are run, i.e. ShowHiddenCheckBoxChange
end if
End Sub
I'm guessing your problem is really just the order of how things are called in your page. What happens when you debug through it?

client side script for treeview events

I have a Treeview with "populateOnDemand" set to true. I want this treeview to keep its state (nodes expanded/collapsed) from one page to another. Viewstate doesn't work because the treeview is different for each page. Here is my code at the moment.
ASPX page :
<asp:TreeView
ID="arbre"
EnableViewState="true"
PopulateNodesFromClient="true"
runat="server" />
Code behind :
Protected Sub arbre_TreeNodeCollapsed(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.TreeNodeEventArgs) Handles arbre.TreeNodeCollapsed
CType(Session("listeNoeudsOuverts"), Hashtable)(e.Node.Value) = True
End Sub
Protected Sub arbre_TreeNodeExpanded(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.TreeNodeEventArgs) Handles arbre.TreeNodeExpanded
CType(Session("listeNoeudsOuverts"), Hashtable)(e.Node.Value) = False
End Sub
Protected Sub arbre_TreeNodePopulate(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.TreeNodeEventArgs) Handles arbre.TreeNodePopulate
// code to populate nodes
CType(Session("listeNoeudsOuverts"), Hashtable)(e.Node.Value) = True
End Sub
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Session("listeNoeudsOuverts") Is Nothing Then
Session("listeNoeudsOuverts") = New Hashtable()
End If
// other stuff
End Sub
This works well, buf I wish I could avoid the postback everytime the user expands or collapses a node. I know I can set EnebleClientScript to true and manage the events client side in Javascript but I won't be able to use my session variable anymore. Is there a way to achieve this ?
Thank you
I will answer myself to a certain extent.
I've done some tests and research, EnableClientScript is true by default, and indeed means that expand and collapse actions are processed client side, by Javascript code that is automaticalt generated by the .Net framework. You can't edit it.
Apparently, if you need to add custom actions when a user expands or collapses anode, you have to use TreeNodeExpanded and TreeNodeCollapsed events, like i did above, and can't avoid postbacks because they are triggered server-side.

ASP.NET, VB: how to access controls inside a FormView from the code behind?

I have a checkbox and a panel inside of a FormView control, and I need to access them from the code behind in order to use the checkbox to determine whether or not the panel is visible. This is the code that I originally used, but since I put the controls inside of the FormView, it no longer works.
Protected Sub checkGenEd_CheckedChanged(ByVal sender As Object, _
ByVal e As System.EventArgs)
If checkGenEd.Checked = True Then
panelOutcome.Visible = True
Else
panelOutcome.Visible = False
End If
End Sub
I've started to figure this out based on other questions I looked up on here, but all of them were in C# instead of VB, so this is as far as I got:
Protected Sub FormView1_DataBound(ByVal sender As Object, ByVal e As System.EventArgs) Handles FormView1.DataBound
If FormView1.CurrentMode = FormViewMode.Edit Then
End If
End Sub
So yeah I'm not sure exactly how to finish it. I'm sorry, this might be pretty basic, but I'm new at this and any help would be appreciated!
EDIT: here's my code now:
Protected Sub FormView1_DataBound(ByVal sender As Object, ByVal e As System.EventArgs) Handles FormView1.DataBound
If FormView1.CurrentMode = FormViewMode.Edit Then
CheckBox checkGenEd = formview1.FindControl("checkGenEd");
Panel panelOutcome = formview1.FindControl("panelOutcome");
End If
End Sub
It's also saying that checkGenEd and panelOutcome are not declared.
EDIT: I changed my code to this but it still doesn't work:
Protected Sub FormView1_DataBound(ByVal sender As Object, ByVal e As System.EventArgs) Handles FormView1.DataBound
If FormView1.CurrentMode = FormViewMode.Edit Then
Dim checkGenEd As CheckBox = FormView1.FindControl("checkGenEd")
Dim panelOutcome As Panel = FormView1.FindControl("panelOutcome")
If checkGenEd.Checked = True Then
panelOutcome.Visible = True
Else
panelOutcome.Visible = False
End If
End If
End Sub
There aren't any errors anymore, but nothing happens when I click the checkbox. I think there needs to be some kind of event to trigger it but I don't know how you can put an event handler inside of an event handler.
With FormView, you have to use find control, as in:
CheckBox checkGenEd = (CheckBox)formview1.FindControl("checkGenEd");
Panel panelOutcome = (Panel)formview1.FindControl("panelOutcome");
You cannot reference a control directly by ID.
HTH.
In VB you need use Directcast
Dim chk As Checkbox = DirectCast(Me.FormView1.FindControl("checkgen"), Checkbox)
FormView has its own event framework. A normal control within a FormView won't generate the postback events you are looking for. I initially made the same mistake. I wanted, like you, to generate some kind of postback that could be intercepted at the server end. Once we get back to the server we can look at the values in checkboxes etc depending on whatever business rules apply. This is what I did.
First of all put all relevant controls within an
<EditItemTemplate>
section within the FormView. (There are other Template tags that may be more appropriate). To generate the postback have a button (for example) like the one below. (This has to be within the EditItemTemplate section as well):
<asp:linkbutton id="UpdateButton"
text="Update"
commandname="Update"
runat="server"/>
You can intercept this at the server with the FormView event ItemCommand. For example:
Private Sub FormView1_ItemCommand(sender As Object, e As System.Web.UI.WebControls.FormViewCommandEventArgs) Handles FormView1.ItemCommand
'your code here
End Sub
Once you are back at the server you can then start looking at the various controls to see what they hold, using findControl if necessary. The button command shown above is an example so you might want to use another control.

Resources