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