2013-03-26 94 views
0

因此,我正在使用WinForms在C#中構建MDI應用程序。在這種情況下,我不能爲我的生活弄清楚如何遵循DRY。我在我的主菜單欄中使用toolstripmenuitems打開了新的MDI兒童。我已經重用了「NewChild」方法作爲每個事件的事件處理程序。我試圖不必爲每個子窗口重複自己,因爲它們都遵循相同的實例化模式。繼WinForms MDI子窗口乾燥

我研究過泛型並使用Type類,但它並不真正讓我想要的地方。理想情況下,我只想說

// etc... 
    TypeOfForm = ConfigurationForm; 
} 

new TypeOfForm(); 

但我不認爲這種失去語言結構存在。

public partial class MainForm : Form 
{ 
    private AboutForm aboutForm; 
    private ConfigurationForm configForm; 
    private ResultsForm resultForm; 
    private LogForm logForm; 

    private void NewChild(object sender, EventArgs e) 
    { 
     Form newForm; 

     if (sender == testConfigurationToolStripMenuItem) 
     { 
      if (configForm == null) 
      { 
       configForm = new ConfigurationForm(); 
      } 
      newForm = configForm; 
     } 
     else if (sender == resultsToolStripMenuItem) 
     { 
      if (resultForm == null) 
      { 
       resultForm = new ResultsForm(); 
      } 
      newForm = resultForm; 
     } 
     else if (sender == logToolStripMenuItem) 
     { 
      if (logForm == null) 
      { 
       logForm = new LogForm(); 
      } 
      newForm = logForm; 
     } 
     else 
     { 
      return; 
     } 

     newForm.MdiParent = this; 
     newForm.Disposed += new EventHandler(ChildDisposed); 
     newForm.Show(); 
    } 
} 

什麼是在這種情況下實施DRY的好方法?

+1

嘗試改變這一行'newForm.MdiParent = this;'''newForm.MdiParent = this.MdiParent;' – MethodMan 2013-03-26 17:39:41

+0

我很困惑,我從MDI父(this)創建這些子窗體,爲什麼要看在這個.mdiparent? – Paveway 2013-04-01 22:44:17

回答

1

我會盡量避免檢查類型。它確實混淆了代碼。

你真的想使用泛型這個公共代碼:

// for multiple instance forms (and instantiating a "singleton" form) 
private void AddNewChild<T>() where T: Form 
{ 
    T newForm = new T(); 
    newForm.MdiParent = this; 
    newForm.Disposed += new EventHandler(ChildDisposed); 
    newForm.Show(); 
} 

// for "singleton" forms 
private void ActivateChild<T>() where T: Form 
{ 
    // off-the-cuff guess, this line may not work/compile 
    var child = this.MdiChildren.OfType<T>().FirstOrDefault(); 

    if (child == null) 
    { 
     AddNewChild<T>(); 
    } 
    else 
    { 
     child.Show(); 
    } 
} 

// usage 
logToolStripMenuItem.Click += (s,e) => ActivateChild<LogForm>(); 
testConfigurationToolStripMenuItem.Click += (s,e) => ActivateChild<ConfigurationForm>(); 
multipleInstanceFormMenuItem.Click += (s,e) => AddNewChild<FormX>(); 
... 
+0

謝謝,這正是我正在尋找的,我不明白C#如何實現泛型。 – Paveway 2013-04-01 22:47:07

0

這裏有一個建議:

請與工具條的對象字典(或使用Tag屬性)和它們的匹配形式或形態類型

// you can't use the UI controls before Init, you could use their Tags 
// so this should be considered pseudo code 
private Dictionary<string, Type> ToolstripForms = new Dictionary<string, Type> 
{ 
    { testConfigurationToolStripMenuItem, typeof(ConfigurationForm) }, 
    { resultsToolStripMenuItem, typeof(ResultsForm) }, 
}; 

,並在您NewForm方法:

private void NewChild(object sender, EventArgs e) 
{ 
    Form newForm = null; 

    // some casting and exception handling would go well here 
    if (sender != null && ToolstripForms.ContainsKey(sender)) // or sender.Tag? 
    { 
     newForm = Activator.CreateInstance(ToolstripForms[sender]) as Form; 
    } 
    ... 
} 

您可能需要一種確定表單是否已經打開並專注的方法,而不是每次都打開一個新表單,但這取決於您。一種方法是在該字典中使用一對對象作爲值 - 類型和現有實例,儘管其他方法可能看起來更好。