Hi,
I used
MDI Tabbed mode in my application,
and I want to catch some event when I switch window. I overrided method OnViewChanged() in my ViewController, but this is executed only if I open new window: http://www.elvacsolutions.eu/linked/video/tabSwitch.htm.
What's the best way?
Thanks for your advice.
How to handle the moment when an active tab is changed in Tabbed MDI mode
Answers approved by DevExpress Support
To accomplish this task, you can handle the DocumentManager.View.DocumentActivated event. Use the approach described in the following article to access the DocumentManager component: How to: Access the Document Manager.
You can also reuse the functionality provided by our WinWindowTemplateController:
C#public class MyWinWindowTemplateController : WinWindowTemplateController {
protected override void OnDocumentActivated(DevExpress.XtraBars.Docking2010.Views.DocumentEventArgs e) {
base.OnDocumentActivated(e);
if (e.Document.Form is IViewHolder) {
View activeView = ((IViewHolder)e.Document.Form).View;
}
}
}
Here is an example of how to handle the DocumentActivated event in older XAF versions:
C#using DevExpress.ExpressApp.Templates;
using DevExpress.ExpressApp.Win.Templates;
public class MainWindowController : WindowController {
public MainWindowController() {
TargetWindowType = WindowType.Main;
}
protected override void OnActivated() {
base.OnActivated();
Frame.TemplateChanged += Frame_TemplateChanged;
}
void Frame_TemplateChanged(object sender, EventArgs e) {
if (((IModelOptionsWin)Application.Model.Options).UIType == UIType.TabbedMDI && Frame.Template is IXafDocumentsHostWindow) {
((IXafDocumentsHostWindow)Frame.Template).DocumentManager.ViewChanged += DocumentManager_ViewChanged;
((IXafDocumentsHostWindow)Frame.Template).DocumentManager.ViewChanging += DocumentManager_ViewChanging;
}
}
void DocumentManager_ViewChanging(object sender, DevExpress.XtraBars.Docking2010.ViewEventArgs args) {
args.View.DocumentActivated -= View_DocumentActivated;
}
void DocumentManager_ViewChanged(object sender, DevExpress.XtraBars.Docking2010.ViewEventArgs args) {
args.View.DocumentActivated += View_DocumentActivated;
}
void View_DocumentActivated(object sender, DevExpress.XtraBars.Docking2010.Views.DocumentEventArgs e) {
if (e.Document.Form is IViewHolder) {
View activeView = ((IViewHolder)e.Document.Form).View;
}
}
protected override void OnDeactivated() {
base.OnDeactivated();
Frame.TemplateChanged -= Frame_TemplateChanged;
if (Frame.Template is IXafDocumentsHostWindow) {
((IXafDocumentsHostWindow)Frame.Template).DocumentManager.ViewChanged -= DocumentManager_ViewChanged;
((IXafDocumentsHostWindow)Frame.Template).DocumentManager.ViewChanging -= DocumentManager_ViewChanging;
}
}
}
Here is an example for older XAF versions that use the previous version of our frame templates:
C#public class MainWindowController : WindowController {
public MainWindowController() {
TargetWindowType = WindowType.Main;
}
protected override void OnActivated() {
base.OnActivated();
Frame.TemplateChanged += new EventHandler(Frame_TemplateChanged);
}
void Frame_TemplateChanged(object sender, EventArgs e) {
if (((IModelOptionsWin)Application.Model.Options).UIType == UIType.TabbedMDI && Frame.Template is MainFormTemplateBase) {
((MainFormTemplateBase)Frame.Template).DocumentManager.View.DocumentActivated += new DevExpress.XtraBars.Docking2010.Views.DocumentEventHandler(View_DocumentActivated);
}
}
void View_DocumentActivated(object sender, DevExpress.XtraBars.Docking2010.Views.DocumentEventArgs e) {
if (e.Document.Form is XtraFormTemplateBase) {
View activeView = ((XtraFormTemplateBase)e.Document.Form).View;
XtraMessageBox.Show(activeView.Id);
}
}
protected override void OnDeactivated() {
base.OnDeactivated();
Frame.TemplateChanged -= new EventHandler(Frame_TemplateChanged);
}
}
Hi!
This doens't work for me. if (e.Document.Form is IViewHolder)
is always false. I'm using templates. Does it mess it up?
Thanks
@Edilson: This example is intended for the new WinForms templates (WinApplication.UseOldTemplates = false). So, either ensure this condition or use another example for the old templates, which is also given above. If neither works for you, please submit a separate ticket via the Support Center (https://www.devexpress.com/Support/Center/Question/Create) and attach your problematic sample for us to debug it. Thanks.
I am afraid there is no universal solution for this task. Probably it will be required to use the DocumentManager's events. Would you please describe your task in greater detail so that we can suggest the most appropriate solution for you?
Hello. I will use a different way to solve my problem. Thanks for the reply.
Hi, in my WindowController (TargetWindowType window is Main) I caught the event MdiChildActivate from MainFormTemplateBase. I need access to the current View (at least for the View.Id) at invocation. When I use Frame.View so View is null.
Here is my code:
public TestWindowController()
{
InitializeComponent();
this.TargetWindowType = DevExpress.ExpressApp.WindowType.Main;
RegisterActions(components);
}
MainFormTemplateBase test = null;
protected override void OnActivated()
{
base.OnActivated();
Window.TemplateChanged += new EventHandler(Window_TemplateChanged);
}
void Window_TemplateChanged(object sender, EventArgs e)
{
test = Window.Template as MainFormTemplateBase;
if (test != null)
{
test.MdiChildActivate += new EventHandler(test_MdiChildActivate);
}
}
public event EventHandler<EventArgs> ViewSwitched;
void test_MdiChildActivate(object sender, EventArgs e)
{
//Frame.View is null
}
The Frame property of your controller returns the main window. This window does not contain a view. View is placed on a child window that represents a tab in the main window. So, you need to access the child Frame to get the view. From my point of view, it is better to create a WindowController for the child Frame and access the main frame's DocumentManager from it via the XafApplication.MainWindow property.
Hello, when I use window controller to Child Frame - event ‘Window_TemplateChanged’ will always invocation for the opening of a new View and event MdiChildActivate will registration on all open views. When I click to some opened view - event MdiChildActivate will invocation many times. I want from the window controller for the Main Window to find which View was activated. Or some other way to achieve the invocation of the some event at view controller for each click on this view in a tabbed UI.
Thank you very much for help.
I was directed here from Q439075. I'm having the exact same issue as Frank. I tried capturing the selected page changing from the tabbedmdimanager. I had the following in my event but the view periodically throws a null reference even if i check to ensure the mdichild is a detailviewform and the view is not null.
ISupportMdiContainer container = Frame.Template as ISupportMdiContainer;
(container.TabbedMdiManager.SelectedPage.MdiChild as DetailViewForm).View