client side script for treeview events - asp.net

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.

Related

Setting button invisible with event not working

I have a Visual Basic Project where I have a page(Parent.aspx) with a user control inside(ChildForm.ascx), the user control have a checkboxlist where if the selection is changed I cause a postback and send an event
Protected Sub checkBoxList_checked(ByVal sender As Object, ByVal e As EventArgs) Handles checkBoxList.SelectedIndexChanged
RaiseEvent MyEvent(sender, e)
End Sub
to make a button invisible on the Parent view
Protected Sub ChildForm_MyEvent(ByVal sender As Object, ByVal e As EventArgs) Handles ChildForm.MyEvent
If condition Then
btnSave.Visible = False
Else
btnSave.Visible= True
End If
End Sub
When I debug I see the breakpoint hitting all the lines of code and the condition apply as intended, but the button is not hidden, I dont know why if is setting the correct value it never refreshes the Parent page to show the changes, even if it does cause a postback.
Please help
Check your page load events (load, prerender, prerenderComplete) to make sure you are not setting the visibility property in there. if you are, you may need to use
"If not IsPostBack"

How To Pass Control As A Variable

This is one of those problems which seems like it should have a simple solution but I can't work out what it is!
How can I pass a control from one sub to another if the first sub doesn't actually call the second? For example, where btnChangeText is in a panel that has a ModalPopupExtender called mpExample, and therefore isn't usually visible:
Protected Sub btnChangeText_Click(sender as object, e as EventArgs) Handles btnChangeText.Click
<SpecifiedTextBox>.Text = "Hello"
End Sub
And then on the main page, visible at all times, is a button associated with each textbox. In this example, it's textbox15:
Protected Sub btnChangeTextBox15_Click(sender as object, e as EventArgs) Handles btnChangeTextBox15.Click
<Set TextBox15 as variable>
mpExample.Show()
End Sub
I know it's a silly example - believe me when I say that the real application I want to make of this actually makes sense! But the point is that I want to somehow store the name of the control to be updated by the first sub when the second sub is run.
If I was calling the first sub from the second it'd be easy, I'd just pass it as an argument, but I'm not. The first sub is called from a button click and is an independent action from the running of the second sub.
I don't seem to be able to use a session variable (my first thought) because I can't find any way to store the control name as a string and then convert it back to an actual control when the first sub runs. That'd be the easiest answer if somebody could tell me how to do it.
One approach would be to store the control's ID as a string in a Session variable, and then use the FindControl method to grab the control in your 2nd Click event.
Protected Sub btnChangeTextBox15_Click(sender as object, e as EventArgs) Handles btnChangeTextBox15.Click
Session("currentTextBox") = TextBox15.ID
mpExample.Show()
End Sub
Protected Sub btnChangeText_Click(sender as object, e as EventArgs) Handles btnChangeText.Click
Dim currentTextBox As TextBox
currentTextBox = CType(Page.FindControl(Session("currentTextBox")),TextBox)
currentTextBox.Text = "Hello"
End Sub
Note that if your TextBox15 control is inside some kind of container (a Panel or something), you'll need to use that container's FindControl method, rather than Page.FindControl.
Another approach is to store the TextBox itself in a Session variable, and then pull that out to set the text in your other method. Note that this only works if the methods are both called in the same request (which doesn't sound like it would work for your use-case). Here's what that would look like:
Protected Sub btnChangeTextBox15_Click(sender as object, e as EventArgs) Handles btnChangeTextBox15.Click
Session("currentTextBox") = TextBox15
mpExample.Show()
End Sub
Protected Sub btnChangeText_Click(sender as object, e as EventArgs) Handles btnChangeText.Click
Dim currentTextBox As TextBox
currentTextBox = CType(Session("currentTextBox"), TextBox)
currentTextBox.Text = "Hello"
End Sub

Page_Load if statement fires regardless

Is there any reason why an if then statement would fire regardless:
Its inside my Page_load:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim a As New Clicks
If Request.QueryString("u") IsNot Nothing Then
a.Click(Request.QueryString("u"), Request.ServerVariables("REMOTE_ADDR"), Request.ServerVariables("HTTP_USER_AGENT"))
Response.Redirect(urls.GetURL(Request.QueryString("u")))
End If
End Sub
As a result, I am get 126 instances of a.Click per page load when "u" isnt present?
I have tried to move to other Page Events but same result
Created a workaround by encasing if statement in the original if statement to capture the unwanted items.
Not the perfect solution but is working

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.

DataPager ceases to work when PageSize is set in code

I have a standard ASP.Net DataPager with a standard ListView (using a DataTable as a data source).
When I set PageSize="24" in the design code:
<asp:DataPager runat="server" ID="DataPager1" PagedControlID="ListView1" QueryStringField="page" PageSize="24" >
the paging works as advertised.
However, when I then change that in code, in the Page_Load, eg:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
DataPager1.PageSize = 48
End Sub
the paging ceases to work completely, while the initial loaded data set is indeed 48 items.
I can't see anything in the code which would affect this, so I'm wondering if I'm missing something - should I be changing something else?
Regards
Moo
Protected Sub DataPager1_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles DataPager1.Init
DataPager1.PageSize = 48
End Sub
I managed to get this working by setting the page size property in the init event for the datapager.
This sort of error I usually find is a data-binding issue... either binding when you shouldn't, or not re-binding when appropriate. Hard to tell from your little snippet of code.
I am unfamiliar with the DataPager object, but I suspect it must rebind the data when you set the PageSize. If so, then every time the page loads it is re-binding and you are losing events. Have you tried this?
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack
DataPager1.PageSize = 48
End If
End Sub

Resources