Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/94.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 访问动态加载的用户控制方法_C#_User Controls - Fatal编程技术网

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

C# 访问动态加载的用户控制方法,c#,user-controls,C#,User Controls,我被困在一个问题中,如果能得到任何帮助或指点,我将不胜感激。 我正在尝试开发一个基于用户选择的应用程序,加载给定的用户控件以收集一些信息。 所有用户控件都是定制的,但它们都有相同的公共方法-清除、获取字符串值等。 在应用程序执行期间,我需要能够调用这些方法。 这就是我尝试过的: public partial class frmDesktop : Form { private UserControl active = new UserControl; private UserCo

我被困在一个问题中,如果能得到任何帮助或指点,我将不胜感激。 我正在尝试开发一个基于用户选择的应用程序,加载给定的用户控件以收集一些信息。 所有用户控件都是定制的,但它们都有相同的公共方法-清除、获取字符串值等。 在应用程序执行期间,我需要能够调用这些方法。 这就是我尝试过的:

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

下面是我正在使用的代码示例:

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();
}
我在这里尝试的可能吗


谢谢。

用户控件是作为类实现的,因此您可以让该类实现一个接口,并以这种方式调用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 ...);

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

您可以实现ControlFactory.GetUserSelectionControl()类的控件。此方法在运行时创建与用户选择相匹配的最佳控件。您可以传入某种类型的输入,以确定最佳控件。
在您的案例中,所有控件都实现相同的接口。然后您可以直接调用这些方法而无需进行反射。但与此同时,您已经得到了一个如何实现接口的示例。

创建一个包含所有控件和方法的接口

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...
}
将所有控件强制转换到界面:

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

在非一侧,反射是低效的,应尽可能避免

如果所有用户控件都有相同的方法,则声明一个接口,从该接口继承并强制转换到该接口

大致如下:

ascx.cs文件:

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

(contenner应该是一个占位符控件,它应该加载到Page_Init,而不是Page_Load,如果可能的话)


你不必做反思。为什么不键入usercontrol并访问其属性,即
((MyUserControl1)hActiveUsrCtrl).MyMethod()我试图避免对每个用户控件都这样做-现在我有大约20个不同的控件,但我知道会有更多…我一定错过了一些东西。。。我声明了接口,在用户控件上继承了它,将GetActiveUsrCtrl更改为IUsrCtrl GetActiveUsrCtrl,并使用pUserControlContainer.controls.Add((control)hActiveUsrCtrl.GetActiveUsrCtrl(parent.appInfo.catalogId,parent))加载了用户控件;尽管如此,当我尝试使用。。。IUsrCtrl typedControl=hActiveUsrCtrl作为IUsrCtrl;如果(typedControl!=null)typedControl.Clear();否则抛出新的ApplicationException(“Ctrl为null或未实现接口方法”);typedControl始终为空..}