Posted By: DCMonkey | Aug 6th @ 2:31 PM
page 1 of 1
Comments: 6 | Views: 918
DCMonkey
DCMonkey
Monkey see, monkey do, monkey will destroy you!
We've had various discussions about MDI and MDI-like UI and WPF here and in the Coffeehouse before, and I've seem some mention they've done it using UserControls as your forms/child windows. I'm curious about how you all are managing those UserControls. There are a couple of ways I could see to do it:

1) Just add them as new tabs in a TabControl. Easy, but it requires a 1-to-1 correspondence between tabs and UserControls, which may not always be what you want. I suppose you could hide the tabs though and provide an alternate UI for switching between them.

2) Write a custom ItemsControl (or Selector) with an item host that just stacks the items right on top of each other (ie: A single cell grid) and manage the visibility or ZIndex of the items. This might make it easier to implement some fancy switching behavior. A separate control would manipulate this ItemsControl to display the desired UserControl.

3) Manage the collection or collections of UserControls yourself and assign the active UserControl to the Content property of a single ContentControl. Strangely enough, even though the TabControl is an ItemsControl it appears to use a method similar to this to display the content of a selected tab item rather than something like method #2.

How are you tackling this?

figuerres
figuerres
???
or just design an app that does not use an MDI.

really.

you can, and 99.999% of time I think we should.

what do you see as needed an MDI ??
figuerres
figuerres
???

well "MDI" is multiple open child windows in a parent window.

so you are not looking for "MDI"  and if someone else calls it MDI they just got it wrong.

one thing you can do, I have used a version of this in an app is...

setup an Interface and a parent container, then have each "Task" or "Function" be a user control that impliments that Interface.

so you have an app "frame" with a big empty panel.

when a menu item or button bar button etc... need to "open" / "load" the task you create an instance of the user control and dock it in the panel.

you can keep a stack of ITaskPanel (if that's the name of the interface)

and when the user "closes" the one displayed you pop it off the stack and show the new top of stack.  that's if you need to chain forms like a => b => c and then back .

or for single tasks the stack can hold the "default Home" control that you return to.

that's one model that works very well.

 

figuerres
figuerres
???
well  not to say that there may not be a need to switch but first I'd make sure I had a good design, many times adding a label or some other control can tell the user the info that wuld have comne from the other "page" so to speak.

but *IF* you need a back and forth process then it sounds like a case for a "Wizzard" or a "Tab Pages" UI
I would take a look at the prism reference implementation by Microsoft.  Our solution was before prism came out, but essentially our architecture is very similar.  We utilize the MVP pattern and have the concept of a view host.  Basically in XAML you can specify where content should go by placing viewhosts.  Presenters can then inject a view into the view host dynamically.  A view host can itself be an items control that can host multiple views.  Also view hosts can be nested so that you can have a distinct presenter driving each particular view.

When you utilize this type of architecture doing something like you mentioned is trivial.  To open up a view all you do is instantiate a new copy of the presenter and specify the view host it should inject its view into.  This could be a tab itemscontrol.  Or it could be an itemscontrol that uses a custom template to give views a more MDI like feel within the container.

It is completely customizable.  Views are completely independent of Presenters and vice versa.  The only contract is in the data binding.

Lastly we have a separate service that takes care of navigation services.  So when the presenter injects its view, it does so through the navigation service.  This service takes care of remember history and so forth so that the user can go back & forth among the views.

The nice thing about this architecture is that the actual size of the supporting libraries are very minimal and very testable.  This follows good agile principles.