Implementing clickable page numbers in search result - asp.net

Classic scenario: Take user input, get a search-result and display it in pages to the user. I then need to display buttons for First, Next, Previous etc, and I maintain the users current page in viewstate. All is good, works fine.
Then I need to implement clickable page numbers, ie. 1-2-3-4-5-6 etc.
Rendering them is simple. I generate a linkbutton control at runtime, add commandargument with the page number and add a handler to it, so click are to be handled. Then I add it to a placeholder, and it is displayed as expected.
But then... If I did not already have a shaved head, I would be pulling out my hair getting the events to fire as expected every time.
How should I do this, so my events are always wired up and able to fire when the paging-linkbuttons are called?
Below is the important parts of the code, some pseudo to make it (hopefully) easier to understand, what I am doing.
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not Page.IsPostBack Then
Search()
End If
End Sub
Sub Search
'Misc databinding stuff, searches and displays results for the page specified in Me.CurrentPage
RenderPagingControls()
End Sub
Sub RenderPagingControls
'loop throug pagenumbers, Build a linkbutton control, add it to a placeholder
AddHandler lbn.Click, AddressOf lbnNumber_Click
lblPageNumbers.Controls.Add(lbn)
...
End Sub
Protected Sub lbnNumber_Click(ByVal sender As Object, ByVal e As EventArgs)
Dim b As LinkButton = CType(sender, LinkButton)
Me.CurrentPage = CInt(b.CommandArgument)
Search()
End Sub
Public Property CurrentPage() As Integer
Get
Dim o As Object = Me.ViewState("CurrentPage")
If o Is Nothing Then
Return 1
Else
Return CType(o, Integer)
End If
End Get
Set(ByVal value As Integer)
Me.ViewState("CurrentPage") = value
End Set
End Property
Protected Sub lbnNumber_Click(ByVal sender As Object, ByVal e As EventArgs)
Dim b As LinkButton = CType(sender, LinkButton)
Me.CurrentPage = CInt(b.CommandArgument)
Search()
End Sub

I'm going to recommend against a LinkButton and recommend Hyperlinks / QueryString parameters instead. For several reasons:
Your page will be much more efficient without the viewstate overhead of a link button.
If these are public facing pages, you'll get better indexing of all the pages if they can be accessed via hyperlinks (and indexed via search engines).
You'll find them much easier to implement. No event management, etc.
You would redefine your CurrentPage method as (hopefully this is correct, I'm better at C# than vb.net):
Public Property CurrentPage() As Integer
Get
Dim o As Object = Me.Request.QueryString("page")
If o Is Nothing Then
Return 1
Else
Return CType(o, Integer)
End If
End Get
End Property
Then just add hyperlinks for each page.
<a href='mypage.aspx?page=1'>1</a> - <a href='mypage.aspx?page=2'>2</a>
etc...
Alternative: If you want to use the LinkButton, you might want to consider putting a single LinkButton in a repeater. Then the only event you have to worry about is the OnItemCommand event. Then no dynamic controls or events. Something like this:
<asp:Repeater ID="rptPages" runat="server" OnItemCommand='doPaging'>
<ItemTemplate>
<asp:LinkButton ID="LinkButton1" runat="server" Text='<%# (Container.DataItem).ToString() %>'
CommandArgument='<%# (Container.DataItem).ToString() %>' />
</ItemTemplate>
<SeparatorTemplate>-</SeparatorTemplate>
</asp:Repeater>
Bind this control to an array (or list) of consecutive Integers (as many are there are pages). Then in your doPaging function (as I call it), check RepeaterCommandEventArgs.CommandArgument to get the page number.

Thanks for the answers, guys. I tried out Austins first, but I must be missing something, because I keep getting the same behavior of link buttons only working every second time... So I gave up on that, and saw the alternative solution with the repeater by Keltex! It is as brilliant as it is simple, and we don't have to worry about any page life-cycle bullshit.
It just really works! ;)
If somebody should need something similar in the future, here is the relevant code behind the scenes:
Sub Search()
...
RenderPagingControls()
End Sub
Sub RenderPagingControls()
Dim pages As New ArrayList
For i As Integer = 1 To Me.PageCount
pages.Add(i)
Next
repPageNumbersTop.DataSource = pages
repPageNumbersTop.DataBind()
repPageNumbersBottom.DataSource = pages
repPageNumbersBottom.DataBind()
End Sub
Public Property CurrentPage() As Integer
Get
Dim o As Object = Me.ViewState("CurrentPage")
If o Is Nothing Then
Return 1
Else
Return CType(o, Integer)
End If
End Get
Set(ByVal value As Integer)
Me.ViewState("CurrentPage") = value
End Set
End Property
Public Property PageCount() As Integer
Get
Dim o As Object = Me.ViewState("PageCount")
If o Is Nothing Then
Return 0
Else
Return CType(o, Integer)
End If
End Get
Set(ByVal value As Integer)
Me.ViewState("PageCount") = value
End Set
End Property
Protected Sub repPageNumbersTop_ItemCommand(ByVal source As Object, ByVal e As System.Web.UI.WebControls.RepeaterCommandEventArgs) Handles repPageNumbersTop.ItemCommand, repPageNumbersBottom.ItemCommand
Me.CurrentPage = CType(e.CommandArgument, Integer)
Search()
End Sub
Private Sub repPageNumbersTop_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.RepeaterItemEventArgs) Handles repPageNumbersTop.ItemDataBound, repPageNumbersBottom.ItemDataBound
If e.Item.ItemType = ListItemType.Item Or e.Item.ItemType = ListItemType.AlternatingItem Then
Dim lbn As LinkButton = CType(e.Item.FindControl("lbnPageNumber"), LinkButton)
If lbn.CommandArgument = Me.CurrentPage.ToString Then
lbn.Enabled = False
End If
End If
End Sub

This code works (sorry it's in C#):
protected void SearchButton_Click(object sender, EventArgs e)
{
//clear the collection!
pnlPageNumber.Controls.Clear();
//simulate search
System.Random rnd = new Random();
//create page buttons
for (int i = 0; i < rnd.Next(3, 15); i++)
{
LinkButton lb = new LinkButton();
pnlPageNumber.Controls.Add(lb);
lb.ID = "btn" + i;
lb.Text = i.ToString();
lb.CommandArgument = i.ToString();
lb.Command += new CommandEventHandler(linkbutton_Command);
//optional literal
pnlPageNumber.Controls.Add(new LiteralControl(" "));
}
ViewState["control#"] = Panel1.Controls.Count;
}
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
//Recreate link buttons
//This is necessary to ensure proper event binding
int count = 0;
if (ViewState["control#"] != null)
count = (int)ViewState["control#"];
for (int i = 0; i < count; i++)
{
LinkButton lb = new LinkButton();
pnlPageNumber.Controls.Add(lb);
lb.ID = "btn" + i; //make sure IDs are the same here and on Search
lb.Command += new CommandEventHandler(linkbutton_Command);
//this is not necessary, but if you do, make sure its in both places
pnlPageNumber.Controls.Add(new LiteralControl(" "));
}
}
}
void linkbutton_Command(object sender, CommandEventArgs e)
{
Response.Write(e.CommandArgument.ToString() + " CLICK<br />");
}

You could use the DataPager control -- the only limitation is you have to use it with the ListView control, but you should be able to represent your data using the ListView control fairly easily because it is very flexible. You can set the DataSource of the ListView control to the result of your data result, whether that be a DataSet, Collection, Array, etc.
To create the paging controls with "first", "last", and page numbers, set up the DataPager like this (where ListView1 is the ID of your ListView control):
<asp:DataPager ID="DataPager1" runat="server"
PagedControlID="ListView1" PageSize="25">
<Fields>
<asp:NextPreviousPagerField FirstPageText="first" ShowFirstPageButton="True"
ShowNextPageButton="False" ShowPreviousPageButton="False" />
<asp:NumericPagerField />
<asp:NextPreviousPagerField LastPageText="last" ShowLastPageButton="True"
ShowNextPageButton="False" ShowPreviousPageButton="False" />
</Fields>
</asp:DataPager>
By design, the DataPager uses the whole result set from the database, but you can improve the performance by caching the result and using that on the subsequent requests.
Hope this helps.

iirc... adding controls dynamically at runtime is a bit tricky. The control tree must be rebuilt during post back... but before viewstate is loaded (not sure when in the page life cycle... but way before page load). So... your problem is that by the time asp.net is trying to figure out your event the actual originating control has not yet been created.

Related

Replace text of ASP Literal in Code Behind

I'm new to ASP and was hoping to get some guidance on how to make my literal accessible in my Code Behind and then change it to the text of a passed in parameter.
I have an resources.ascx file that displays a list of people (pulled from a database). That is working fine and it looks something like this:
Full name
T: (888-888-8888)
F: (888-888-8888)
The problem, however, is that I now want it conditionally say "Toll Free" instead of "F:" for one page.
In the people.aspx page, I'm passing in "Toll Free" to the resource:
<%# Register Src="~/UserControls/resources.ascx" TagName="Resources" TagPrefix="ucResources" %>
<ucResources:Resources ID="Resources1" FaxNumberAlias="Toll Free" runat="server" />
resources.ascx The repeater outputs all the people from the database to the page.
<asp:Repeater ID="Repeater1" runat="server">
<ItemTemplate>
<div class="sectioncontent">
<b><%#Eval("EmployeeFirstName")%> <%#Eval("EmployeeLastName)%></b>
T: <%#Eval("Phone")%>
<br>
<asp:Literal runat="server" ID="FaxNumberLabel">F:</asp:Literal> <%#Eval("Fax")%><br>
</div>
<br />
</ItemTemplate>
In the resources.ascx.vb file, I wanna do something like this but FaxNumberLabel (the literal I declared in resources.ascx) isn't accessible or hasn't been declared.
Public Property FaxNumberAlias() As String
Get
Return _FaxNumberAlias
End Get
Set(ByVal value As String)
_FaxNumberAlias = value
End Set
End Property
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not String.IsNullOrEmpty(_FaxNumberAlias) Then
FaxNumberLabel.Text = _FaxNumberAlias
End If
PopulateRepeater()
End Sub
What am I missing that connects the literal to the code behind?
The problem is that the Literal is inside a Repeater so you may potentially have lots of them. The best way is to access them inside the OnDataItemBound event of your repeaters:
Protected Sub Repeater1_OnDataItemBound(ByVal sender As Object, ByVal e As RepeaterItemEventArgs) Handles Repeater1.OnDataItemBound
If (e.Item.ItemType = ListItemType.Item) Or _
(e.Item.ItemType = ListItemType.AlternatingItem) Then
Dim litFaxNumberLabel As Literal = e.Item.FindControl("FaxNumberLabel")
litFaxNumberLabel.Text = _FaxNumberAlias
End If
End Sub
Note: Excuse any bad syntax, it's been over 4 years since I touched VB!
You can simply use like this -
protected void DataDisplay_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if ((e.Item.ItemType == ListItemType.Item) || (e.Item.ItemType == ListItemType.AlternatingItem))
{
LinkButton lit = (LinkButton)e.Item.FindControl("LinkButton2");
if (lit.Text == "0")
{
int a = Convert.ToInt32(lit.Text);
if (a == 0)
{
if (a == 0)
{
lit.Text = "Your Text";
}
}
}
}
}
In my case, I am using a button (btnRedirect) in each row.
RepeaterItem item = btnRedirect.NamingContainer as RepeaterItem;
var type = item.FindControl("IdUsed") as Literal;
var literalValue = type.Text;

PagedDataSource not showing data in subsequent pages

It's probably something small, but I haven't been figure out why the following isn't working completely. The first time the user submits the search, the first page of search results show up properly. However, when the user tries to navigate by using the Previous and Next Page buttons, the repeater doesn't show the appropriate data from the DataTable.
search.aspx
<asp:Repeater ID="rptSearchResults" runat="server" OnItemDataBound="rptSearchResults_ItemDataBound">
<ItemTemplate>
<div>
<asp:Literal ID="ltlCustName" runat="server" />
</div>
</ItemTemplate>
</asp:Repeater>
search.aspx.vb
Public dtCustomers As DataTable = New DataTable()
Sub Page_Load(ByVal Sender As Object, ByVal E As EventArgs) Handles Me.Load
' Check to see if this is the first time postback-ing to itself.
blnFirstPostBack = (Request.Form("firstpb") = "1")
' When the page first loads, show the search form with search options.
If Not Page.IsPostBack Then
Session("StoredDT") = Nothing
ShowSearchForm()
' Once the form is submitted, show the search results.
Else
Response.Write("DEBUG: Get Data")
If blnFirstPostBack Then
GatherFormData()
dtCustomers = BuildDT()
Session("StoredDT") = dtCustomers
BindData()
ElseIf Not Session("StoredDT") Is Nothing Then
dtCustomers = Session("StoredDT")
End If
End If
End Sub
Sub BindData()
Response.Write("DEBUG: Bind Data")
' At this point, I've checked that the dtCustomers is showing the proper data (e.g., grabbing from session when appropriate).
Dim objPDS As PagedDataSource = New PagedDataSource()
objPDS.DataSource = dtCustomers.DefaultView
objPDS.AllowPaging = True
objPDS.PageSize = intNumPerPage
' I've checked that Me.ViewState("_CurrentPage") gets updated to the correct page.
objPDS.CurrentPageIndex = Me.ViewState("_CurrentPage")
rptSearchResults.DataSource = objPDS
' I'm not sure if the error is here but although the dtCustomers is the proper data, the PagedDataSource and the binding here doesn't seem to play nice.
Call rptSearchResults.DataBind()
End Sub
' Subroutine called when the previous page button is pressed.
Sub GoToPrevPage()
Response.Write("DEBUG: Prev Page")
' Set viewstate variable to the previous page.
Me.ViewState("_CurrentPage") -= 1
BindData()
End Sub
' Subroutine called when the next page button is pressed.
Sub GoToNextPage()
Response.Write("DEBUG: Next Page")
' Set viewstate variable to the next page.
Me.ViewState("_CurrentPage") += 1
BindData()
End Sub
Protected Sub rptSearchResults_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.RepeaterItemEventArgs) Handles rptSearchResults.ItemDataBound
Dim item As RepeaterItem = e.Item
Dim strCustName As String = ""
If (item.ItemType = ListItemType.Item) Or (item.ItemType = ListItemType.AlternatingItem) Then
strCustName = e.Item.DataItem("CustName")
Dim ltlCustName As Literal = CType(e.Item.FindControl("ltlCustName"), Literal)
ltlCustName.Text = strCustName
End If
End Sub
Sample Page 1 (shows proper data):
DEBUG: Get Data
DEBUG: Bind Data
Laurence Clinton
John Doe
Sean King
Jane Smith
Sample Page 2 (does not show proper data but shows enough spaces for the missing data):
DEBUG: Get Data
DEBUG: Next Page
DEBUG: Bind Data
[no name showing here 5]
[no name showing here 6]
[no name showing here 7]
[no name showing here 8]
Please excuse the abbreviated code but the actual code is massive so the simplification is to make it easier to get to the heart of the issue.
Let me know if any of that was unclear or if more code is required. Thanks in advance!
Update 2/19/2013:
So after fiddling with the code a bit, I think the error happens in the repeater subroutine. The original literal inside of the repeater works now. For some reason I don't think it worked before but it works fine now. The problem is when we go a step further using a custom control inside of the repeater subroutine. It seems that the information doesn't get passed into the control. The control gets called properly because supporting HTML found only within the control gets outputted properly but the customer information that we try to pass into the control doesn't get inside. Here is the modified code:
search.aspx
<asp:Repeater ID="rptSearchResults" runat="server" OnItemDataBound="rptSearchResults_ItemDataBound">
<ItemTemplate>
<div>
<asp:Literal ID="ltlCustName" runat="server" />
<Acme:CustInfo ID="AcmeCustInfo" runat="server" />
</div>
</ItemTemplate>
</asp:Repeater>
search.aspx.vb
Protected Sub rptSearchResults_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.RepeaterItemEventArgs) Handles rptSearchResults.ItemDataBound
Dim item As RepeaterItem = e.Item
Dim strCustName As String = ""
If (item.ItemType = ListItemType.Item) Or (item.ItemType = ListItemType.AlternatingItem) Then
strCustName = e.Item.DataItem("CustName")
' This literal properly shows the customer name on subsequent pages so the customer name reaches this point properly.
Dim ltlCustName As Literal = CType(e.Item.FindControl("ltlCustName"), Literal)
ltlCustName.Text = strCustName
' This control gets called properly but strCustName doesn't
' get passed into the control. The control works fine for the
' first page but subsequent pages do not work. Also, the
' control works fine when PagedDataSource is not used.
Dim AcmeCustInfo As CustInfo = CType(e.Item.FindControl("AcmeCustInfo"), CustInfo)
AcmeCustInfo.CustName = strCustName
End If
End Sub
Per Request from Ann
Here is the code for CustInfo. Needless to say, a lot of the fluff has been stripped out to focus on the issue but if anything is missing that will be useful, please let me know and I'll update the example accordingly.
custinfo.ascx
<%# Control Language="VB" AutoEventWireup="false" CodeFile="CustInfo.ascx.vb" Inherits="CustInfo" %>
<div style="border: 1px solid black;">
<asp:Literal ID="ltlCustName" runat="server" />
</div>
custinfo.ascx.vb
Imports System
Imports System.Web
Imports System.Web.Security
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.Web.UI.HtmlControls
Imports System.Configuration
Imports System.Data
Imports System.Data.SqlClient
Imports System.IO
Imports System.Web.HttpUtility
Partial Class CustInfo
Inherits System.Web.UI.UserControl
Private _CustName As String = ""
Public Property CustName() As String
Get
Return _CustName
End Get
Set(value As String)
_CustName = value
End Set
End Property
Public Sub Page_Load(ByVal Sender As Object, ByVal E As EventArgs) Handles Me.Load
Dim ltlCustName As Literal = CType(FindControl("ltlCustName"), Literal)
ltlCustName.Text = "<b>Name: " & CustName & "</b>"
End Sub
End Class
I'm not a PagedDataSource expert, but I've used user controls extensively.
You're setting the value of the literal in your CustInfo control in the Load subroutine. If I'm not mistaken, that's going to get called when the CustInfo control is created. That would happen before OnItemDataBound is called, so -- I think -- the Load subroutine will happen and the value of the literal be set (to an empty string) before you assign the value of the CustName property. To fix this, try setting the value of the literal later, such as in the PreRender subroutine.
It looks like you're binding on every postback, so the following shouldn't be an issue, but if you aren't, here are some thing that might affect you:
ItemDataBound only runs if you re-bind. If you have ViewState turned on for your repeater, the controls will be recreated on postback, and ItemCreated would run, but ItemDataBound wouldn't. So you'd never re-set your CustName property. And this would matter because ...
... your CustName property has a variable as a backing store: it isn't preserved in ViewState. So when the user control is recreated, the CustName property you previously set won't be there anymore: your literal's contents will be set to the empty string that is the default value of the CustName property.
Those two together would give exactly the behavior you've described. But since it looks like you do bind on every postback (eventually) that may not be the issue. I'm including it for completeness.

asp.net: Attributes.Add is to save - and how do i read them?

I'm adding in asp.net (vb) an attribute to an image-button:
imgButton.Attributes.Add("myAttr", "true")
This is working fine.
Now i want to read the attribute, but it does not work:
If imgButton.Attributes("myAttr") = "true" Then
..doSomething..
How do I get this thing working?
Edit
I have an asp.net repeater.
In this repeater i have in each itemtemplate two image buttons.
If I'm clicking on an imagebutton, the other imagebutton in this row changes it's URL.
I want that this URL is saved, after clicking on another row's imagebutton.
So I'm adding in the repeater event
ItemCommand
Dim imgButton As ImageButton
If e.CommandName = "imgBtn1" Then
imgButton = CType(e.Item.FindControl("imgBtn1"), ImageButton)
imgButton.ImageUrl = "myURL"
imgButton.Attributes.Add("myAttr1", "true")
ElseIf e.CommandName = "imgBtn2" Then
imgButton = CType(e.Item.FindControl("imgBtn2"), ImageButton)
imgButton.ImageUrl = "myURL"
imgButton.Attributes.Add("myAttr2", "true")
End If
In the Page Load event I'm adding:
If Page.IsPostBack Then
Dim countRepeaterItems As Integer = myRepeater.Items.Count
Dim imgButton As ImageButton
For i As Integer = 0 To countRepeaterItems - 1
imgButton = CType(myRepeater.Items(i).FindControl("imgBtn1"), ImageButton)
If imgButton.Attributes.Item("myAttr1") = "true" Then
imgButton.ImageUrl = "myURL"
End If
imgButton = CType(myRepeater.Items(i).FindControl("imgBtn2"), ImageButton)
If imgButton.Attributes.Item("myAttr2") = "true" Then
imgButton.ImageUrl = "myURL"
End If
Next
End If
While debugging, it still skips everything, because all Attributes are empty (but actually they are not)!
Looks like for VB it should be:
If imgButton.Attributes.Item("myAttr") = "true" Then
EDIT: original answer was for C#:
Should be square brackets on the reads:
If imgButton.Attributes["myAttr"] = "true" Then
http://msdn.microsoft.com/en-us/library/kkeesb2c.aspx#Y0
I guess! May be you have (turn off the viewstate) set EnableViewState=False to the imgButton.
Take a look at this sample:
Markup:
<form id="form1" runat="server">
<asp:Button ID="Button1" runat="server" Text="Button" />
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
</form>
Code:
Protected Sub Button1_Click(sender As Object, e As System.EventArgs) Handles Button1.Click
If Label1.Attributes("myAttr") = "true" Then
Label1.Attributes.Add("myAttr", "false")
Label1.Text = "false is set"
Else
Label1.Attributes.Add("myAttr", "true")
Label1.Text = "true is set"
End If
End Sub
Protected Sub Page_Load(sender As Object, e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
Label1.Attributes.Add("myAttr", "true")
End If
End Sub
EDIT:
May be typo in ItemCommand event code.
imgButton.ImageUrl = "myURL"
imgButton.Attributes.Add("myAttr1", "true") '<----- Correction
Addressing the issue of not finding the attributes set in your page load.
I am not entirely clear on what you are trying to accomplish, but it seems likely that you are running into a problem with the order that events execute. On a post back, the page load event executes, then the event handler for the control causing the post back. If your image button causes the post back, then the attribute is not being set until after the page load event has already completed. However, assuming you are using viewstate, your attribute should be persisted and detected on the following post back.
If this is what is happening to you, then one possible way around it would be to move the code from your page load event to the page pre render event. Pre render occurs after the control's post back events have been handled, and it is one of the last points where you can hook in and make changes to your content before it is committed to viewstate.

Iterate over rows/checkboxes in a RadGrid

I have a Telerik RadGrid with a GridTemplateColumn that contains a checkbox, as follows:
<telerik:GridTemplateColumn HeaderText="MINE" UniqueName="MyTemplateColumn">
<ItemTemplate>
<asp:CheckBox id="MyCheckBox" runat="server"></asp:CheckBox>
</ItemTemplate>
</telerik:GridTemplateColumn>
I want to set the box to be "checked" based on a value read from the database. I could handle the ItemDataBound event and read the database when each row is bound, but that results in n lookups. Instead, I want to handle DataBound, and then set all the values at once. So, in that method, I want code like this:
// read all values from database first, then...
foreach(var chkbox in MyRadGrid.MasterTableView.Columns.FindByUniqueName("MyTemplateColumn").FindControl("MyCheckBox")) {
chkbox.Checked = oneValue;
}
That doesn't work, because FindControl isn't a method of GridColumn, and it won't generate an iterable list of the checkboxes. What is the correct way to iterate through the checkboxes in the template column? Thanks!
Telerik got back to me on their forums with the answer, as follows:
foreach (GridDataItem item in MyRadGrid.MasterTableView.Items)
{
CheckBox chk = (CheckBox)item.FindControl("MyCheckBox");
// Set the value here
}
Hope this is useful for someone!
I am having the same issue.. this was how I did it..
'Created a local hashtable to use now and otherwise
Private _GroupMembers As New Hashtable
'Loaded it up on page load
Private Function GetMembers() As Boolean
Try
Dim da As New DataAccess
Dim ht As New Hashtable
Dim i As Int16 = 0
ht.Add("CAC", Session("cac"))
ht.Add("GroupID", _GroupID)
If da.GetData("rap_spGetGroupMemberList", ht) = True Then
If da.SQLDataRows.HasRows Then
While da.SQLDataRows.Read()
i = i + 1
_GroupMembers.Add(i, da.SQLDataRows("UserID"))
End While
End If
da.SQLDataRows.Dispose()
End If
da = Nothing
Catch ex As Exception
Console.Write(ex.Message)
End Try
End Function
'Check for contains
Protected Sub RadGrid2_ItemDataBound(ByVal sender As Object, ByVal e As Telerik.Web.UI.GridItemEventArgs) Handles RadGrid2.ItemDataBound
Try
If e.Item.IsDataBound Then
If Not e.Item.DataItem("UserID") Is Nothing Then
If Not IsDBNull(e.Item.DataItem("UserID")) Then
Dim UserID As Long = e.Item.DataItem("UserID")
If _GroupMembers.ContainsValue(UserID) Then
e.Item.Selected = True
End If
End If
End If
End If
Catch ex As Exception
Console.Write(ex.Message)
End Try
End Sub

Incrementing variables in ASP.net on button click

I am new to asp.net. I am creating a ASP.net website using VB.net. So here's my problem
Dim myCounter as Integer = 0
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.Web.UI.ImageClickEventArgs) Handles Button1.Click
myCounter = myCounter + 1
Label1.Text = myCounter.ToString()
end Sub
As expected I always get Label Text as 0 each time click the button. How to I create global variable and increment it.
Every time the page posts back, it is essentially starting over from scratch - anything initialized to 0, for example, will be zero again. This is because the server doesn't know anything about the last time the page ran - all it knows is you clicked a button which submits a form to that page, so it creates another instance of the page and starts again.
If you need to persist a value across postbacks, the standard method is to use ViewState:
Public Property MyCounter() As Integer
Get
Dim val As Object = ViewState("MyCounter")
Return If(val IsNot Nothing, CInt(val), 0)
End Get
Set(ByVal value As Integer)
ViewState("MyCounter") = value
End Set
End Property
It's also possible to use Session, which will persist the value across all pages and requests for the life of the user's session. For that to work, you can use the same sample above, replacing ViewState with Session.
Put this code in your Button Click Event
int count=0;
count++;
ViewState["count"] = Convert.ToInt32(ViewState["count"]) + count;
Label1.Text = ViewState["count"].ToString();
#Rex M's suggestion for using Viewstate is good.
If the counter is not sensitive information or something you're worried about someone tampering with., here's an easier idea:
You can also use an <asp:HiddenField> and store the value there. Then it will persist between postbacks and you can increment it each time..
Her's another method that doesn't use hidden field, viewstate, session or cache
Probably not something very 'safe' but probably saves you some time.
Assuming initial Label1.Text = 0
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.Web.UI.ImageClickEventArgs) Handles Button1.Click
Label1.Text = (Integer.Parse(Label1.Text) + 1).ToString()
end Sub
your page class gets recreated on each request... so myCounter won't exist the next time.
you can either
make myCounter static (not a great idea)
put it in the Application, Session, or Cache collection
depends on what you're trying to do
You can use view count :---
Code on event of button_click..
ViewState["count"] = Convert.ToInt32(ViewState["count"])+1;
Label2.Text = "This button has been clicked " + ViewState["count"].ToString() + " times";
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
ViewState["Count"] = 0;
}
}
protected void btnCount_Click(object sender, EventArgs e)
{
ViewState["Count"] = (int)(ViewState["Count"]) + 1;
lblCount.Text = "Page Visited " +ViewState["Count"].ToString() +" times !";
//Response.Write(ViewState["Count"].ToString());
}

Resources