SCSF - MDI workspace a problémy s ním spjaté

MyEgo.cz

home foto blogy mywindows.cz kontakt

SCSF - MDI workspace a problémy s ním spjaté

Při použití MDI workspace v SCSF narazíte na pár problémů, které vám udělají pár vrásek na čele. Prvním z nich je, jak správně reagovat na zavření formuláře alias MDI okna pomocí klasického křížku.
Pokud se uzavírá View programově, tak se volá metoda OnCloseView definovaná v Presentru, která zavře View a případně ho i odstraní z WorkItem kolekce. Viz příklad:

CODE
   public void OnCloseView(){
        base.CloseView();//zavře View v aktivním workspace
        WorkItem.SmartParts.Remove(View);//odstraní View z kolekce
        if (View is IDisposable)
           ((IDisposable)View).Dispose();//Dispose View z paměti
  }


Avšak v případě X tlačítka se v podstatě provede jen první část a nedojde k odstranění View z SmartParts kolekce a k uvolnění. Předkládám, že toto je problém MDI a Windows workspace! Aby se View správně, nebo-li úplně zavřelo, musíme se přihlásit k odběru události na Parent formu alias MDI containeru v tomto případě. A to uděláme takto:
Přidáním odběru události zavření Parent formu v View.OnLoad metodě.

CODE
   if (ParentForm != null){
        ParentForm.FormClosed += new FormClosedEventHandler(this,OnParentFormClosed);
    }


a samozřejmě deklaraci akce jež se má v případě zavření Parent formu provést. V našem případě zavoláme výše použitou metodu OnViewClose v Presentru.

CODE
   protected virtual void OnParentFormClosed(object sender, FormClosedEventArgs e){
       if (e.CloseReason == CloseReason.UserClosing){
          presenter.OnCloseView();
       }
    }



Update:

Tak jsem zjistil, že to nepracuje tak jak by mělo a dochází k zacyklení pokud se formulář zavírá třeba pomocí tlačítka na formuláři. Dá se to vyřešit odhlášením odběru události FormClosed. Viz kód:

CODE
     private void btnClose_Click(object sender, EventArgs e)
      {
         if (ParentForm != null) {
            ParentForm.FormClosed -= new FormClosedEventHandler(OnParentFormClosed);
         }
         _presenter.OnCloseView();
      }


Moc elegantní řešení to není, protože pokud třeba zavíráme formulář ještě z toolbaru pomocí commandu, tak musíme řešit odhlášení této události i zde. To znamená, ten samý kód na dvou místech neboli porušení DRY konceptu.

Osobně vidím problém v tom, že CloseReason je stejná jak v případě uazvření přes X tlačítko na formu, tak přes programové uzavření. Třeba na něco příjdu.

Další problémek je při aktivaci View v MDI workspace. MDI workspace nemá dostupné přímo klasické Control vlastnosti, jako je třeba Title nebo Dock property. Proto se musí pro nastavení těchto vlastností použít buď SmartPartInfo nebo WindowSmartPartInfo, které se použijí jako druhý parametr pro metodu Show v daném workspace. Viz následující příklad:

CODE
       [CommandHandler(CommandNames.ShowLifeInfoList)]
                 public void OnShowLifeInfoList(object sender, EventArgs e)
                 {
                    SmartPartInfo partInfo = new SmartPartInfo(Constants.UIExtensionSiteNames.LifeInfoList, "Seznam SPORT");
                    LifeInfoListView view = WorkItem.SmartParts[Constants.UIExtensionSiteNames.LifeInfoList] as LifeInfoListView;
                    if (view == null) {
                       view = WorkItem.SmartParts.AddNew<LifeInfoListView>(Constants.UIExtensionSiteNames.LifeInfoList);
                       view.Dock = DockStyle.Fill;
                    }
                    WorkItem.Workspaces[Constants.WorkspaceNames.MdiWorkspace].Show(view, partInfo);
                 }



Aktuálně byl uvolněna první verze SCSF MDI Contrib Projectu. Tento projekt eliminuje některé známé problémy MDI workspace v SCSF, plus přináší některé další řešení, které stojí určitě za průzkum.


Nový komentář