Dynamically adding controls to a panel within a data repeater - asp.net

I have a Data Repeater to which I need to add x number of images depending on their existence in the database.
I need the images added within hyperlinks for Javascript functionality. In order to dynamically add the hyperlinks and images I have placed them within a panel in the data repeater and am adding them in the ItemDataBound event.
The problem is that only the first image is being written to the datarepeater.
Protected Sub Repeater1_ItemDataBound(ByVal sender As Object, ByVal e As RepeaterItemEventArgs) Handles myDataRepeater.ItemDataBound
Dim myPanel As Panel = e.Item.FindControl("pnlImages")
Dim myLink As New System.Web.UI.WebControls.HyperLink
Dim myImage As New System.Web.UI.WebControls.Image
Dim myProperty As String = Request.QueryString("ID")
Dim dirInfo As New DirectoryInfo(Server.MapPath("~/ftp/images/"))
Dim fs_infos() As FileInfo = dirInfo.GetFiles("*" + myProperty.Substring(1) + "*")
For Each fs_info As FileInfo In fs_infos
If fs_info.Name.Substring(8, 1) <> "P" Then
myLink.ID = fs_info.Name
myLink.NavigateUrl = "~/ftp/images/" + fs_info.Name
myLink.Attributes.Add("onClick", "return hs.expand(this)")
myLink.Width = 90
myImage.ID = "img" + fs_info.Name
myImage.ImageUrl = "~/ftp/images/" + fs_info.Name
myImage.Width = 80
myImage.Height = 60
myLink.Controls.Add(myImage)
myPanel.Controls.Add(myLink)
End If
Next fs_info
fs_infos = Nothing
End Sub
Any ideas as to what I am doing wrong - or a better way of doing things?

You create just one Link and one Image object and use it for each iteration. Move the dims of myLink and myImage into the if statement and everything should work.

Related

Responding to dynamically created async postback buttons

When my ASP page is loaded I am reading data from a SQL database into a list of objects, then looping through this list and creating dynamic placeholders, updatepanels, textboxs and buttons which are then added to a main placeholder. Each updatepanel is set to conditional and the unique button is added to the scriptmanager. I tried to create async triggers dynamically but found this is not possible. Below is my code:
Dim plcComments As New PlaceHolder()
plcComments.ID = "plcComments" + Link.ID.ToString()
Dim updComments As New UpdatePanel()
updComments.ID = "updComments" + Link.ID.ToString()
updComments.UpdateMode = UpdatePanelUpdateMode.Conditional
Dim txtComment As New TextBox()
txtComment.ID = "txtComment" + Link.ID.ToString()
txtComment.Text = "txtComment " + Link.ID.ToString() 'Example text
updComments.ContentTemplateContainer.Controls.Add(txtComment)
Dim btnComment As New Button()
btnComment.ID = "btnComment" + Link.ID.ToString()
btnComment.Text = "btnComment" + Link.ID.ToString()
updComments.ContentTemplateContainer.Controls.Add(btnComment)
ScriptManager1.RegisterAsyncPostBackControl(btnComment)
plcComments.Controls.Add(updComments)
In a normal circumstance I understand you would have code behind for each button that acts a trigger. As these buttons are created dynamically with unique names, how can I react to each button when it is pressed?
After looking into the AddHandler function I came up with this dirty method:
AddHandler btnComment.Click, AddressOf Me.Button_Handler
This latches to each button as it is created, points back at the same sub routine, and creates the controls within the subroutine based upon the sender.
Protected Sub Button_Handler(sender As Object, e As EventArgs)
Dim Comment_ID As String = DirectCast(sender, Button).ID.ToString.Remove(0, 3)
Dim txtComment As TextBox = Me.FindControl("txt" & Comment_ID)
Dim plcComment As PlaceHolder = Me.FindControl("plc" & Comment_ID)
Dim updComment As UpdatePanel = Me.FindControl("upd" & Comment_ID)
End Sub
Probably not the cleanest or best way to do it but it works.

Make a dropdownlist save the new value that the user selects

I have a DropDownList iniwhich on page load it loads up all the data into it, however when the user wants to make a change to what text is displayed they just simply click on the dropdown and select the new one. My question is How do I make it so it saves the new text value that they choose? Here is what I have now:
Private Sub cboCure_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles cboCure.SelectedIndexChanged
cboCure.AutoPostBack = True
Dim objXMLDoc As New System.Xml.XmlDocument
Dim objNodeList As System.Xml.XmlNodeList
Dim strXML As String = ""
Dim url As String = ""
MaterialStuff = New Message.Material
Dim code As String = cboCure.SelectedItem.Text
cboCure.Items.Clear()
If cboCure.Items.Count < 1 Then
strXML = Message.GetCureCodes
objXMLDoc.LoadXml(strXML)
objNodeList = objXMLDoc.GetElementsByTagName("Material_Cure")
cboCure.Items.Add("")
For Each childNode As System.Xml.XmlNode In objNodeList.Item(0).ChildNodes
cboCure.Items.Add(New System.Web.UI.WebControls.ListItem(childNode.SelectSingleNode("CureCodeLetter").InnerText,
childNode.SelectSingleNode("CureCode").InnerText))
Next
End If
cboCure.SelectedItem.Text = code
End Sub
I want the variable code to be the new text value that the user clicks but I can't seem to get it right, it keeps showing up as "" or the value that is originally displayed when the page loads.
EDIT:
Here is my Page_Load
If Not Page.IsPostBack Then
...code
else
cboCure_SelectedIndexChanged(sender, e )
end if

ASP.NET VB Display new images at runtime

In my VB project i already have functions in place for retrieving every image path in a specified directory, I then use
Dim Pics() As String = piccom.GetPictures("The\Dir")
For Each pic In Pics
If Not pic = "" Then
Dim bmp As New Bitmap(pic)
Dim Width As Integer = bmp.Width
Dim Height As Integer = bmp.Height
Else
Exit For
End If
Next
to loop through all the returned images, thing is I need to be able to display these images at run time in the main content of the page, how can I display said images at runtime?
EDIT:
I went out on a whim and tried this
For Each pic In Pics
If Not pic = "" Then
Dim bmp As New Bitmap(pic)
Dim Width As Integer = bmp.Width
Dim Height As Integer = bmp.Height
Response.ContentType = "image/jpeg"
bmp.Save(Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg)
Else
Exit For
End If
Next
Now this actually got me closer to what i want, but instead of displaying the page with the images nested in it it just streamed the first image it grabbed to my browser - not quite what i was after. I want all the images nested in the pre-existing content box on the page.
try this:
Dim Pics() As String = piccom.GetPictures("The\Dir")
For Each pic In Pics
If Not pic = "" Then
Dim bmp As New Bitmap(pic)
Dim Width As Integer = bmp.Width
Dim Height As Integer = bmp.Height
picImage.Image = bm
picImage.SizeMode = PictureBoxSizeMode.AutoSize
Else
Exit For
End If
Next
Finally got it working in the end, first I created a new page called 'image.aspx', and put this in it
Imports System.Drawing
Imports System.Drawing.Drawing2D
Public Class image
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim query As String = Request.QueryString("i")
Dim maxw As String = Request.QueryString("maxw")
Dim maxh As String = Request.QueryString("maxh")
If Not query = "" Then
Dim file = AppDomain.CurrentDomain.BaseDirectory + "\DIRWHEREPICTURESARE" + query
Dim bmp As New Bitmap(file)
Response.ContentType = "image/jpeg"
bmp.Save(Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg)
End If
End Sub
End Class
I then created a repeater in my page, with an object template like so
<asp:Repeater ID="Repeater1" runat="server">
<ItemTemplate>
<asp:Image ID="Image1" runat="server" ImageUrl="<%#Container.DataItem%>"/><br />
</ItemTemplate>
</asp:Repeater>
and in the code behind put
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim Pics() As String = piccom.GetPictures("Image\Directory")
Dim aList = From fileName In Pics
Repeater1.DataSource = aList
Repeater1.DataBind()
End Sub
Hope this helps anyone who runs into this problem!

ASP.NET Control added to Placeholder lost values right after adding

Working over 5 hours on the following problem:
Private Sub ModulEdit_PreInit(sender As Object, e As EventArgs) Handles Me.PreInit
Dim modulid As Integer = 1
loadeditors(modulid)
End Sub
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
End Sub
Public Sub loadeditors(modulID As Integer)
PlaceHolder1.Controls.Clear()
Using dbContext As New EntitiesModel()
Dim mps As List(Of ef.Modulparameter) = dbContext.Modulparameters.Where(Function(c) c.ModulID = modulID).ToList
Dim mmid As Int16
If EditMode.Checked = True Then
mmid = RadComboBox3.SelectedValue
End If
Dim mp As ef.Modulparameter
For Each mp In mps
Dim lbl As New Label
lbl.Text = "<BR>" & mp.Name & "<BR>"
PlaceHolder1.Controls.Add(lbl)
Select Case mp.Editor.Name
Case "textbox1line"
Dim con As New TextBox
con.ID = mp.ID
If EditMode.Checked = True Then
Using dbContext2 As New EntitiesModel
Try
Dim mpa As ef.Menu_modul_paramvalue = dbContext2.Menu_modul_paramvalues.Where(Function(c) c.ModulparameterID = mp.ID And c.Menu_modulID = mmid).First
con.Text = mpa.Valuestring
Catch ex As Exception
con.Text = "AAAA"
End Try
End Using
End If
PlaceHolder1.Controls.Add(con)
'RadAjaxManagerProxy1.AjaxSettings.AddAjaxSetting(Panel1, con, Nothing)
'RadAjaxManagerProxy1.AjaxSettings.AddAjaxSetting(con, con, Nothing)
Case "radeditor"
Dim con As New RadEditor
con.ID = mp.ID
con.ToolsFile = "\admin\controls\ToolsFile.xml"
'con.CssFiles.Add("\Content\frenzy\css\frenzy-orange.css")
If EditMode.Checked = True Then
Using dbContext2 As New EntitiesModel
Try
Dim mpa As ef.Menu_modul_paramvalue = dbContext2.Menu_modul_paramvalues.Where(Function(c) c.ModulparameterID = mp.ID And c.Menu_modulID = mmid).First
con.Content = mpa.Valuestring
Catch ex As Exception
con.Content = "BBBB"
End Try
End Using
End If
PlaceHolder1.Controls.Add(con)
'RadAjaxManagerProxy1.AjaxSettings.AddAjaxSetting(Panel1, con, Nothing)
'RadAjaxManagerProxy1.AjaxSettings.AddAjaxSetting(con, con, Nothing)
End Select
Next
End Using
End Sub
I add the control dynamicly, calling the codepart above in pre_init (tryed in load and init too with same result)
The value (text) for the control is there until that line PlaceHolder1.Controls.Add(con)
After the con.text is empty.
The control is added after, but with no value.
Strange, that in the same proc i add another control (label), where the text value is on the page after.
Adding additional info:
the control value (text or content), when debugging the LoadEditors), is allways correctly set. But then on the page both (textbox and radeditor) are empty
The routing is called from pre init, as described in a lot of related posts.
You are calling loadeditors in ModulEdit_Init. Shouldn't this be LoadControls ?
I fixed it myself:
Adding "con.ViewStateMode = System.Web.UI.ViewStateMode.Disabled" before adding control to placeholder
Calling "loadeditors()" in RadComboBox3 too
much probably the problem was, that i loaded editors in page-load or init, which got the correct values, but then the RadComboBox3.SelectedIndexChanged event was called, which overwrote the values somehow
So my answer is not a real answer, but it works now (I hate such: it works, but i dont know why) ;)

Creating buttons dynamically in ListView

I have a following problem. I have a ListView which returns data from SQL table. One of its columns looks like "Ambient/Trance/Goa Trance/House".
All i want to do is parse this column and create buttons for each value, for example a button for "Ambient", a button for "Trance", etc.
I tried to create buttons in ItemDataBound event in the following way:
Dim ListView_Albums_PlaceHolder_Artists As PlaceHolder = e.Item.FindControl("ListView_Albums_PlaceHolder_Artists")
Dim Artists As String() = e.Item.DataItem("album_artists").ToString.Split("/")
Dim ArtistsN As String() = e.Item.DataItem("album_artists_n").ToString.Split("/")
Dim ListView_Albums_Literal_Artists As New Literal
If Artists.Length = 1 Then
ListView_Albums_Literal_Artists.Text = "Artist: "
Else
ListView_Albums_Literal_Artists.Text = "Artists: "
End If
ListView_Albums_PlaceHolder_Artists.Controls.Add(ListView_Albums_Literal_Artists)
For Integer1 As Integer = 0 To Artists.Length - 1
Dim ListView_Albums_LinkButton_Artist As New LinkButton
ListView_Albums_LinkButton_Artist.Text = ArtistsN(Integer1)
ListView_Albums_LinkButton_Artist.CommandName = "Artist"
ListView_Albums_LinkButton_Artist.CommandArgument = Artists(Integer1)
ListView_Albums_LinkButton_Artist.CssClass = "a-03"
ListView_Albums_PlaceHolder_Artists.Controls.Add(ListView_Albums_LinkButton_Artist)
Dim ListView_Albums_Literal As New Literal
ListView_Albums_Literal.Text = ", "
If Not Integer1 = Artists.Length - 1 Then
ListView_Albums_PlaceHolder_Artists.Controls.Add(ListView_Albums_Literal)
End If
Next
They created fine but they didn't work at all. I tried to Add Handler for Click or Command event but it also didn't help.
Please help me to solve my problem!
Edit:
As VinayC suggested I changed ItemDataBound to ItemCreated. That helped, but I faced another problem: as far as I understand e.Item.DataItem or, maybe, e.Item becomes Nothing on PostBacks so the buttons do not work.
How to solve that problem? Thanks once again!
I believe that buttons must be getting created late in page life cycle and hence not responding to events.
You may want to try moving your code in ItemCreated event and use ListView's ItemCommand event to trap these. Yet another suggestion is to assign (different) ID to your link buttons - for example
ListView_Albums_LinkButton_Artist.ID = "A" & Artists(Integer1)
In case, you want to attach an click event handler directly to buttons then ID is must.
So, I solved my problem. The solution wasn't simple but here it is:
In ItemCreated event I firstly count the number of buttons, then save it to ViewState, and only then I create buttons. I had to save the number of buttons to ViewState because on every postback e.Item.DataItem becomes Nothing.
Maybe there is a simplier solution but I found only that one...
Sub OnItemCreated(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.ListViewItemEventArgs)
Dim ListView_Albums_PlaceHolder_Artists As PlaceHolder = e.Item.FindControl("ListView_Albums_PlaceHolder_Artists")
If Not ListView_Albums_PlaceHolder_Artists Is Nothing Then
If Not e.Item.DataItem Is Nothing Then
ViewState("Length") = e.Item.DataItem("album_artists").ToString.Split("/").Length
End If
If Not ViewState("Length") Is Nothing Then
Dim Length As Integer = ViewState("Length")
For Integer1 As Integer = 0 To Length - 1
Dim ListView_Albums_LinkButton_Artist As New LinkButton
ListView_Albums_LinkButton_Artist.ID = "ListView_Albums_LinkButton_Artist_" & Integer1
ListView_Albums_PlaceHolder_Artists.Controls.Add(ListView_Albums_LinkButton_Artist)
Next
End If
End If
End Sub
Sub OnItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.ListViewItemEventArgs)
Dim ListView_Albums_PlaceHolder_Artists As PlaceHolder = e.Item.FindControl("ListView_Albums_PlaceHolder_Artists")
If Not ListView_Albums_PlaceHolder_Artists Is Nothing Then
If Not e.Item.DataItem Is Nothing Then
Dim Artists As String() = e.Item.DataItem("album_artists").ToString.Split("/")
Dim Artists_N As String() = e.Item.DataItem("album_artists_n").ToString.Split("/")
For Integer1 As Integer = 0 To Artists.Length - 1
Dim ListView_Albums_LinkButton_Artist As LinkButton = e.Item.FindControl("ListView_Albums_LinkButton_Artist_" & Integer1)
ListView_Albums_LinkButton_Artist.CommandArgument = Artists(Integer1)
ListView_Albums_LinkButton_Artist.Text = Artists_N(Integer1)
ListView_Albums_LinkButton_Artist.CssClass = "a-03"
Next
End If
End If
End Sub

Resources