2013-03-18 31 views
1

我陷入了一個問題,並會感謝任何幫助或指針,我可以得到。 我想開發一個基於用戶選擇的應用程序,加載給定的用戶控件來收集一些信息。 所有的用戶控件都是自定義的,但它們都具有相同的公共方法 - 清除,獲取字符串值等。 在執行應用程序期間,我需要能夠調用這些方法。 這是我已經試過:訪問動態加載的用戶控制方法

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

是什麼,我想在這裏甚至可能嗎?

謝謝。

+2

你不必做反思。你爲什麼不用類型化你的用戶控件並訪問它的屬性,例如'((MyUserControl1)hActiveUsrCtrl).MyMethod();' – 2013-03-18 13:28:20

+0

我試圖避免爲每一個用戶控件做這個 - 現在我有大約20不同的,但我知道會有更多... – user2139806 2013-03-18 13:33:03

回答

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 ...); 
+0

我必須缺少一些東西......我聲明瞭接口,繼承它在用戶控件上,將GetActiveUsrCtrl更改爲IUsrCtrl GetActiveUsrCtrl並使用pUserControlContainer.Controls加載用戶控件。添加((Control)hActiveUsrCtrl.GetActiveUsrCtrl(parent.appInfo.catalogId,parent));然而,當我嘗試調用該方法... IUsrCtrl typedControl = hActiveUsrCtrl as IUsrCtrl; if(typedControl!= null)typedControl.Clear(); 否則拋出新的ApplicationException(「Ctrl爲null或沒有實現接口方法」); typedControl始終爲空。 } – user2139806 2013-03-18 15:58:34

+0

更新是否有幫助? – 2013-03-18 18:58:32

0

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

您可以實現一個控制factroy類ControlFactory.GetUserSelectionControl()。此方法在運行時創建匹配用戶選擇的最佳控件。您可以傳入某種輸入來確定最佳控制。 並且所有的控件在你的情況下實現相同的接口。然後你可以直接調用方法而不用反射。但同時你已經有了一個關於如何實現接口的例子。

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

一邊不是反射非常低效,應該不惜一切代價避免!

0

如果所有用戶控件都具有相同的方法,則聲明一個接口,從它繼承並轉換爲接口。

東西沿着線:

... ascx.cs文件:

公共部分類AleaPoisson:用戶控件,ISymboleAlea { 公共無效SomeFunction(); ... }

aspx.cs文件:

(conteneur應該是一個佔位符控制並且應該在Page_Init被加載,而不是的Page_Load如果可能的話)

變種CTL = conteneur.Page .LoadControl(路徑); conteneur.Controls.Add(ctl); ((ISymboleAlea)ctl).SomeFunction();