Replace CheckBoxList TemplateControl with custom UserControl? - asp.net

I am trying to create a more detailed item template for the standard CheckBoxList control. It exposes an ITemplate property called TemplateControl but I wasn't able to find a straightforward resource on how to actually use it. Here's the code I have so far:
Protected Overrides Sub OnLoad(ByVal e As System.EventArgs)
MyBase.OnLoad(e)
Dim items As New List(Of ListItem)
items.Add(New ListItem() With {.Text = "A", .Value = "1"})
items.Add(New ListItem() With {.Text = "B", .Value = "2"})
items.Add(New ListItem() With {.Text = "C", .Value = "3"})
Dim lst As New CheckBoxList()
Dim tpl As ITemplate = LoadTemplate("~/CustomListItem.ascx")
Dim g As New TemplateControlWrapper()
tpl.InstantiateIn(g)
lst.TemplateControl = g
lst.DataSource = items
lst.DataBind()
Form.Controls.Add(lst)
End Sub
Class TemplateControlWrapper
Inherits UserControl
End Class
It seems to be ignoring the TemplateControl property completely. Any ideas?

CheckBoxList's TemplateControl property does not actually allow you to modify the template of the CheckBoxList. This is a property inherited all the way from System.Web.UI.Control, and it means the templated control that the CheckBoxList lives in, or put another way, the .aspx page, .ascx user control, or master page that the control lives on. (If the control is included as part of a composite control, I honestly don't know without experimenting if the TemplateControl property would return null, or keep going up the control chain until it found a Page or UserControl.)
The CheckBoxList control does not offer the kind of template modification you are looking to do. You may need to custom-bind a Repeater or DataList (with a CheckBox control in the ItemTemplate) in order to achieve the functionality you're looking for.

You are missing a couple things... this MSDN page has a pretty straightforward example:
http://msdn.microsoft.com/en-us/library/36574bf6.aspx
For starters, you are missing INamingContainer.

Related

Creating a New control of the same type as another control that is already declared

I'm using a custom template class to generate lines with my repeater control, i'd like to be able to specify the controls in this repeater dynamically from the code behind my aspx page.
In the code behind I've added controls to a list like this:
Dim lstControls As New List(Of Control)
lstControls.Add(New TextBox)
lstControls.Add(New Label)
lstControls.Add(New CheckBox)
lstControls.Add(New DropDownList)
lstControls.Add(New CheckBox)
Then i use this line to add the controls to my template
rptrSummary.ItemTemplate = New myTemplate(ListItemType.Item, , lstControls)
From the instantiateIn sub i'm doing something like this:
Dim ph As New PlaceHolder
For i = 0 To lstControls.Count - 1
ph.Controls.Add(lstControls(i))
Next
This doesn't work properly and following .databind() of my repeater control the controls i specify only appear on the final row. I think this is because i've only declared the controls as NEW once, so i only have one rows worth.
tldr?/ conclusion:
How can i generate new controls of the same type as controls from my list? Something like:
Dim newControl as new Control = type(lstControl(0))
(this obviously doesn't work)
I've found the answer, here are some examples in case anyone else is stuck (i may also change the title so it's more similar to likely search criteria):
dim egTextbox as new textbox
dim egLabel as new label
dim newObject1 as Object = Activator.CreateInstance(egTextbox.GetType)
dim newObject2 as Object = Activator.CreateInstance(egLabel.GetType)
newObject1 is now a textbox
newObject2 is now a label

Implementing ITemplate and accesing control properties

I'm trying to develop a custom GridView control with properties OpenFormModal and ModalWindowWidth and ModalWindowHeight and a few more.
From CustomGridView class I call an instance of CustomGVITemplate:
Protected Overrides Function CreateColumns(ByVal dataSource As PagedDataSource, ByVal useDataSource As Boolean) As ICollection
Dim columnList As ICollection = MyBase.CreateColumns(dataSource, useDataSource)
Dim cmdDel As New TemplateField
cmdDel.ItemTemplate = New CustomGVITemplate(ListItemType.Item, "delete")
'I CAN'T ASSING VALUE TO CUSTOM PROPERTIES HERE
list.Add(cmdDel)
End Function
The thing is, I should access CustomGridView properties from within InstantiateIn sub inside CustomGVITemplate class, the only way I know to do it is pass these parameters through
New CustomGVITemplate(ListItemType.Item, "delete", ALL-OTHER-PROPERTIES-HERE)
I don't like this solution as I'm forced to do a lot of Optional parameters so not all calls use all properties, also, I can't find the way to define properties in CustomGVITemplate and asign values to them.
Other possible solutions?
Thank you
SOLVED: The thing was I was trying to access values and proerties in CreateColumns event, when data hasn't been binded yet, the solution was to create CommandButton (or Button) in CreateColumns events and access properties and DataKeys later, in RowCommand or button OnClick events.

How to enable/disable web elements of a parent aspx page from the child ascx page?

I have an aspx page with three web controls: one to control the List Users page, one to control the Edit Users page, and one to control the Add User page. I have discovered a method for accessing these elements, but it seems to be limited. Here is what I have done:
Protected Sub editUser(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewEditEventArgs)
'set selected user from gridview.
Dim index As Integer = e.NewEditIndex
Dim userId As Integer = gvListUsers.DataKeys(index).Value
Session.Item("SelectedUserId") = userId
'show edit page, hide list and add page.
With Page.Form.Controls(1)
.Controls(getControlId("loadAddUser")).Visible = False
.Controls(getControlId("loadEditUser")).Visible = True
.Controls(getControlId("loadListUser")).Visible = False
End With
End Sub
The getControlId function looks like this:
Public Function getControlId(ByVal control As String) As Integer
Dim enumer As System.Collections.IEnumerator = Page.Form.Controls.Item(1).Controls.GetEnumerator
Dim i As Integer
For i = 0 To (Page.Form.Controls.Item(1).Controls.Count - 1)
If Page.Form.Controls(1).Controls.Item(i).ID = control Then
Return i
End If
Next
Return Nothing
End Function
This works in most cases. However, I am unable to access the "enabled" attribute of these web controls. Why is this, and how might I access that attribute?
Thanks :)
You could raise events from your UserControls which you subscribe to in the parent ASPX page. In the parent page event action you could enable/disable your controls,
Here's an example of events in UserControls: http://codebetter.com/blogs/brendan.tompkins/archive/2004/10/06/Easily-Raise-Events-From-ASP.NET-ASCX-User-Controls.aspx
Something else to think about: are you getting any benefit from moving this code into usercontrols? Would any of the individual controls be re-usable on their own? Creating tightly coupled controls that rely on each other being present doesn't give you much re-usability of the individual controls.
Visible is a property provided by the System.Web.UI.Control class, which is why you can access it directly. Enabled is not a property on this class, so you need to map the control object to a variable of the type of your custom control class if you want to access the Enabled property.
Dim myControl As TheAddUserControl
With Page.Form.Controls(1)
myControl = .Controls(getControlId("loadAddUser"))
myControl.Enabled = False
.Controls(getControlId("loadEditUser")).Visible = True
.Controls(getControlId("loadListUser")).Visible = False
End With
To expose an Enabled property in you user control:
Public Property Enabled As Boolean
Get
Return (Child1.Enabled And Child2.Enabled And Child3.Enabled)
End Get
Set(ByVal value As Boolean)
Child1.Enabled = value
Child2.Enabled = value
Child3.Enabled = value
End Set
End Poperty

Inheriting DropDownList and adding custom values using its DataSourceObject

I'm inheriting a DropDownList to add two custom ListItems. The first item is "Select one..." and the second item gets added at the end, it's value is "Custom".
I override DataBind and use the following code:
Dim data As List(Of ListItem) = CType(DataSource, List(Of ListItem))
data.Insert(0, New ListItem("Select one...", SelectOneListItemValue))
If DisplayCustomOption Then
data.Insert(data.Count, New ListItem("Custom", CustomListItemValue))
End If
DataSource = data
MyBase.DataBind()
The problem is this code won't work if the DataSource is anything other than a List of ListItem. Is there a better way of doing this?
You could make the assumption that the data source always inherits IList, in which case you could do the following:
Dim data As IList = CType(DataSource, IList)
data.Insert(0, New ListItem("Select one...", SelectOneListItemValue))
' And so on...
Of course, this assumes that whatever the data source is, it allows you to add objects of the type ListItem. But this might be generic enough for what you need.
You could just leave the databind alone and add your special Items in the DataBound event handler.
Protected Sub MyDropDownList_DataBound(sender As Object, e As EventArgs) _
Handles MyDropDownList.DataBound
MyBase.Items.Insert(0, New ListItem("Select One...", SelectOneListItemValue))
If DisplayCustomOption Then
MyBase.Add(New ListItem("Custom", Custom))
End If
End Sub
(My VB.NET is limited, so you may need to adjust syntax)

Problem while Creating Dynamic ModalPopup

i want to create a modalpopup dynamically but i come across a problem.I pasted my sub here and i dont know what to do for that problem.When i want to show modalpopup,it says
"Control 'mdldelete2' of type 'ModalPopupExtender' must be placed inside a form tag with runat=server." How can i solve this?
Public Sub Raise_Alarm(ByRef p_Page As Page,
ByRef p_AssignedButton As System.Web.UI.WebControls.Button,
ByVal p_Message As String)
Dim mdldelete2 As Global.AjaxControlToolkit.ModalPopupExtender =
p_Page.Page.FindControl("mdldelete2")
If mdldelete2 Is Nothing Then
mdldelete2 = New Global.AjaxControlToolkit.ModalPopupExtender
End If
With mdldelete2
.TargetControlID = p_AssignedButton.ID
.PopupControlID = "pnlDelete"
.ID = "mdldelete2"
.BackgroundCssClass = "modalBackground"
.OkControlID = "btnDeleteOk"
.CancelControlID = "btnDeleteCancel"
End With
p_Page.Controls.Add(mdldelete2)
Dim mylabel As Label
mylabel = p_Page.FindControl("lblStatus")
mylabel.Text = p_Message
mdldelete2.Show()
End Sub
Really, you should be adding the mdldelete2 control to the Controls collection of the Form control, rather than the Page directly - that might help.
I often find it's easier to add a PlaceHolder control to the page for this sort of thing - it doesn't add anything directly to the page, but gives you a named container to find and add controls to.
Also, just a point - if you did find an instance of the control with the Page.FindControl method, then you don't need to add it to a form collection again, as it's already in there.
Looks like you need to add a ScriptManager control to the aspx
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>

Resources