开发者

Reference a UserControl Class Based Off String Value

I current开发者_JS百科ly have the following code:

Dim ucAppName As UserControl_appName = CType(Parent.FindControl(strucParam(i).ParentFindControl), UserControl_appName)

How can I modify it so that "UserControl_appName" is not hard coded. I would like to pass it as a string. Thanks!


Hints:

You'll need to pass a System.Type to your method ...

You'll need to use Object.GetType() and also the typeof operator. You can also create an instance of a Type of a class by using its qualified name if its in the currently executing assembly OR the AssemblyQualifiedName

Basic idea below:

WebForm

<h2>Passing Types</h2>
<asp:Panel runat="server" ID="pnl1">
    <p>
        <asp:TextBox runat="server" ID="txt1" />
    </p>
    <p>
        <asp:DropDownList runat="server" ID="ddl1" />
    </p>
    <p>
        <asp:HyperLink runat="server" ID="hl1" Text="Link1" NavigateUrl="http://www.google.co.uk" Target="_blank" />
    </p>
</div>
<asp:Label runat="server" ID="lout" />
<div>
    <p>
        <asp:DropDownList runat="server" ID="ddlTypes">
        </asp:DropDownList>
        &nbsp;
        <asp:Button runat="server" ID="btnGetValueFromType" Text="Get Value By Control Type" onclick="btnGetValueFromType_Click" />
    </p>
</asp:Panel>

CodeBehind (Apologies, its been quite a while since I did any VB.net so this example is in C#)

    protected void Page_Load(object sender, EventArgs e)
    {
        if (! IsPostBack){
            buildGui();
        }
    }

    private void buildGui(){
        List<string> lstStrings = new List<string>(5);

        lstStrings.Add("one");
        lstStrings.Add("two");
        lstStrings.Add("three");
        lstStrings.Add("four");
        lstStrings.Add("five");

        ddl1.DataSource = lstStrings;
        ddl1.DataBind();

        //Populate the Types Dropdown with some fullyqualified type names (includes the assembly name,version number, PublicKey etc.)
        Dictionary<string, string> lstTypes = new Dictionary<string, string>(3);

        lstTypes.Add(this.ddl1.GetType().Name, this.ddl1.GetType().AssemblyQualifiedName);
        lstTypes.Add(this.txt1.GetType().Name, this.txt1.GetType().AssemblyQualifiedName);
        lstTypes.Add(this.hl1.GetType().Name, this.hl1.GetType().AssemblyQualifiedName);

        //lstTypes.Add(this.hl1.GetType().Name, this.hl1.GetType().AssemblyQualifiedName);
        lstTypes.Add(this.CRJunk01.GetType().Name, this.CRJunk01.GetType().AssemblyQualifiedName);

        ddlTypes.DataSource = lstTypes;
        ddlTypes.DataValueField = "value";
        ddlTypes.DataTextField = "key";
        ddlTypes.DataBind();
    }

    protected void btnGetValueFromType_Click(object sender, EventArgs e)
    {
        Type t = Type.GetType(ddlTypes.SelectedValue);

        lout.Text = "Looking for a type: " + t.ToString();

        foreach(Control c in this.pnl1.Controls){
            if (c.GetType().Equals(Type.GetType(ddlTypes.SelectedValue)))//Look for controls whose type is the same as the type selected in ddl1.
            {
                lout.Text += string.Format("<br/>Got Control of type: {0}", c.GetType().Name);
                //Cast to your custom Interface/BaseClass and extract the value.
                lout.Text += "<br/>Value is: " + ((ICrJunkControl)(c)).ControlValue;
            }
        }
    }

This is the sort of thing you'll probably need to 'leverage'.

On a final note, it will probably be best if all your custom controls inherit from a base class or an interface. That way, when you've located the object you want based on its type you can cast it to the interface or base class and then get the value of a bespoke shared member e.g. ControlValue. The implementation of your base classes will override this. This will help to overcome problems related to disparate controls having different members that expose their state.

e.g.

Textbox -> Text
DropdownList -> SelectedValue
Hyperlink -> Text/NavigateUrl

HTH,


Use an interface and implement it on your usercontrol. You can then cast your usercontrol to the interface and have all the common properties and methods available to you.

Public Interface ucInterface

    Property textbox() As String
    Function calculate() As Double

End Interface

Public Class UserControl_appName
    Inherits System.Web.UI.UserControl
    Implements ucInterface

    Public Function calculate() As Double Implements ucInterface.calculate
        Return 99 / 10
    End Function

    Public Property textbox() As String Implements ucInterface.textbox
        Get
            Return txtBox.text
        End Get
        Set(ByVal value As String)
            txtBox.text = value
        End Set
    End Property

End Class

Public Class Test
    Public Sub Test()

        Dim ucAppName As ucInterface = CType(Parent.FindControl(strucParam(i).ParentFindControl), ucInterface)

        ucAppName.textbox = "Test 1"
        ucAppName.calculate()

    End Sub
End Class


Check out system.Reflection. You can also retrieve objects from other assemblies, or even from referenced libraries. Of course, for this to work, you need to remember that this code returns a reference to an an "object". You will still have the poblem of either defining an interface which defeines the common implementaiton for all of your controls, or another means of type determination.

Imports System.Reflection
Public Class ObjectFactory
Public Shared Function NamedObject(ByVal ObjectName As String) As Object
    Dim Assem = [Assembly].GetExecutingAssembly()

    Dim MyType As Type = Assem.GetType(ObjectName.Trim)
    Dim MyObject As Object = Nothing
    Try
        MyObject = Activator.CreateInstance(MyType)
    Catch MyProblem As TargetInvocationException
        MessageBox.Show(MyProblem.ToString)
    End Try

    Return MyObject
End Function

End Class

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜