How to set visibility on public property in VB.NET - asp.net

I am maintaining some old code, I am a c# developer.
We have a usercontrol with a tablecell that I want to hide with my code on my other aspx page. It is reference and all that good stuff.
But how do you write a property to set visibility in vb.net.
Something like this, but not working.
Public Property vis As TableCell
Get
LogoArea.Visible = False
End Get
Set(value As TableCell)
LogoArea.Visible = True
End Set
End Property

Use this instead:
Public Property LogoVisible As Boolean
Get
Return LogoArea.Visible
End Get
Set(value As Boolean)
LogoArea.Visible = value
End Set
End Property
This wraps around the Visible property of the LogoArea cell. Assuming it's a TableCell from your previous example, which is the web controls version, not the HtmlControls version.

Related

ASP.NET TreeView control - CheckedNodes is always empty

I have an ASP.NET TreeView control with the "ShowCheckboxes" state set to "All".
If I check the boxes on the tree, then the tree.CheckedNodes property is always "False".
I've also tried looking at the individual Nodes(i).Checked property, but those are also all false.
If I manually set the Checked property to True from code, then it does get reflected in the .CheckedNodes property.
I feel like I must be missing something obvious- why would this simple boolean property fail to reflect what I've done in the UI?
Protected Function GetChosenIDs() As List(Of Guid)
Try
Dim result As List(Of Guid) = New List(Of Guid)
'This loop never executes, because nothing is marked "Checked".
For Each node As TreeNode In tree.CheckedNodes
result.Add(New Guid(node.Value))
Next
Return result
Catch ex As Exception
Throw ex
End Try
End Function

Connect reusable ASP.NET WebControl to a method for loading data

I'm trying to create a control that can extend other webcontrols and set some properties like visible and enabled, based on user permissions.
Here's an example where your user role would need to include the "CanSave" permission:
<asp:Button ID="btn1" runat="server" Text="Save"/>
<myControls:PermissionsExtender runat="server" ControlToSet="btn1" Permission="CanSave"/>
I'm trying to keep this reusable, that's why the PermissionExtender is in a separate project that can not have any dependencies to other projects. To make a decision, the control of course needs to get this info from somewhere else (database or something). I made another control and, using events, the above extender will be set by a master control, so only that needs to know where to look up the information.
The master control now needs to be configured to know where the information about roles and permissions will be coming from. My idea was to have an interface inside the reusable project, and implement that somewhere else, then configure my control to go and find the class that implements the method I need and load it through reflection. But I'm unclear how this could work. I would probably place the master control in the masterpage and supply it a class name like PermissionClass="SecurityLibrary.PermissionsClass". Kinda like ObjectDatasource does it, but other suggestions are welcome.
The method signature would be like:
bool HasPermission(string permission)
It would know the current users role and using that combination, looks up if the role includes the permission.
How can I wire up a call from the control to a method inside my main project that can supply the necessary information without making them dependent.
I think I've got something that will work for you (tested fine for me but I may have misunderstood part of what you were looking for). With this implementation the asp.net designer code will look like this:
<web:PermissionMasterControl runat="server" ID="masterController" PermissionClass="SecurityLibrary.RandomPermissionClass" />
<asp:Button ID="btnSave" runat="server" Text="save" />
<web:PermissionExtender runat="server" ControlToSet="btnSave" Permission="CanSave" MasterControllerID="masterController" />
Now for the SecurityLibrary. Pretty straight forward, I included a simple "RandomPermissionClass" that randomly returns true/false.
Namespace SecurityLibrary
Public MustInherit Class PermissionClass
Public MustOverride Function HasPermission(ByVal permission As String) As Boolean
End Class
Public Class RandomPermissionClass
Inherits PermissionClass
Private rand As New Random()
Public Overrides Function HasPermission(permission As String) As Boolean
Return If(rand.Next(2) = 0, False, True)
End Function
End Class
End Namespace
Now we have the "myControls" library, which contains no references to SecurityLibrary. I created two controls and a delegate. The controls are "PermissionMasterControl" and "PermissionExtender". The delegate is what is used to actually perform the check against the reflected object.
Namespace myControls
Public Delegate Function HasPermissionDelegate(ByVal permission As String) As Boolean
Public Class PermissionMasterControl
Inherits System.Web.UI.Control
Public Property PermissionClass As String
Get
Return If(ViewState("PermissionClass") Is Nothing, "", ViewState("PermissionClass").ToString())
End Get
Set(value As String)
ViewState("PermissionClass") = value
End Set
End Property
Private ReadOnly Property PermissionDelegate As HasPermissionDelegate
Get
If _permissionDel Is Nothing Then
If Not String.IsNullOrEmpty(PermissionClass) Then
Dim t = Type.GetType(PermissionClass, False)
If t IsNot Nothing Then
_permissionObj = Activator.CreateInstance(t)
Dim mi As MethodInfo = _
t.GetMethod("HasPermission", BindingFlags.Public Or BindingFlags.Instance)
_permissionDel = [Delegate].CreateDelegate(GetType(HasPermissionDelegate), _permissionObj, mi)
End If
End If
End If
Return _permissionDel
End Get
End Property
Private _permissionObj As Object = Nothing
Private _permissionDel As HasPermissionDelegate = Nothing
Public Function HasPermission(ByVal permission As String) As Boolean
If PermissionDelegate Is Nothing Then
Throw New NullReferenceException("The specified permission class (" + PermissionClass + ") could not be loaded/found.")
End If
Return PermissionDelegate(permission)
End Function
End Class
Public Class PermissionExtender
Inherits System.Web.UI.Control
Public Property ControlToSet As String
Get
Return If(ViewState("ControlToSet") Is Nothing, "", ViewState("ControlToSet").ToString())
End Get
Set(value As String)
ViewState("ControlToSet") = value
End Set
End Property
Public Property Permission As String
Get
Return If(ViewState("Permission") Is Nothing, "", ViewState("Permission").ToString())
End Get
Set(value As String)
ViewState("Permission") = value
End Set
End Property
Public Property MasterControllerID As String
Get
Return If(ViewState("MasterControllerID") Is Nothing, "", ViewState("MasterControllerID").ToString())
End Get
Set(value As String)
ViewState("MasterControllerID") = value
End Set
End Property
Protected ReadOnly Property MasterController As PermissionMasterControl
Get
If _mastercontroller Is Nothing Then
_mastercontroller = Me.Page.FindControl(MasterControllerID)
End If
Return _mastercontroller
End Get
End Property
Protected ReadOnly Property ManagedControl As Control
Get
If _controlToSet Is Nothing Then
_controlToSet = Me.NamingContainer.FindControl(ControlToSet)
End If
Return _controlToSet
End Get
End Property
Private _controlToSet As Control = Nothing
Private _mastercontroller As PermissionMasterControl = Nothing
Protected Overrides Sub OnLoad(e As System.EventArgs)
MyBase.OnLoad(e)
Dim bResult As Boolean = MasterController.HasPermission(Permission)
ManagedControl.Visible = bResult
End Sub
End Class
End Namespace

ASP.NET Custom Control - Template Allowing Literal Content

I want my User Control to be able to have Literal Content inside of it. For Example:
<fc:Text runat="server">Please enter your login information:</fc:Text>
Currently the code for my user control is:
<ParseChildren(True, "Content")> _
Partial Public Class ctrFormText
Inherits UserControl
Private _content As ArrayList
<PersistenceMode(PersistenceMode.InnerDefaultProperty), _
DesignerSerializationVisibility(DesignerSerializationVisibility.Content), _
TemplateInstance(TemplateInstance.Single)> _
Public Property Content() As ArrayList
Get
If _content Is Nothing Then
Return New ArrayList
End If
Return _content
End Get
Set(ByVal value As ArrayList)
_content = value
End Set
End Property
Protected Overrides Sub CreateChildControls()
If _content IsNot Nothing Then
ctrChildren.Controls.Clear()
For Each i As Control In _content
ctrChildren.Controls.Add(i)
Next
End If
MyBase.CreateChildControls()
End Sub
End Class
And when I put text inside this control (like above) i get this error:
Parser Error Message: Literal content ('Please enter your login information to access CKMS:') is not allowed within a 'System.Collections.ArrayList'.
This control could have other content than just the text, so making the Content property an attribute will not solve my problem.
I found in some places that I need to implement a ControlBuilder Class, along with another class that implements IParserAccessor.
Anyway I just want my default "Content" property to have all types of controls allowed in it, both literal and actual controls.
You need to set the ParseChildren attribute to "False", otherwise any content in your control will be parsed into the "Content" property. This does not meet your needs, as you want to have controls AND content.
In order to accomplish this, override the AddParsedSubObject method. Check for the parsed control type, and if it's a literal control, add it to your UserControl's Content property. If it's some other control, just add it to the Controls collection like usual.
At the end of parsing all your sub-objects, simply display the Content property in a literal control or a panel or something.

Validator Disappears on PostBack Inside Composite Control

This should be a simple problem to fix, as it uses the same way I fixed my last problem with FooControl (below).
Basically, I want to add a derived validator I made to this composite control. It works fine but on postback it just disappears in the markup, making me think it's lost its ViewState.
I am probably doing something wrong with instantiating it, but I've tried setting only the ControlToValidate, moving things around, and nothing works.
I've provided some surrounding code to see what's working and then what's not.
Private FooControl As IFooControl
Private Validator As MyValidator
Protected Overrides Sub CreateChildControls()
FooControl = FooControlProvider.CreateFooControl(blah)
Me.Controls.Add(FooControl.RetrieveControl())
' Begin Not Working
Validator = New MyValidator()
Me.Controls.Add(Validator)
Validator.ID = "MyValidatorID"
Validator.ControlToValidate = FooControl.ID
Validator.IsRequired = True ' Custom property
Validator.ErrorMessage = "Please select an answer"
' End Not Working
If Not DataSource Is Nothing Then
FooControlProvider.AssignDataSource(DataSource, FooControl)
End If
End Sub
I've found the problem. Apparently, on PostBack, no matter how you order the creation of the Validator, its display is set to None. I found this by breaking on the Render method and checking the Validator variable.
The solution (hack?) is to set the validator to your desired Display during the Render method.
Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
Validator.Display = ValidatorDisplay.Dynamic
MyBase.Render(writer)
End Sub

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

Resources