Introduction
This tip will show you how to put your usual winforms (designed now) in a "view" which is the main container of XAF UI.
There are official guides as to how to show fully customized forms in XAF, but placing an Action over a view and showing window from there is the core of these guides.
The main disadvantage of this approach is that we cannot call it from the navigation menu and have to call it from ToolBar
or RibbonBar
. It doesn't make good sense for end users.
Background
I challenge the XAF dev guys and myself to find a generic solution for custom and complex form designing in XAF.
On the one hand, the benefits of XAF are hard to ignore and on the other hand, its limitations and rules are too maddening.
This tip is a partial result of this challenge.
Using the Code
The first step is creating controller that handles navigation pane behaviors. Controllers are classes to change XAF application's flow and implement custom end-user interaction.
This controller will change the default behavior of specific navigation item and show our custom view.
The mentioned controller must inherit from DevExpress.ExpressApp.SystemModule.ShowNavigationItemController
.
For rewriting default behavior, we need override ShowNavigationItem
method.
protected override void ShowNavigationItem(SingleChoiceActionExecuteEventArgs e)
{
if ((e.SelectedChoiceActionItem != null)
&& e.SelectedChoiceActionItem.Enabled.ResultValue
&& e.SelectedChoiceActionItem.Id == "the id of navigation node ")
{
Frame workFrame = Application.CreateFrame(TemplateContext.ApplicationWindow);
View v = new BaseView(typeof(Custom Form ),"Caption","ID of View");
workFrame.SetView(v);
e.ShowViewParameters.TargetWindow = TargetWindow.Default;
e.ShowViewParameters.CreatedView = v;
return;
}
base.ShowNavigationItem(e);
}
The above code causes specified navigation item, shows our custom view.
The next step is defining the BaseView
class.
class BaseView : DevExpress.ExpressApp.View
{
Form frm;
public BaseView(Type Frm, string Caption, string ID)
: base(true)
{
if (Frm == null)
throw new Exception("Form is null or invalid");
if (!Frm.IsSubclassOf(typeof(Form)))
{
throw new Exception("Form is null or invalid");
}
frm = (Form)Activator.CreateInstance(Frm);
this.Id = ID;
this.Caption = Caption;
this.CurrentObject = null;
}
protected override object CreateControlsCore()
{
frm.TopLevel = false;
frm.FormBorderStyle = FormBorderStyle.None;
frm.Visible = true;
return frm;
}
protected override void LoadModelCore()
{
}
protected override void RefreshCore()
{
}
protected override void SaveModelCore()
{
}
}
In the above code, we inherit from View
class (the base of XAF views) and implement our custom rules.
The constructor gets 3 parameters, the first parameter is custom form to show, the second and third are caption and id of generated view.
The magic is in this code.
frm.TopLevel = false;
That allows window nest in a control.
Points of Interest
This solution has solved my problem, but further development can be done to create stronger relation to XAF rules, specially in LoadModelCore
, RefreshCore
, SaveModelCore
in BaseView
class.