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

时间:2013-03-18 13:22:12

标签: c# user-controls

我遇到了问题,并且会感谢我能得到的任何帮助或指示。 我正在尝试开发一个基于用户选择的应用程序,加载给定的用户控件来收集一些信息。 所有用户控件都是自定义的,但它们都具有相同的公共方法 - 清除,获取字符串值等。 在执行应用程序期间,我需要能够调用这些方法。 这就是我尝试过的:

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);
        ...
    }

我正在努力保持简单和小巧,所以在“GetActiveUsrCtrl”我使用一个空的用户控件并将控件分配给它。

这可以正常工作并将所需的用户控件加载到面板中。

我遇到的问题是调用控件的公共方法。 由于我加载用户控件的方式,当我尝试使用反射来调用方法时,我得到NullReferenceException

Bellow它是我正在使用的代码的一个例子:

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();
}

我在这里尝试甚至可能吗?

感谢。

4 个答案:

答案 0 :(得分:0)

UserControls是作为类实现的,因此您可以让该类实现一个接口,并以这种方式调用GetData方法。

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

public class MyUserControl : UserControl, 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");
}

<强>更新

如果我理解,看起来你需要一个中间变量。

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

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

答案 1 :(得分:0)

如果所有控件都有相同的公共方法等,为什么不使用界面?

您可以实现一个控制factroy类ControlFactory.GetUserSelectionControl()。此方法在运行时创建与用户选择匹配的最佳控件。您可以传入一种输入以识别最佳控件。 并且所有控件都在您的情况下实现相同的接口。然后你可以直接调用方法而不用反射。但与此同时,你已经有了一个如何实现接口的例子。

答案 2 :(得分:0)

创建一个包含所有控件方法的界面

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

让所有控件继承自此界面:

public class MyControl : UserControl, IMyControl

将所有控件投射到界面:

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

一方面反思效率非常低,应该不惜一切代价避免!

答案 3 :(得分:0)

如果所有用户控件都具有相同的方法,则声明一个接口,继承它并转换为接口。

类似于:

... ascx.cs文件:

公共部分类AleaPoisson:UserControl,ISymboleAlea { public void SomeFunction(); ... }

aspx.cs文件:

(conteneur应该是PlaceHolder控件,它应该加载到Page_Init,而不是Page_Load,如果可能的话)

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