简体   繁体   English

访问动态加载的用户控制方法

[英]Access dynamically loaded user control methods

I'm stuck in a problem and would appreciate any help or pointers I can get.我遇到了一个问题,希望得到任何帮助或指示。 I'm trying to develop an application that based on a user choice, loads a given user control to gather some info.我正在尝试开发一个基于用户选择的应用程序,加载给定的用户控件以收集一些信息。 All of the user controls are custom made but all of them have the same public methods - clear, get a string value, etc. During the execution of the application I need to be able to call those methods.所有的用户控件都是定制的,但它们都有相同的公共方法——清除、获取字符串值等。在应用程序的执行过程中,我需要能够调用这些方法。 This is what I've tried:这是我尝试过的:

public partial class frmDesktop : Form
{
    private UserControl active = new UserControl;

    private UserControl GetActiveUsrCtrl(AppEnum.Catalog catalogId, frmMain parent)
    { 
        UserControl ctrl= null;

        switch (catalogId)
        {
            case AppEnum.Catalog.XYZ_Catalog:
                 XYZCtrl _XYZCtrl = new XYZCtrl(parent);
                 ctrl = _XYZCtrl;
                 break;

            case ...
        }
        return ctrl;
    }

    private void frmDesktop_Load(object sender, EventArgs e)
    {
        ...
        // load the user control into the panel
        activeCtrl = GetActiveUsrCtrl(catalogId, parent);
        pUserControlContainer.Controls.Add(activeCtrl);
        ...
    }

I'm trying to keep things simple and small so in “GetActiveUsrCtrl” I use an empty user control and assign my control to it.我试图让事情变得简单和小,所以在“GetActiveUsrCtrl”我使用一个空的用户控件并将我的控件分配给它。

This works and loads the desired user control into a panel, as expected.这可以正常工作并将所需的用户控件加载到面板中,如预期的那样。

The problem I'm having is calling the public methods of the control.我遇到的问题是调用控件的公共方法。 Because of the way I loaded the user control, when I try to use reflection to invoke the method I get a NullReferenceException .由于我加载用户控件的方式,当我尝试使用反射来调用该方法时,我得到一个NullReferenceException

Bellow it's an example of the code I'm using:下面是我正在使用的代码示例:

Private void button1_Click(object sender, EventArgs e)
{
    Type tp = null;
    MethodInfo mtd = null;
    tp = hActiveUsrCtrl.GetType();
    mtd = tp.GetMethod("GetData");
    string Criteria = (mth.Invoke(hActiveUsrCtrl, null)).ToString();
}

Is what I'm trying here even possible?我在这里尝试的甚至可能吗?

Thanks.谢谢。

Create an interface containing all your controls methods创建一个包含所有控件方法的界面

public interface IMyControl
{
 public void clear();
 public string getastringvalue();
 etc......
}

Get all your controls to inherit from this interface:获取所有控件以从该界面继承:

public class MyControl : UserControl, IMyControl

Cast all your controls to the interface:将所有控件投射到界面:

private void button1_Click(object sender, EventArgs e)
{
    IMyControl typedControl = hActiveUsrCtrl as IMyControl;
    typedControl.Clear();
    etc...
}

On a side not Reflection is inefficient and should be avoided where possible!另一方面,反射效率低下,应尽可能避免!

UserControls are implemented as classes, so you can have that class implement an interface, and just call the GetData method that way. UserControls 是作为类实现的,因此您可以让该类实现一个接口,并以这种方式调用 GetData 方法。

public interface IGetData {
  string GetData(parameters ...);
}

public class MyUserControl : UserControl, IGetData {
  ...
}

If all the User Controls can have the same signature for the GetData method, you don't even have to figure out which type it is, just cast it to IGetData.如果所有用户控件都可以具有相同的 GetData 方法签名,则您甚至不必弄清楚它是哪种类型,只需将其强制转换为 IGetData。

IGetData getable = activeCtrl as IGetData;
if (getable != null) {
  var data = getable.GetData(...);
  // do stuff with data
} else {
  throw new ApplicationException("activeCtrl was null or didn't implement IGetData");
}

Update:更新:

If I understand, it looks like you need an intermediate variable.如果我理解,看起来您需要一个中间变量。

// newUc implements IGetData, not hActiveUsrCtrl
IGetData newUc = hActiveUsrCtrl.GetActiveUsrCtrl(pare‌​nt.appInfo.catalogId, parent);
pUserControlContainer.Controls.Add((Control)newUc);

var data = newUc.GetData(parameters ...);

If all control have the same public methods etc., why do you not use an interface?如果所有控件都具有相同的公共方法等,为什么不使用接口?

You may implement a control factroy class ControlFactory.GetUserSelectionControl() .您可以实现控制工厂类 ControlFactory.GetUserSelectionControl() 。 This method creates at runtime the best control matching the selection of the user.此方法在运行时创建与用户选择相匹配的最佳控件。 You can pass in an input of a kind to identify the best control.您可以传入一种输入来识别最佳控件。 And all controls implement in your case the same interface.并且所有控件都在您的情况下实现相同的界面。 Then you can directly call the methods without reflection.然后你可以直接调用这些方法而无需反射。 But in the meantime you got already an example on how to implement the interfaces.但与此同时,您已经获得了有关如何实现接口的示例。

If all the user control have the same methods, declare an interface, inherit from it, and cast to the interface.如果所有用户控件都具有相同的方法,则声明一个接口,从它继承,并强制转换为该接口。

something along the lines of :类似的东西:

ascx.cs file : ascx.cs 文件:

public partial class AleaPoisson : UserControl, ISymboleAlea {
public void SomeFunction();
...
}

aspx.cs file : aspx.cs 文件:

( conteneur should be a PlaceHolder control and it should be loaded on Page_Init, rather than Page_Load if possible ) (conteneur 应该是一个 PlaceHolder 控件,它应该在 Page_Init 上加载,如果可能的话,而不是 Page_Load )

var ctl = conteneur.Page.LoadControl( path );
conteneur.Controls.Add( ctl );
((ISymboleAlea)ctl).SomeFunction();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM