I have an application with various modules.
I have divided my main shell (xaml) into different regions and now I can load modules on those regions.
But I have requirement where in on click of some button I have to open a new window and then a new module will load on the new window.
I created a new window and I am opening that window , but the window is having a region which the RegionManager of main application does not recognize.
How do I load a module on a region which is not on main window but on child window ?
You can find a quick sample solution for your problem in the following SkyDrive public folder as "RegionInChildWindowWithNavigation":
RegionInChildWindowWithNavigation
Based on my understanding, the problem you mentioned would be related on setting the RegionManager property on the ChildWindow View that cause the defined ModalWindowRegion be reachable from the RegionManager. Below is the ModalDialog ChildWindow view constructor from the aforemention sample. Notice that it also adds an event handler to properly remove all the views in the ChildWindow when closed.
[ImportingConstructor]
public ModalDialog(IRegionManager rm)
{
this.rm = rm;
this.SetValue(RegionManager.RegionManagerProperty, rm);
InitializeComponent();
this.Closed += new EventHandler(WindowsView_Closed);
}
void WindowsView_Closed(object sender, EventArgs e)
{
while (rm.Regions["ModalWindowRegion"].Views.Count() > 0)
{
rm.Regions["ModalWindowRegion"].Remove(rm.Regions["ModalWindowRegion"].Views.FirstOrDefault());
}
}
Then, you would just need to RequestNavigate() to the specified Region which is defined in the ChildWindow view from the RegionManager as follows:
ModalDialogWindow.Show();
rm.RequestNavigate("ModalWindowRegion", new Uri("HelloWorldView", UriKind.Relative));
In addition, you may find useful the following CodePlex threads:
Define Region(s) in Childwindows using Prism + MVVM
Display Child window WPF
I hope this helps.
Related
I'm new to WPF Prism, I have seen many online article about Prism and I found all of example code are using windows application as shell, so I have a question, can i let UserControl as a shell? if not why?
The shell is supposed to be a window since a WPF application always has a top-level window (unless hosted in a broswer as an XBAP) but you could set the Content of the window to a user control in the InitializeShell() method of your bootstrapper:
protected override DependencyObject CreateShell()
{
return Container.Resolve<MainWindow>();
}
protected override void InitializeShell()
{
Application.Current.MainWindow.Content = new UserControl();
Application.Current.MainWindow.Show();
}
A UserControl must be hosted in a window or page. It is not a top-level control.
The Window can be opened alone; while the UserControl can’t. That is why the top-level window must be a Window.
The UserControl can also contains Regions. This allows you to nest a UserControl in another UserControl using Regions.
I am new in WPF and Prism. I'd like to know if I should create new bootstrapper for each new window? For Example I have "Window1" where I select element from ListBox and click button "ShowDetails" and in the new window "Window2" I should see the details of my selection. I have windows and modules for them, but I'd like to know how and where I can register the module "Module2" for "Window2"?
Example of my Bootstrapper.
class Bootstrapper : UnityBootstrapper
{
protected override DependencyObject CreateShell()
{
var mainWindow = new Window1();
mainWindow.Show();
return mainWindow;
}
protected override IModuleCatalog GetModuleCatalog()
{
var moduleCatalog = new ModuleCatalog();
moduleCatalog.AddModule(typeof(Module1));
return moduleCatalog;
}
}
"App.xaml.cs"
public partial class App : Application
{
public App()
{
var bootstrapper = new Bootstrapper();
bootstrapper.Run();
}
}
The Bootstrapper is used usually in the startup class of a WPF Application. Usually this will be the file App.xaml.cs in the standard template, which is the code-behind class of the App.xaml file. You override the method OnStartup and instantiate your Bootstrapper and call its run method. You can delay the startup of the bootstrapper until the override of OnStartup instead of writing this in the constructor of the App.xaml.cs class. You will then use the RegionManager in Prism and define regions in your XAML. If you have multiple independent Windows this is a bit different from the way Prism is intended to be used. There is the concept of a MainWindow or Shell which you define in the CreateShell method of the Bootstrapper class which is available in the Prism source code. Instead, have a main window and define regions and perhaps consider creating a mechanism for displaying additional windows in dialogs. It is possible partition up the MainWindow into multiple regions and inject user controls via the RegionManager. This is done via the activate method of the RegionManager.
Start up by reading the Patterns And Practices Guide and perhaps consider watching the videos of Mike Taulty upon Prism. The first video is here:
Prism & Silverlight: Part 1 - Taking Sketched Code Towards Unity
There are many videos in the video series (10 in total) that will help you get started with PRISM.
An example of how to define a region in XAML is shown next:
<ItemsControl Regions:RegionManager.RegionName="MainRegion" />
A PRISM region can be activated, e.g. through a DelegateCommand or ICommand bound to a button is the following code:
var viewA = new ViewA();
var regionA = (new RegionManager()).Regions["RegionA"];
regionA.Activate(viewA);
You will have to define multiple modules that implement the IModule Interface and add these to your ModuleCatalog as you already have done with ModuleA.
In my WPF application, I have a single Main window with a Grid. The Login and Shell are 2 separate UserControls added as children to a grid. I need to find out when the Shell is loaded and start a timer from the Main window.
I just need to know as to what event is raised when a UserControl is added using Grid.Children.Add method, so that I can check if Login is loaded or the Shell and start the timer.
I'm not quite sure what you're trying,
but it sounds like you're looking for the Load event:
UserControl MyControl = new UserControl();
MyControl.Loaded += new RoutedEventHandler(MyControl_Loaded);
public void MyControl_Loaded(object sender, RoutedEventArgs e)
{
if (((UserControl)sender).IsLoaded)
{
..... do something
}
}
Hope it helps
It is need to realize UI settings system - loading/saving some properites of UI elements (which can be modified by user in runtime) from/into persistent storage. For example:
DevExpress grid control - columns width's, visibility, summary area and so on (this control has set of methods pairs like RestoreLayoutFrom/SaveLayoutTo, but SaveLayoutToStream(Xml) doesnt work in grid.Unloaded handler - when grid is disconnected from PresentationSource)
grid rows/columns, which widths/heights can be adjusted by user via GridSplitter
sizeable popup controls
It is easy to set up controls properties from settings storage after controls loading/initializing/etc, but how catch the moment before controls unloading (when they still remains in visual tree) in order to retrieve their settings for saving?
Short description
I intend to create singleton - UISettingsManager, which inside has a Dictionary with pairs of [element Uid, element settings data]. In visual container (Window, UserControl) this manager can be used in a way like this:
public partial class PageHeader : UserControl
{
public PageHeader()
{
InitializeComponent();
UISettingsManager.RestoreSettings(myGridControl);
UISettingsManager.RestoreSettings(myPopup);
}
}
myGridControl & myPopup has unique Uid's (in application scope), so UISettingsManager can retrieve their settings from inner dictionary & apply it to the controls; of course UISettingsManager knows, how to work with some different types of controls.
But when it is the right moment to store settings of controls, which container is Window or UserControl?
I would use the Window's Closing event.
public class MyWindow : Window
{
public MyWindow()
{
this.Closing += new System.ComponentModel.CancelEventHandler(MyWindow_Closing);
}
void MyWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
// Save what I want to here
}
}
This would be the safest bet, because you will always, at some point, close the window.
However, there may be alternatives, including the Unloaded event for a user control.
I got my hands om MEF for a week now and I am trying to build up a WPF application that loads imported controls from MEF.
I created a WPF application project and removed the default window and application start up URI. Then I handled the application startup event to compose the application:
public partial class App : Application, IPartImportsSatisfiedNotification
{
{...}
private void App_Startup(object sender, StartupEventArgs e)
{
this.Compose();
}
public void Compose()
{
try
{
globalCatalog.Catalogs.Add(new DirectoryCatalog(extensionsDirectoryPath));
CompositionContainer container = new CompositionContainer(globalCatalog);
container.ComposeParts(this);
}
catch (Exception ex)
{
// Do something
}
}
{...}
}
Actually, when debugging and watching objects after imports are satisfied, everything has hierarchically composed fine like I wanted. But when I try to show up the MainWindow of the application an exception is thrown on MainWindow.Show() call:
"Specified element is already the logical child of another element. Disconnect it first."
Though my code in OnImportsSatisfied method seems fine as it is working when not using MEF mecanism:
public void OnImportsSatisfied()
{
Window mainWindow = new Window();
mainWindow.Content = this.importedControl;
this.MainWindow = mainWindow;
this.MainWindow.Show();
}
I insist on the fact that this works perfectly when not importing controls with MEF. What is surprising is that this code does not work too:
Window mainWindow = new Window();
//mainWindow.Content = this.importedControl;
this.MainWindow = mainWindow;
this.MainWindow.Show();
So I suspect that ComposeParts is doing a bit more than what it says as it is the only member acting on my actual application instance.
Hope someone can help me (Glenn?).
Thanks.
Edit:
I discovered that when I remove the IPartImportsSatisfiedNotification interface from my parts, no exception is thrown and the window shows up. But of course the window is empty as I need this OnImportsSatisfied method to set the DataContext of the window to its associated imported view model.
The sample applications of the WPF Application Framework (WAF) show how to use MEF within a WPF application.
I finally discovered that I was importing my WPF user controls by using the default ImportAttribute constructor, which in fact will make a shared instance of the class if the creation policy is not specified during export. And as many of my controls were implementing the same interface and I was binding them in my views, I was actually trying to add this shared user control instance to different visual elements, which is not permited by WPF (and so the exception).
I marked my imports using the RequiredCreationPolicy set to NonShared and everything got back in order! That was all about learning MEF...