UPDATE: I modified the article after tweaking the code some to make it more efficient. Instead of passing the entire parent control, I simply pass the control collection associated to the parent.
This is a solution I came up with to handle the issue of dynamic casting of controls. In this case I had a situation where I needed to be able to specify a control or form parent control collection and the name of the control I wanted to emulate and access the properties of. I wanted to be able to use a dynamic object to access the properties of an object embedded within a form without having to hard code any specific values associated to identifying that control.
Here's the actual class that implements the generic type that I will use to cast a located control from. The generic variable is itemType. I loop through the parent collection of controls and locate the control I seek to emulate as a Control type. Once found, perform a DirectCast to cast from Control type to the generic itemType. The function then returns the itemType specified in the object instantiation :
VB.NET
Public Class NewGenericControl(Of itemType As {Control, New})
Public Sub New()
End Sub
Public Function GetControlByName(ByVal controls As Control.ControlCollection, ByVal ctlName As String) As itemType
Dim newCtl As New itemType
' Loop trhough the controls on the parent to locate the desired control to manage
For Each ctl As Control In controls
If (ctl.Name.StartsWith(ctlName)) Then
newCtl = DirectCast(ctl, itemType)
Return newCtl
End If
Next ctl
Return newCtl
End Function
End Class
C#
public class NewGenericControl<itemType> where itemType : Control, new()
{
public NewGenericControl()
{
}
public itemType GetControlByName(Control.ControlCollection controls, string ctlName)
{
itemType newCtl = new itemType();
// Loop trhough the controls on the parent to locate the desired control to manage
foreach (Control ctl in controls) {
if ((ctl.Name.StartsWith(ctlName))) {
newCtl = (itemType)ctl;
return newCtl;
}
}
return newCtl;
}
}
Here's the code that accesses the class by specifying a control type. It's only two lines of code. In this case I am emulating a PictureBox that I used to act as a button. As you can see, I'm accessing the Enabled property of the control itself through the generic instance of the control:
VB.NET
Dim splitContainer As New NewGenericControl(Of ucQuestionManager)
splitContainer.GetControlByName(Me.TabPage2.Controls, "ucQuestionManager").JumpToQuestion(questionId)
C#
NewGenericControl<ucQuestionManager> splitContainer = new NewGenericControl<ucQuestionManager>();
splitContainer.GetControlByName(this.TabPage2.Controls, "ucQuestionManager").JumpToQuestion(questionId);
Here's another example with a TreeView control that was embedded in a SplitContainer panel control inside the form:
VB.NET
Dim splitContainer As New NewGenericControl(Of SplitContainer)
Dim newTree As New NewGenericControl(Of TreeView)
newTree.GetControlByName(DirectCast(splitContainer.GetControlByName(m_parent.ParentForm.Controls, "SplitContainer1").Panel1, Control).Controls, "treeAnswerList").Nodes(Me.QuestionId).Nodes.Add(1, m_answerValue)
C#
NewGenericControl<SplitContainer> splitContainer = new NewGenericControl<SplitContainer>();
NewGenericControl<TreeView> newTree = new NewGenericControl<TreeView>();
newTree.GetControlByName(((Control)splitContainer.GetControlByName(m_parent.ParentForm.Controls, "SplitContainer1").Panel1).Controls, "treeAnswerList").Nodes(this.QuestionId).Nodes.Add(1, m_answerValue);
As you can see you can directly access embedded controls even by passing in an emulated instance of the parent container control! Sweet...
1 comment:
What a freaking nerd! :-P
Post a Comment