Create LinkButtons with dynamic ID's - asp.net

I've dabbled in the past with VB and ASP classic and am currently trying to write my first site in ASP.net and I'm very much learning as I go...but I've spent all of today trying to do this one and I've not got anywhere with the usual googling.
Hopefully it's apparent in my code that I am trying to dynamically add 2 LinkButtons with unique ID's below a LinkButton with a static ID. I want the IDs in the 2 unique LinkButtons to have the "companyname" dataitem value in it so that I can unhide them when the first "companylink" is clicked - I'm yet to write the sub "LoadCompany" to unhide the two LinkButton's but I'm pretty confident I already know how to do that.
<asp:Content ContentPlaceHolderID="leftsidebarcontent" runat="server">
<li id="leftsidebarhead" class="sidebaritems">/* MENU */</li><br />
<asp:Datalist id="customers" runat="server" RepeatLayout="Flow">
<ItemTemplate>
<li class="leftsidebaritem sidebaritems"><asp:LinkButton id="CompanyLink" runat="server" OnCommand="LoadCompany" Text='<%#Container.DataItem("companyname")%>'></asp:LinkButton></li>
<li class="leftsidebaritem sidebaritems"><asp:LinkButton id='<%#Container.DataItem("companyname")%> & "Reviews"' runat="server" Text="Reviews"></asp:LinkButton></li>
<li class="leftsidebaritem sidebaritems"><asp:LinkButton id='LinkButton1' runat="server" Text="Other"></asp:LinkButton></li>
<br />
</ItemTemplate>
</asp:Datalist>
If it helps - the first LinkButton is to populate a nav menu down the left of the page, below each one of these LinkButton's I want two further linkbuttons which will be hidden, until the original linkbutton is clicked, at which point they unhide - so creating a kind of nested navigation menu.

You can do like this in markup:
<asp:Content ID="Content1" ContentPlaceHolderID="leftsidebarcontent" runat="server">
<p id="leftsidebarhead" class="sidebaritems">/* MENU */</p>
<br />
<asp:DataList ID="customers" runat="server" RepeatLayout="Flow" OnItemCommand="customers_ItemCommand" >
<ItemTemplate>
<li class="leftsidebaritem sidebaritems">
<asp:LinkButton ID="CompanyLink" runat="server" CommandName="LoadCompany"
Text='<%#DataBinder.Eval(Container.DataItem, "companyname")%>'></asp:LinkButton></li>
<ul id="ulSubItems" runat="server" visible="false">
<li class="leftsidebaritem sidebaritems">
<asp:LinkButton ID='LinkButton1' runat="server" Text="Reviews"></asp:LinkButton></li>
<li class="leftsidebaritem sidebaritems">
<asp:LinkButton ID='LinkButton2' runat="server" Text="Other"></asp:LinkButton></li>
</ul>
<br />
</ItemTemplate>
</asp:DataList>
</asp:Content>
And in the codebehind:
Protected Sub customers_ItemCommand(source As Object, e As DataListCommandEventArgs) Handles customers.ItemCommand
'Hide all subitems
For Each itm As DataListItem In customers.Items
If itm.ItemType = ListItemType.Item OrElse itm.ItemType = ListItemType.AlternatingItem Then
Dim ulSubItems As HtmlGenericControl = CType(itm.FindControl("ulSubItems"), HtmlGenericControl)
ulSubItems.Visible = False
End If
Next
If e.CommandName = "LoadCompany" Then
Dim MySubItems As HtmlGenericControl = CType(e.Item.FindControl("ulSubItems"), HtmlGenericControl)
If Not MySubItems Is Nothing Then
MySubItems.Visible = True
End If
End If
End Sub

Related

ASP.Net add item to listbox without posting

I am trying to add items to a listbox. I have a textbox and a button and when the user enters something into the textbox and hits add, I want to insert a new item the listbox without the page refreshing.
Here is what I have so far:
<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<div class="col-xs-6 text-center">
<asp:Label ID="empid" runat="server" Text="Employee ID" CssClass="label-default label "></asp:Label>
<asp:TextBox ID="txtEmployeeID" runat="server" CssClass="form-control"></asp:TextBox>
<div class="col-xs-6">
<asp:Button ID="btnAddEmp" runat="server" Text="Add Emp" CssClass="btn btn-primary top-buffer" Width="100%" />
</div>
<div class="col-xs-6">
<asp:Button ID="btnRemoveEmp" runat="server" Text="Remove Emp" CssClass="btn btn-danger top-buffer" Width="100%" />
</div>
<asp:ListBox ID="listEmps" runat="server"
CssClass="top-buffer add-height"
Width="100%"
ValidationGroup="req"></asp:ListBox>
</div>
</ContentTemplate>
</asp:UpdatePanel>
and here is my button click event
Protected Sub btnAddEmp_Click(sender As Object, e As EventArgs) Handles btnAddEmp.Click
If Not IsPostBack() Then
If listEmps.Items.Count = 0 Then
listEmps.Items.Add(txtEmployeeID.Text)
Else
'check list to see if employee already exists
For i = listEmps.Items.Count - 1 To 0 Step -1
If RTrim(txtEmployeeID.Text) = RTrim(listEmps.Items(i).ToString) Then
'employee already exists within list
Response.Write("<script>alert('Employee ID " & txtEmployeeID.Text.Trim & " has already been added. ')</script>")
txtEmployeeID.Text = ""
Exit Sub
End If
Next
'add to list
listEmps.Items.Add(txtEmployeeID.Text)
End If
End If
End Sub
How can I properly add items to a listbox without refreshing the page?
Remove your If Not IsPostBack() Then check in your button click event. The IsPostBack() is typically only used for the Page_Load event. Since your button is contained in an UpdatePanel the click event should be asynchronous and won't cause a postback.

ItemCommand of DataList in UpdatePanel is not fired on Postback

I have a popup panel which contains an UpdatePanel, which contains a DataList. Table rows are populated using ItemTemplate and there is a LinkButton generated on each row for deleting this row. I would like to delete this record in the DataList's ItemCommand event handler and rebind the DataList.
However, after I click a "delete" button in the DataList, ItemCommand is not fired. I've already checked if IsPostBack in my Page_Load and only do Datalist.Databind() if it's not a postback. Normally I would expect first Page_Load and then list_ItemCommand being called after I click a delete button in the DataList, but list_ItemCommand is not called as expected. And nothing is then displayed in DataList which is inside the UpdatePanel.
And stranger, if I remove the IsPostBack check in Page_Load, that being said, rebind the DataList in every Page_Load, ItemCommand will be caught and list_ItemCommand is called. This is against the answers in many other posts "ItemCommand event will be canceled if DataList is rebinded during PostBack".
Code behind:
Protected records As New List(Of Record)
Protected Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Set some page properties...
If Not Page.IsPostBack Then
GetListOfRecordFromDatabase()
datalist.DataSource = records
datalist.DataBind()
End If
End Sub
Protected Sub datalist_ItemCommand(ByVal source As Object, ByVal e As System.Web.UI.WebControls.DataListCommandEventArgs) Handles datalist.ItemCommand
Select Case e.CommandName.ToLower
Case "delete"
For Each c As Record In records
If c.Id = e.CommandArgument Then
records.Remove(c)
Exit For
End If
Next
DeleteRecordFromDatabase(e.CommandArgument)
datalist.DataSource = records
datalist.DataBind()
End Select
End Sub
Controls:
<asp:Content ID="content1" runat="server" ContentPlaceHolderID="Content1PlaceHolder">
<asp:LinkButton ID="btnpopup" runat="server" OnClientClick="javascript:return popup()"></asp:LinkButton>
<asp:ScriptManagerProxy ID="ScriptManagerProxy1" runat="server" EnableViewState="false" >
</asp:ScriptManagerProxy>
<asp:Panel ID="PanelPopup" runat="server" style="display:none;">
<asp:UpdatePanel ID="UPPopup" runat="server" UpdateMode="conditional" EnableViewState="false">
<ContentTemplate>
<div id="divPopup1" runat="server">
<table id="table1" cellpadding="2" cellspacing="1" width="500" border="0" >
<asp:DataList ID="datalist" runat="server" OnItemCommand="datalist_ItemCommand">
<ItemTemplate>
<tr align="center">
<td><%#Container.ItemIndex +1 %></td>
<td><asp:Label ID="Label1" runat="server" Text='<%# eval("Name") %>'></asp:Label></td>
<td><asp:Label ID="Label2" runat="server" Text='<%# eval("Color") %>'></asp:Label></td>
<td><asp:LinkButton ID="Delete" CommandName="Delete" runat="server" Text="Delete" CommandArgument='<%# eval("Id") %>' ></asp:LinkButton></td>
</tr>
</ItemTemplate>
</asp:DataList>
</table>
</div>
</ContentTemplate>
</asp:UpdatePanel>
<div style="text-align:center;"><br />
<asp:Button ID="BtnSavePopup" runat="server" Text="Save and Close"/>
</div>
</asp:Panel>
<script type="text/javascript">
function popup() {
return mypagehelper.openAsModalPopup("<% =PanelPopup.ClientID%>");
}
</script>
</asp:Content>
Further more, I tried to grab the ControlID and the Control who raised the event during Postback using this code:
If IsPostBack Then
Dim CtrlID As String = String.Empty
If Request.Form("__EVENTTARGET") IsNot Nothing And
Request.Form("__EVENTTARGET") <> String.Empty Then
CtrlID = Request.Form("__EVENTTARGET")
Dim postbackControl As System.Web.UI.Control = Page.FindControl(CtrlID)
Else
End If
And I found that I can get my CtrlID as "ctl00$datalist$ctl08$Delete" but the postbackControl is Nothing. While on my other normal pages I can get both the controlID and actual control(which is a LinkButton) who raised the event.
Remove EnableViewState="false" from update panel.
it's late answer but i faced in soon, also may be it help some one else ...
the CommandName="Delete" is reserved for DataList "OnItemDeleting" Event
so just changing the CommandName to anything else (for example "Remove") will help or handle the OnItemDeleting Event.

Can't find a control in repeateritem.findcontrol

I have a nested repeaters in a form and bind them to tables in a dataset. I can find the controls by name and read and set values in the Itemdatabound event, However I can't find the control by the same name in a button click event. I can find the repeater and the item.
<asp:Repeater ID="rptrDivision" OnItemDataBound="rptrDivision_ItemDataBound" runat="server">
<itemtemplate>
<div class="fluid">
<div class="widget grid12">
<div class="whead"><div class="grid2"><h4 class="fieldDivision" >
<h4 class="fieldDivision" ><asp:Label ID="lblDivName" runat="server" Visible="True" ><%# DataBinder.Eval(Container.DataItem, "LocationName")%></asp:Label></h4></div>
<div class="grid10">
<div class="grid4 divAdmin" ><label><strong>Division Administrator: </strong> </label></div>
<div class="grid8 on_off">
<div class="floatL ml10"><asp:CheckBox ID="cbxDivMgr" name="chbox" runat="server" /></div>
</div>
</div></div>
<asp:Repeater ID="rptrCamera" OnItemDataBound="rptrCamera_ItemDataBound" runat="server" datasource='<%# Container.DataItem.Row.GetChildRows("CameraJoin")%>'>
<HeaderTemplate>
<div class="body">
</HeaderTemplate>
<itemtemplate>
<div class="formRow">
<div class="grid2">
<asp:Label ID="CameraName" runat="server" ><strong><%# Container.DataItem("Name")%></strong></asp:Label> </div>
<div class="grid10" >
<asp:RadioButtonList ID="rblRoles" runat="server" CssClass="mr10" RepeatColumns="5" CellPadding="2" CellSpacing="2">
<asp:ListItem Value="role1" >Role1</asp:ListItem>
<asp:ListItem Value="role2">Role2 </asp:ListItem>
<asp:ListItem Value="role3" >Role3 </asp:ListItem>
<asp:ListItem Value="Role4">role4 </asp:ListItem>
<asp:ListItem Value="none" Selected="True">N/A </asp:ListItem>
</asp:RadioButtonList>
</div>
</div>
</itemtemplate>
<FooterTemplate>
</div>
</FooterTemplate>
</asp:Repeater>
</itemtemplate>
</asp:Repeater>
<asp:Button ID="btnSubmit" runat="server" Text="Submit" CssClass="buttonM bBlue" OnClientClick="btnSubmit_Click" /> <asp:Button ID="btnCancel" runat="server" Text="Cancel" CssClass="buttonM bBlue" OnClientClick="btnCancel_Click"/>
The submit button is outside the repeater but in the same form
Protected Sub btnSubmit_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnSubmit.Click
For Each Item As RepeaterItem In rptrDivision.Items
If (Item.ItemType = ListItemType.Item) Or (Item.ItemType = ListItemType.AlternatingItem) Then
DivLabel = CType(Item.FindControl("lblDivName"), Label)
DivName = DivLabel.Text
DivMgr = CType(Item.FindControl("cbxDivMgr"), CheckBox)
'''do some logic
End If
Next
End Sub
I've looked in the debugger and item has the correct number of controls so I know I am in the right place, but the findcontrol in the repeater item can't locate the control by name. It always comes back as null.
Every example I can find from here to MSDN forums to asp.net to bytes.com show looping through the items in the repeater and calling the find control the same way. I can't figure out what I am doing wrong.
Edit:
SO here is the kicker just make sure I'm not crazy I did a loop through the controlscollection on the repeater item and on the second control it comes back with the ID "lblDivName" yet if I call the item.findControl("lblDivName") it returns a null value.
Control events (like a Button's click event) occur before DataBound events (see ASP.NET Page Life Cycle on MSDN for more information). Thus, your Repeater is not DataBound yet, so its databound controls have not been initialized (they are null).
You have some options.
Preferably, you would use the Repeater's databound event to work with it's data items - since this is when you know for sure that they are initialized and populated with values.
However, you could just call "DataBind" prior to doing the processing in your Click event:
Protected Sub btnSubmit_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnSubmit.Click
rptrDivision.DataSource = yourDataSource
rptrDivision.DataBind()
For Each Item As RepeaterItem In rptrDivision.Items
' The rest of your code
End Sub
This should ensure that your controls have values.

Shading every other row in a VB.net Listview?

I have been Googling this for about a day now, and every post I find is too old and Visual Studio doesn't recognize some pieces of code that people have posted. I have a dynamically populated Listview. I would really like every other line to be shaded for readability purposes, and just can't figure it out.
Everything I try to do messes with the Modal PopupExtender that I have inside of the Listview. It trys to shade the lines inside the PopUpBox too. This is one of the Listviews that I would like shaded.
<!-- Descriptions -->
<asp:TabPanel ID="tab2" runat="server" HeaderText="Descriptions">
<HeaderTemplate>Descriptions</HeaderTemplate>
<ContentTemplate>
<ul class="info">
<asp:ListView ID="lvDescriptions" runat="server" DataSourceID="dsMarketingDescriptions" DataKeyNames="MarketingID">
<ItemTemplate>
<li>
<asp:LinkButton ID="ViewDescriptionButton" runat="server"><%#Eval("MarketingTitle")%></asp:LinkButton>
<asp:Panel ID="ViewDescriptionPanel" runat="server" CssClass="DescModalPopup"> <div class="PopupHeader" id="PopupHeader">View Description
<asp:ImageButton ID="CancelDescriptionButton" runat="server" ImageUrl="../../images/exit.png" AlternateText="" Style="float:right;"/>
</div>
<asp:Label ID="Description" runat="server" style="padding:5px;"><%# Eval("MarketingData") %></asp:Label>
</asp:Panel>
<asp:ModalPopupExtender ID="ViewDescriptionModal" runat="server" BackgroundCssClass="modalBackground" DropShadow="false" DynamicServicePath="" Enabled="true" PopupControlID="ViewDescriptionPanel" TargetControlID="ViewDescriptionButton" CancelControlID="CancelDescriptionButton"></asp:ModalPopupExtender>
</li>
</ItemTemplate>
</asp:ListView>
</ul>
</ContentTemplate>
</asp:TabPanel>
Try using the AlternatingItemTemplate to specify a different background color for alternating items.
Are you trying to do something like this with the ModalPopupExtender?:
protected void ListView1_ItemDataBound(object sender, ListViewItemEventArgs e)
{
Panel pnl = e.Item.FindControl("Panel1") as Panel;
if (pnl != null)
{
pnl.BackColor = ListView1.Items.IndexOf(e.Item) % 2 == 1 ? Color.PeachPuff : Color.White;
}
}

ASP.NET Repeater Template, Conditional Code for every Nth element

I'm using an asp.net repeater to create a bunch of images. The image markup is all the same so the standard <ItemTemplate> is fine.
However, I want to wrap K images in a div. Lets say I bind 25+ images to the repeater and I want 5 images per div. How do I go about conditionally creating the start and close tags for the div?
Is this a case better suited for a for loop.
This should work for you, with no need for anything in the code behind (other than binding the repeater..):
<asp:Repeater ID="repImages" runat="server">
<HeaderTemplate><div></HeaderTemplate>
<ItemTemplate>
<%# (Container.ItemIndex != 0 && Container.ItemIndex % 5 == 0) ? #"</div><div>" : string.Empty %>
<asp:Image ID="imgGallery" runat="server" ImageUrl='<%# /* your code here */ %>' />
</ItemTemplate>
<FooterTemplate></div></FooterTemplate>
</asp:Repeater>
Here is where Asp.Net WebForms can give you incredible RAD efficiency.
You can use the new ListView control, and set the number of items per "group", which will allow you to setup the HTML that surrounds a group, as well as each individual item. This way you can surround the group with the conditional tags.
<asp:ListView ID="ListView1" runat="server" DataKeyNames="id" DataSourceID="LinqDataSource1" GroupItemCount="3">
<LayoutTemplate>
<div id="layout">
<asp:PlaceHolder ID="groupPlaceholder" runat="server"></asp:PlaceHolder>
</div>
</LayoutTemplate>
<GroupTemplate>
<div class="group">
<asp:PlaceHolder ID="itemPlaceholder" runat="server"></asp:PlaceHolder>
</div>
</GroupTemplate>
<EmptyDataTemplate>
<span>No data was returned.</span>
</EmptyDataTemplate>
<ItemTemplate>
<div class="item">
<img alt='<%# Eval("title") %>' title='<%# Eval("title") %>'
src='<%# Eval("filename","photos/{0}") %>' />
</div>
</ItemTemplate>
</asp:ListView>
If you want to keep your markup on the ASPX page you could also try this variation on David's method:
On the aspx page:
<ItemTemplate>
<asp:Literal runat="server" ID="divStart" Text="<div>" />
<asp:Image ....>
<asp:Literal runat="server" ID="divEnd" Text="</div>" />
</ItemTemplate>
In the ItemDataBound event in the codebehind:
e.Item.FindControl("divStart").Visible
= e.Item.FindControl("divEnd").Visible
= e.Item.ItemIndex % 5 == 0;
Add two empty label controls into your Repeaters ItemTemplate where you'd want your div tags to be.
Then add an ItemDataBound event to the Repeater.
Then add this code into the ItemDataBound event:
Protected Sub Repeater1_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.RepeaterItemEventArgs)
If (e.Item.ItemType = ListItemType.Item) Or (e.Item.ItemType = ListItemType.AlternatingItem) Then
If e.Item.ItemIndex Mod 5 = 0 Then
Dim lblDivStart As Label = CType(e.Item.FindControl("lblDivStart"), Label)
Dim lblDivEnd As Label = CType(e.Item.FindControl("lblDivEnd"), Label)
lblDivStart.text = "<div>"
lblDivEnd.text = "</div>"
End If
End If
End Sub
Note - This will need some tweaking to handle the first div and you may need to do something like If (e.Item.ItemIndex + 1) Mod 5 = 0 to get the divs to show up exactly where you want them.
For more info:
DataListItem.ItemIndex Property
DataList.ItemDataBound Event

Resources