I'm trying to get an alphabet pager working in GridView. It does work, but only one letter shows up in the repeater that I'm using to show the letters. I've read other posts and looked at my code and it seems like it should be working, but it's not.
Any help would be appreciated.
Here is my html
<asp:Repeater ID="rptAlphabets" runat="server">
<ItemTemplate>
<asp:LinkButton ID="lnkBtn1" runat="server" Text='<%#Eval("Value")%>' Visible='<%# Convert.ToBoolean(Eval("Selected"))%>' OnClick="Alphabet_Click"/>
<asp:Label ID="lblAlpha" runat="server" Text='<%#Eval("Value")%>' Visible='<%# Convert.ToBoolean(Eval("Selected"))%>' />
</ItemTemplate>
</asp:Repeater>
Here is my code behind
Private Sub GenerateAlphabets()
Dim alphabets As New List(Of ListItem)()
Dim alphabet As New ListItem
alphabet.Value = "ALL"
alphabet.Selected = alphabet.Value.Equals(ViewState("CurrentAlphabet"))
alphabets.Add(alphabet)
For i As Integer = 65 To 90
alphabet = New ListItem()
alphabet.Value = [Char].ConvertFromUtf32(i)
alphabet.Selected = alphabet.Value.Equals(ViewState("CurrentAlphabet"))
alphabets.Add(alphabet)
Next
rptAlphabets.DataSource = alphabets
rptAlphabets.DataBind()
End Sub
I'm using most of the code from an aspsnippets method.
EDIT :
I'm calling the GenerateAlphabets from my Page_Load
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Try
ClearMessages()
If Not IsPostBack Then
ViewState("CurrentAlphabet") = "ALL"
Me.GenerateAlphabets()
BindGrids()
BindDropDownListBoxes()
End If
Catch ex As Exception
Me.HandleError(ex)
End Try
End Sub
Change your LinkButton code like this.
<asp:LinkButton ID="lnkBtn1" runat="server"
Text='<%#Eval("Value")%>'
Visible='<%# Convert.ToBoolean(Eval("Selected")) = False %>'
OnClick="Alphabet_Click"/>
Reason: You are hiding all LinkButtons that are not currently selected. You should be showing them instead.
Related
I'm attempting to use Controls.AddAt(), but it apparently breaks controls at later indexes:
Here's my minimal example:
Aspx put in a form:
<asp:DropDownList runat="server" ID="ddl" />
<asp:Button Text="text" runat="server" OnClick="Unnamed2_Click" />
Code Behind:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
ddl.Items.Add("Click the button")
'Controls.Add(New HyperLink) 'Works fine, but is put at end of collection.
'Controls.AddAt(2 ,New HyperLink) 'Is also safe but I wanted the control first
Controls.AddAt(0, New HyperLink) 'ddl loses it's item after postback
End If
End Sub
On the first postback of the page after calling AddAt, the DropDownList loses it's item. It doesn't matter what kind of control I add even HTMLControls. Viewstate is not disabled.
How do I dynamically add controls without breaking others?
If you used a PlaceHolder to add your HyperLink into, it would not mess up the rest of the page:
<asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
<asp:DropDownList ID="ddl" EnableViewState="true" runat="server" />
<asp:Button ID="bn1" Text="text" OnClick="Unnamed2_Click" runat="server" />
With code like
Protected Sub Unnamed2_Click(sender As Object, e As EventArgs) Handles bn1.Click
Dim newItem = "Click the button" & DateTime.Now.ToString("HH:mm:ss")
ddl.Items.Add(newItem)
ddl.SelectedIndex = ddl.Items.Count - 1
PlaceHolder1.Controls.Add(New HyperLink With {.ID = "hyp", .Text = "Hyperlink here"})
End Sub
And always give your asp:Controls an ID if they take one.
I'm trying to make a tabbed menu for the asp.net website I'm working on. One of the pre-requisite is obviously to color the current tab differently, so the user can know on which tab is currently is.
To do this, I made this method in my code-behind:
Protected Function GetCssClass(ByVal ctrl As LinkButton) As String
If ctrl.ID = currentLink Then
Return "current"
Else
Return String.Empty
End If
End Function
and I call the method like this in my aspx page:
<asp:LinkButton ID="LinkButton1" runat="server" PostBackUrl="/Default.aspx" CssClass="<%#GetCssClass(LinkButton1) %>" >Home</asp:LinkButton>
<asp:LinkButton ID="LinkButton2" runat="server" PostBackUrl="/Directory/page1.aspx" CssClass="<%#GetCssClass(LinkButton2) %>" >Page1</asp:LinkButton>
But the method is never hit... As I understand, the method should be called each time the LinkButton is drawn...
Does someone have an idea why?
Thanks in advance !
Edit: Just as a precision, all this code is in the masterpage.
Edit2: Here are the changes I made according to Quagland's suggestion.
In the aspx masterpage:
<asp:HiddenField ID="currentLink" runat="server" />
<asp:LinkButton ID="LinkButton1" runat="server" PostBackUrl="/Default.aspx" OnClick="LinkButton_Click" OnPreRender="LinkButton_PreRender" >Home</asp:LinkButton>
<asp:LinkButton ID="LinkButton2" runat="server" PostBackUrl="/OtherDirectory/Page1.aspx" OnClick="LinkButton_Click" OnPreRender="LinkButton_PreRender" >Page1</asp:LinkButton>
<asp:LinkButton ID="LinkButton3" runat="server" PostBackUrl="/OtherDirectory/Page2.aspx" OnClick="LinkButton_Click" OnPreRender="LinkButton_PreRender" >Page2</asp:LinkButton>
<asp:LinkButton ID="LinkButton4" runat="server" PostBackUrl="/OtherDirectory/Page3.aspx" OnClick="LinkButton_Click" OnPreRender="LinkButton_PreRender" >Page3</asp:LinkButton>
And in the code behind:
Protected Sub LinkButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles LinkButton1.Click, LinkButton2.Click, LinkButton3.Click, LinkButton4.Click, LinkButton5.Click, LinkButton6.Click, LinkButton7.Click, LinkButton8.Click
Dim lnk As LinkButton = CType(sender, LinkButton)
currentLink.Value = lnk.ID
End Sub
Protected Function GetCssClass(ByVal ctrl As LinkButton) As String
If ctrl.ID = currentLink.Value Then
Return "current"
Else
Return String.Empty
End If
End Function
Protected Sub LinkButton_PreRender(ByVal sender As Object, ByVal e As EventArgs) Handles LinkButton1.PreRender, LinkButton2.PreRender, LinkButton3.PreRender, LinkButton4.PreRender, LinkButton5.PreRender, LinkButton6.PreRender, LinkButton7.PreRender, LinkButton8.PreRender
Dim lnk As LinkButton = CType(sender, LinkButton)
lnk.CssClass = GetCssClass(lnk)
End Sub
The problem is now that the click event is not always fired. On first click, nothing happens, but on second click on a tab, the click event is correctly triggered. Any clue ?
Edit3: Could it be that the value stored in the hidden field is reset each time the masterpage is reloaded (I mean, each link points to a couple masterpage + content page) ?
You need to use <%= ... %> (i.e. replace # with =).
The hash form is used with data binding, you want to just create output.
For .NET 4 prefer <%: ... %> (use a colon) to automatically do HTML encoding.
I have quickly tested a solution that might work for you. I'm just not sure where your 'currentlink' variable comes from. I have implemented it as a hidden field here.
In Masterpage.aspx:
<asp:HiddenField ID="currentLink" runat="server" />
<asp:LinkButton ID="LinkButton1" runat="server">Home</asp:LinkButton>
<asp:LinkButton ID="LinkButton2" runat="server">Page1</asp:LinkButton>
In code behind:
use your original GetCssClass function add this:
Protected Sub LinkButton_PreRender(ByVal sender As Object, ByVal e As System.EventArgs)
Handles LinkButton1.PreRender, LinkButton2.PreRender
Dim lnk As LinkButton = CType(sender, LinkButton)
lnk.CssClass = GetCssClass(lnk)
End Sub
I have put it in PreRender because i was using the LinkButton click events to set the hidden field value (and Click happens after Load but before PreRender):
Protected Sub LinkButton_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles LinkButton1.Click, LinkButton2.Click
Dim lnk As LinkButton = CType(sender, LinkButton)
currentLink.Value = lnk.ID
End Sub
also, if there are numerous Linkbuttons, you may want to declare like:
<asp:LinkButton ID="LinkButton1" runat="server" OnClick="LinkButton_Click" OnPreRender="LinkButton_PreRender">Home</asp:LinkButton>
EDIT:
Here is another solution that will work with cross page postbacks. Not much code but you'll need to put some on every page. Anyway:
Masterpage.aspx:
<asp:LinkButton ID="LinkButton1" runat="server" PostBackUrl="Default.aspx">Home</asp:LinkButton>
<asp:LinkButton ID="LinkButton2" runat="server" PostBackUrl="Page1.aspx">Page1</asp:LinkButton>
<asp:LinkButton ID="LinkButton3" runat="server" PostBackUrl="Page2.aspx">Page2</asp:LinkButton>
<asp:LinkButton ID="LinkButton4" runat="server" PostBackUrl="Page3.aspx">Page3</asp:LinkButton>
Masterpage.aspx.vb:
Public Sub SetCssClass(ByVal ctrl As String)
CType(FindControl(ctrl), LinkButton).CssClass = "current"
End Sub
All content pages:
*.aspx:
add this directive to create a strongly typed reference to the masterpage
<%# MasterType VirtualPath="~/MasterPage.master" %>
*.aspx.vb:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Master.SetCssClass("LinkButton1") '' << put the name of the relevant link button here
End Sub
Set the CssClass in the code-behind. This will state your intent more clearly than calling DataBind on your linkbuttons if you use databinding syntax. Since you're doing it for multiple controls maybe stick them in a method called ApplyCssClasses.
I'm not sure why <%= %> isn't working but personally I don't like to mix code and markup, I like to keep them completely separate.
I would suggest setting the CSS class in code perhaps on the page load event.
lnkPopulate.CssClass = "current"
<%# ... %> will work if you're OK with doing LinkButton1.DataBind() in your code-behind at the appropriate time.
I have a simple usercontrol, with a datalist, and checkboxes inside.
<asp:DataList ID="DataListDroits" runat="server" DataKeyField="droit_id" DataSourceID="SqlDroits">
<ItemTemplate>
<asp:HiddenField ID="HiddenFieldDroitID" runat="server" Value='<%# Eval("droit_id") %>' />
<asp:CheckBox ID="CheckBoxDroit" runat="server" Text='<%# Eval("droit_label") %>' />
</ItemTemplate>
</asp:DataList>
I check them using code behind in the usercontrol :
Public Sub CheckRole(ByVal role As Integer)
For Each dliOrganisme As DataListItem In Me.DataListOrganismes.Items
Dim DataListDroits As DataList = dliOrganisme.FindControl("DataListDroits")
If DataListDroits IsNot Nothing Then
For Each dliDroit As DataListItem In DataListDroits.Items
If role = CInt(CType(dliDroit.FindControl("HiddenFieldDroitID"), HiddenField).Value) Then
Dim CheckBoxDroit As CheckBox = dliDroit.FindControl("CheckBoxDroit")
CheckBoxDroit.Checked = True
End If
Next ' DataListDroits
End If
Next ' DataListItem
End Sub
And in the page_load of the calling webform :
Dim CheckBoxesRoles1 As ASP.organisme_checkboxesroles_ascx = Me.FormViewRubrique.FindControl("CheckBoxesRoles1")
Dim rolesCoches As New List(Of Integer)
Dim cmdRoles As New SqlCommand("SELECT droit_id FROM o_droit_rubrique WHERE rubrique_id = #rubrique", conn)
cmdRoles.Parameters.AddWithValue("rubrique", Request.QueryString("rid"))
Dim rdrRoles As SqlDataReader = cmdRoles.ExecuteReader
While rdrRoles.Read
CheckBoxesRoles1.CheckRole(rdrRoles("droit_id"))
End While
rdrRoles.Close()
... and yet, they are not checked.
But if I do this :
Protected Sub Page_LoadComplete(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.LoadComplete
Dim CheckBoxesRoles1 As ASP.organisme_checkboxesroles_ascx = Me.FormViewRubrique.FindControl("CheckBoxesRoles1")
If CheckBoxesRoles1 IsNot Nothing Then
For Each role As Integer In CheckBoxesRoles1.CheckedRoles
Response.Write("role : " & role & "<br>")
Next
End If
End Sub
I tells me they are...
I'm going mad here ! Why does it tells me they are checked while they obviously are not ?
Well... for one thing, you aren't checking if your checkboxes are checked, all you're doing is outputting the value of "role". What exactly are you expecting here?
Two suggestions:
1) Set the Checked property of your CheckBox in the aspx like so:
<asp:CheckBox ID="CheckBoxDroit" runat="server" Text='<%# Eval("droit_label") %>' Checked='<%# (Eval("droit_id") > 0).ToString()' />
2) Set the property in OnItemDataBound in code-behind
One of two things is happening: Either the code you expect to be executing is not really executing (ie, is your if block ever true? Is the control not being found? Try a breakpoint), OR you are doing it at the wrong time -- after the page has already been rendered.
how can i use request.querystring in asp.net.i have a linkbutton and this is in a repeater control.i want to play video for the corresponding link _click.i want to pass a fileID of the corresponding link to a function,how can i do this ?
<asp:Repeater ID="Repeater2" runat="server">
<ItemTemplate>
<asp:LinkButton runat="server" ID="LnkBtn"
OnClick="ButtonShowVideo_Click"><%#Eval("FileName")%>
</asp:LinkButton>
</ItemTemplate>
</asp:Repeater>
Protected Sub ButtonShowVideo_Click(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles ButtonShowVideo.Click
Repeater1.DataSource = GetSpecificVideo(**here i want to get the fileID**)
Repeater1.DataBind()
End Sub
Private Function GetSpecificVideo(ByVal i As Object) As DataTable
'pass the id of the video
Dim connectionString As String = ConfigurationManager
.ConnectionStrings("UploadConnectionString").ConnectionString
Dim adapter As New SqlDataAdapter("SELECT FileName, FileID,FilePath " +
"FROM FileM WHERE FileID = #FileID", connectionString)
adapter.SelectCommand.Parameters.Add("#FileID", SqlDbType.Int).Value =
DirectCast(i,Integer)
Dim table As New DataTable()
adapter.Fill(table)
Return table
End Function
This won't help you:
<asp:Repeater ID="Repeater2" runat="server">
<ItemTemplate>
<asp:LinkButton runat="server" ID="LnkBtn"
OnClick="ButtonShowVideo_Click"><%#Eval("FileName")%>
</asp:LinkButton>
</ItemTemplate>
</asp:Repeater>
as it will not put FileName into query stirng. Rather use this method:
<asp:Repeater ID="Repeater2" runat="server">
<ItemTemplate>
<asp:LinkButton runat="server" ID="LnkBtn"
CommandArgument='<%#Eval("FileName")%>'
OnClick="ButtonShowVideo_Click"><%#Eval("FileName")%>
</asp:LinkButton>
</ItemTemplate>
</asp:Repeater>
In code behind:
Protected Sub ButtonShowVideo_Click(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles ButtonShowVideo.Click
Dim btn as LinkButton = sender as LinkButton
if(btn is not null) then
if(NOT string.IsNullOrEmpty(btn.CommandArgument)) then
dim vid as integer = Convert.ToInt32(btn.CommandArgument)
Repeater1.DataSource = GetSpecificVideo(vid)
Repeater1.DataBind()
end if
end if
End Sub
If you plan to use query string, the button click can do either of the following:
Hyperlinks to a page with the designated quertstring to identify the action/entity etc
Do a server-side redirect to the page as describe in item 1 above
So where is your issue that you find challenging?
I have a gridview nested within a repeater, and I'm trying to enable paging on the gridview without much success.
The gridview databound is like this
<asp:repeater....>
<asp:gridview id="GridView1" Datasource='<%# LoadData(CInt(Eval("Id"))) %>'
OnPageIndexChanging="GridViewPageIndexChanging" AllowPaging="true"
PageSize="10" ............. </asp:GridView>
</asp:repeater>
In the code behind my LoadData method get a list of objects:
Public Function LoadData(ByVal Id As Integer) As IList(Of Client)
Dim ds As IList(Of Client) = client.GetClientById(Id)
Return ds
End Function
And the event handler is as follow:
Protected Sub GridViewPageIndexChanging(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewPageEventArgs)
sender.PageIndex = e.NewPageIndex
End Sub
My code doesn't change the page in the gridview, am I missing something ?
Any help is very much appreciated.
You have to call DataBind().
Dim grid as GridView = DirectCast(sender, GridView)
grid.PageIndex = e.NewPageIndex
grid.DataBind()
EDIT
Since I can't comment yet and creating another answer to an answer makes everything confusing, I'll just edit this one.
I'm afraid the Repeater is a wrong control to use for what you want. The problem stems from the fact that it does not preserve DataItem when GridView's page events fire. So the "id" gets evaluated into nothing and subsequently a zero. Btw, in C# you'd get a null exception.
I suggest you use the DataList instead:
<asp:DataList ID="DataList" runat="server" DataKeyField="id">
<ItemTemplate>
<asp:GridView ID="Grid" runat="server"
AllowPaging="true"
PageSize="2"
OnPageIndexChanging="Grid_PageIndexChanging"
DataSource='<%# GetData(DirectCast(DataList.DataKeys(DirectCast(Container, DataListItem).ItemIndex), Integer)) %>'
>
</asp:GridView>
<hr />
</ItemTemplate>
</asp:DataList>
With code behind:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
DataList.DataSource = New Integer() {1, 2, 3, 4, 5}.Select(Function(x) New With {.id = x})
DataList.DataBind()
End If
End Sub
Protected Function GetData(ByVal id As Integer) As String()
Dim arr As String() = New String(4) {}
For i As Integer = 0 To arr.Length - 1
arr(i) = String.Format("id {0}; grid item {1}", id, i)
Next
Return arr
End Function
Protected Sub Grid_PageIndexChanging(ByVal sender As Object, ByVal e As GridViewPageEventArgs)
Dim grid As GridView = DirectCast(sender, GridView)
grid.PageIndex = e.NewPageIndex
grid.DataBind()
End Sub
This code works -- I tested. Although, personally I don't like using binding expressions.
I'm one step further ,
After I do the binding I got an exception on Eval.
I changed it in the datasource to <%#LoadData(DataBinder.Eval(Container.DataItem,"Id"))%>
I don't get the Eval exception anymore after the binding. However my grid still empty.
[update]
Ok I got it solved by keeping my Ids in hashtable and I rebind my gridview with the equivalent id from the hashtable.
It is all good now thanks everyone for your helps.
One thing I see if your markup. Your sample has the GridView directly within the Repeater control. You will need it within the ItemTemplate.
<asp:Repeater ID="rpt" runat="server" ...>
<ItemTemplate>
<asp:GridView id="gv1" runat="server" ...>
.
.
.
</asp:GridView>
</ItemTemplate>
</asp:Repeater>