The Navigation System supports context navigation. You can track the process of creating navigation items in the navigation control and add custom navigation items. This topic demonstrates how to implement custom context navigation in your applications. A Window Controller will be implemented. This Controller will add the "Task-Based Help" child navigation items. The items will invoke a List View containing various help documents.
Show Me |
The complete sample project is available in the DevExpress Code Central database at http://www.devexpress.com/example=E1843. Depending on the target platform type (ASP.NET, WinForms, etc), you can either run this example online or download an auto-executable sample. |
To implement the sample custom context navigation, perform the following steps:
- Define the HelpDocument business class. This is the class that will represent help documents.
-
Implement a custom Window Controller. It will contain the custom context navigation logic. The logic should be composed of two parts:
A ShowNavigationItemController.NavigationItemCreated event handler. This event handler must create a child navigation item titled "Task-Based Help". Note that each help document will be associated with a particular business class. And, a created navigation item can point to a View of a business class that doesn't have associated documents. In this instance, the "Task-Based Help" navigation item shouldn't be created.
A ShowNavigationItemController.CustomShowNavigationItem event handler. This event handler must invoke a customized View when the "Task-Based Help" navigation item is selected.
Define the HelpDocument Business Class
The HelpDocument business class comprises three properties:
- Title - represents a document's title.
- Text - holds the actual text contained in the document. A help document's text can be very long, so this property should be decorated with the Size[-1] attribute (see Built-in Attributes).
- ObjectType - each document will be associated with a business class. So only help topics relevant to a specific business class will be displayed. The ObjectType property holds the associated business class' type. Since this property is of the Type type, a custom value converter must be implemented (see ValueConverter) for the property to be stored properly in the database.
|
using DevExpress.Xpo.Metadata;
public class TypeValueConverter : ValueConverter {
public override object ConvertToStorageType(object value) {
return value.ToString();
}
public override object ConvertFromStorageType(object value) {
if (value == null) return null;
else return Type.GetType((string)value);
}
public override Type StorageType {
get { return typeof(string); }
}
}
[DefaultClassOptions, ImageName("BO_Report")]
public class HelpDocument : BaseObject {
public HelpDocument(Session session) : base(session) { }
[DevExpress.Xpo.ValueConverter(typeof(TypeValueConverter))]
public Type ObjectType {
get { return GetPropertyValue<Type>("ObjectType"); }
set { SetPropertyValue<Type>("ObjectType", value); }
}
public string Title {
get { return GetPropertyValue<string>("Title"); }
set { SetPropertyValue<string>("Title", value); }
}
[Size(-1)]
public string Text {
get { return GetPropertyValue<string>("Text"); }
set { SetPropertyValue<string>("Text", value); }
}
}
Imports DevExpress.Xpo.Metadata
Public Class TypeValueConverter
Inherits ValueConverter
Public Overrides Function ConvertToStorageType(ByVal value As Object) As Object
Return value.ToString()
End Function
Public Overrides Function ConvertFromStorageType(ByVal value As Object) As Object
If value Is Nothing Then
Return Nothing
Else
Return Type.GetType(CStr(value))
End If
End Function
Public Overrides ReadOnly Property StorageType() As Type
Get
Return GetType(String)
End Get
End Property
End Class
<DefaultClassOptions, ImageName("BO_Report")> _
Public Class HelpDocument
Inherits BaseObject
Public Sub New(ByVal session As Session)
MyBase.New(session)
End Sub
<DevExpress.Xpo.ValueConverter(GetType(TypeValueConverter))> _
Public Property ObjectType() As Type
Get
Return GetPropertyValue(Of Type)("ObjectType")
End Get
Set(ByVal value As Type)
SetPropertyValue(Of Type)("ObjectType", value)
End Set
End Property
Public Property Title() As String
Get
Return GetPropertyValue(Of String)("Title")
End Get
Set(ByVal value As String)
SetPropertyValue(Of String)("Title", value)
End Set
End Property
<Size(-1)> _
Public Property Text() As String
Get
Return GetPropertyValue(Of String)("Text")
End Get
Set(ByVal value As String)
SetPropertyValue(Of String)("Text", value)
End Set
End Property
End Class
|
C# |
using DevExpress.Xpo.Metadata;
public class TypeValueConverter : ValueConverter {
public override object ConvertToStorageType(object value) {
return value.ToString();
}
public override object ConvertFromStorageType(object value) {
if (value == null) return null;
else return Type.GetType((string)value);
}
public override Type StorageType {
get { return typeof(string); }
}
}
[DefaultClassOptions, ImageName("BO_Report")]
public class HelpDocument : BaseObject {
public HelpDocument(Session session) : base(session) { }
[DevExpress.Xpo.ValueConverter(typeof(TypeValueConverter))]
public Type ObjectType {
get { return GetPropertyValue<Type>("ObjectType"); }
set { SetPropertyValue<Type>("ObjectType", value); }
}
public string Title {
get { return GetPropertyValue<string>("Title"); }
set { SetPropertyValue<string>("Title", value); }
}
[Size(-1)]
public string Text {
get { return GetPropertyValue<string>("Text"); }
set { SetPropertyValue<string>("Text", value); }
}
}
|
VB |
Imports DevExpress.Xpo.Metadata
Public Class TypeValueConverter
Inherits ValueConverter
Public Overrides Function ConvertToStorageType(ByVal value As Object) As Object
Return value.ToString()
End Function
Public Overrides Function ConvertFromStorageType(ByVal value As Object) As Object
If value Is Nothing Then
Return Nothing
Else
Return Type.GetType(CStr(value))
End If
End Function
Public Overrides ReadOnly Property StorageType() As Type
Get
Return GetType(String)
End Get
End Property
End Class
<DefaultClassOptions, ImageName("BO_Report")> _
Public Class HelpDocument
Inherits BaseObject
Public Sub New(ByVal session As Session)
MyBase.New(session)
End Sub
<DevExpress.Xpo.ValueConverter(GetType(TypeValueConverter))> _
Public Property ObjectType() As Type
Get
Return GetPropertyValue(Of Type)("ObjectType")
End Get
Set(ByVal value As Type)
SetPropertyValue(Of Type)("ObjectType", value)
End Set
End Property
Public Property Title() As String
Get
Return GetPropertyValue(Of String)("Title")
End Get
Set(ByVal value As String)
SetPropertyValue(Of String)("Title", value)
End Set
End Property
<Size(-1)> _
Public Property Text() As String
Get
Return GetPropertyValue(Of String)("Text")
End Get
Set(ByVal value As String)
SetPropertyValue(Of String)("Text", value)
End Set
End Property
End Class
|
Implement a Custom Window Controller
The custom Controller must only be activated for the main Window, since only the main Window Templates contains the navigation Action Container (see Navigation System). To implement the custom context navigation logic, subscribe to two ShowNavigationItemController events: the NavigationItemCreated and CustomShowNavigationItem.
|
using DevExpress.ExpressApp.SystemModule;
public class TaskBasedHelpController : WindowController {
private ShowNavigationItemController showNavigationItemController;
public TaskBasedHelpController() {
this.TargetWindowType = WindowType.Main;
}
protected override void OnFrameAssigned() {
UnsubscribeFromEvents();
base.OnFrameAssigned();
showNavigationItemController =
Frame.GetController<ShowNavigationItemController>();
if(showNavigationItemController != null) {
showNavigationItemController.NavigationItemCreated +=
new EventHandler<NavigationItemCreatedEventArgs>(
showNavigationItemController_NavigationItemCreated);
showNavigationItemController.CustomShowNavigationItem +=
new EventHandler<CustomShowNavigationItemEventArgs>(
showNavigationItemController_CustomShowNavigationItem);
}
}
}
Imports DevExpress.ExpressApp.SystemModule
Public Class TaskBasedHelpController
Inherits WindowController
Private showNavigationItemController As ShowNavigationItemController
Public Sub New()
Me.TargetWindowType = WindowType.Main
End Sub
Protected Overrides Sub OnFrameAssigned()
UnsubscribeFromEvents()
MyBase.OnFrameAssigned()
showNavigationItemController = Frame.GetController(Of ShowNavigationItemController)()
If showNavigationItemController IsNot Nothing Then
AddHandler showNavigationItemController.NavigationItemCreated, _
AddressOf showNavigationItemController_NavigationItemCreated
AddHandler showNavigationItemController.CustomShowNavigationItem, _
AddressOf showNavigationItemController_CustomShowNavigationItem
End If
End Sub
End Class
|
C# |
using DevExpress.ExpressApp.SystemModule;
public class TaskBasedHelpController : WindowController {
private ShowNavigationItemController showNavigationItemController;
public TaskBasedHelpController() {
this.TargetWindowType = WindowType.Main;
}
protected override void OnFrameAssigned() {
UnsubscribeFromEvents();
base.OnFrameAssigned();
showNavigationItemController =
Frame.GetController<ShowNavigationItemController>();
if(showNavigationItemController != null) {
showNavigationItemController.NavigationItemCreated +=
new EventHandler<NavigationItemCreatedEventArgs>(
showNavigationItemController_NavigationItemCreated);
showNavigationItemController.CustomShowNavigationItem +=
new EventHandler<CustomShowNavigationItemEventArgs>(
showNavigationItemController_CustomShowNavigationItem);
}
}
}
|
VB |
Imports DevExpress.ExpressApp.SystemModule
Public Class TaskBasedHelpController
Inherits WindowController
Private showNavigationItemController As ShowNavigationItemController
Public Sub New()
Me.TargetWindowType = WindowType.Main
End Sub
Protected Overrides Sub OnFrameAssigned()
UnsubscribeFromEvents()
MyBase.OnFrameAssigned()
showNavigationItemController = Frame.GetController(Of ShowNavigationItemController)()
If showNavigationItemController IsNot Nothing Then
AddHandler showNavigationItemController.NavigationItemCreated, _
AddressOf showNavigationItemController_NavigationItemCreated
AddHandler showNavigationItemController.CustomShowNavigationItem, _
AddressOf showNavigationItemController_CustomShowNavigationItem
End If
End Sub
End Class
|
Handle the NavigationItemCreated event
The NavigationItemCreated event occurs after a navigation item has been created in the navigation control. You'll need to track the creation of navigation items in the event handler. Since not every navigation item points to a View, check whether a particular NavigationItem node's View property is set. If it is, check whether help documents for a particular business class exist. If there are existing help documents, create the "Task-Based Help" child navigation item.
|
using DevExpress.ExpressApp.NodeWrappers;
using DevExpress.ExpressApp.DC;
using DevExpress.Data.Filtering;
using DevExpress.ExpressApp.Model;
public class TaskBasedHelpController : WindowController {
public const string ViewId = "HelpDocument_ListView_FewColumns";
public const string CriteriaKeyName = "Criteria";
void showNavigationItemController_NavigationItemCreated(
object sender, NavigationItemCreatedEventArgs e) {
ChoiceActionItem navigationItem = e.NavigationItem;
IModelView viewNode = ((IModelNavigationItem)e.NavigationItem.Model).View;
if (viewNode != null ) {
ITypeInfo objectTypeInfo =
XafTypesInfo.Instance.FindTypeInfo(viewNode.ModelClass.Name);
if(objectTypeInfo != null) {
ObjectSpace myObjectSpace = Application.CreateObjectSpace();
int helpDocumentsCount = myObjectSpace.GetObjectsCount(
typeof(HelpDocument), CriteriaOperator.Parse(
"ObjectType == '" + objectTypeInfo.Type.ToString() + "'"));
if(helpDocumentsCount != 0) {
ViewShortcut shortcut = new
ViewShortcut(typeof(HelpDocument), null, ViewId);
shortcut[CriteriaKeyName] = viewNode.ModelClass.Name;
ChoiceActionItem DocumentsNavigationGroup =
new ChoiceActionItem("CustomDocuments",
"Task-Based Help", shortcut);
navigationItem.Items.Add(DocumentsNavigationGroup);
}
}
}
}
}
Imports DevExpress.ExpressApp.NodeWrappers
Imports DevExpress.ExpressApp.DC
Imports DevExpress.Data.Filtering
Imports DevExpress.ExpressApp.Model
Public Class TaskBasedHelpController
Inherits WindowController
Public Const ViewId As String = "HelpDocument_ListView_FewColumns"
Public Const CriteriaKeyName As String = "Criteria"
Private Sub showNavigationItemController_NavigationItemCreated( _
ByVal sender As Object, ByVal e As NavigationItemCreatedEventArgs)
Dim navigationItem As ChoiceActionItem = e.NavigationItem
Dim viewNode As IModelView = (CType(e.NavigationItem.Model, IModelNavigationItem)).View
If viewNode IsNot Nothing Then
Dim objectTypeInfo As ITypeInfo = XafTypesInfo.Instance.FindTypeInfo( _
viewNode.ModelClass.Name)
If objectTypeInfo IsNot Nothing Then
Dim myObjectSpace As ObjectSpace = Application.CreateObjectSpace()
Dim helpDocumentsCount As Integer = myObjectSpace.GetObjectsCount( _
GetType(HelpDocument), CriteriaOperator.Parse( _
"ObjectType == '" & objectTypeInfo.Type.ToString() & "'"))
If helpDocumentsCount <> 0 Then
Dim shortcut As New ViewShortcut(GetType(HelpDocument), Nothing, ViewId)
shortcut(CriteriaKeyName) = viewNode.ModelClass.Name
Dim DocumentsNavigationGroup As New ChoiceActionItem( _
"CustomDocuments", "Task-Based Help", shortcut)
navigationItem.Items.Add(DocumentsNavigationGroup)
End If
End If
End If
End Sub
End Class
|
C# |
using DevExpress.ExpressApp.NodeWrappers;
using DevExpress.ExpressApp.DC;
using DevExpress.Data.Filtering;
using DevExpress.ExpressApp.Model;
public class TaskBasedHelpController : WindowController {
public const string ViewId = "HelpDocument_ListView_FewColumns";
public const string CriteriaKeyName = "Criteria";
void showNavigationItemController_NavigationItemCreated(
object sender, NavigationItemCreatedEventArgs e) {
ChoiceActionItem navigationItem = e.NavigationItem;
IModelView viewNode = ((IModelNavigationItem)e.NavigationItem.Model).View;
if (viewNode != null ) {
ITypeInfo objectTypeInfo =
XafTypesInfo.Instance.FindTypeInfo(viewNode.ModelClass.Name);
if(objectTypeInfo != null) {
ObjectSpace myObjectSpace = Application.CreateObjectSpace();
int helpDocumentsCount = myObjectSpace.GetObjectsCount(
typeof(HelpDocument), CriteriaOperator.Parse(
"ObjectType == '" + objectTypeInfo.Type.ToString() + "'"));
if(helpDocumentsCount != 0) {
ViewShortcut shortcut = new
ViewShortcut(typeof(HelpDocument), null, ViewId);
shortcut[CriteriaKeyName] = viewNode.ModelClass.Name;
ChoiceActionItem DocumentsNavigationGroup =
new ChoiceActionItem("CustomDocuments",
"Task-Based Help", shortcut);
navigationItem.Items.Add(DocumentsNavigationGroup);
}
}
}
}
}
|
VB |
Imports DevExpress.ExpressApp.NodeWrappers
Imports DevExpress.ExpressApp.DC
Imports DevExpress.Data.Filtering
Imports DevExpress.ExpressApp.Model
Public Class TaskBasedHelpController
Inherits WindowController
Public Const ViewId As String = "HelpDocument_ListView_FewColumns"
Public Const CriteriaKeyName As String = "Criteria"
Private Sub showNavigationItemController_NavigationItemCreated( _
ByVal sender As Object, ByVal e As NavigationItemCreatedEventArgs)
Dim navigationItem As ChoiceActionItem = e.NavigationItem
Dim viewNode As IModelView = (CType(e.NavigationItem.Model, IModelNavigationItem)).View
If viewNode IsNot Nothing Then
Dim objectTypeInfo As ITypeInfo = XafTypesInfo.Instance.FindTypeInfo( _
viewNode.ModelClass.Name)
If objectTypeInfo IsNot Nothing Then
Dim myObjectSpace As ObjectSpace = Application.CreateObjectSpace()
Dim helpDocumentsCount As Integer = myObjectSpace.GetObjectsCount( _
GetType(HelpDocument), CriteriaOperator.Parse( _
"ObjectType == '" & objectTypeInfo.Type.ToString() & "'"))
If helpDocumentsCount <> 0 Then
Dim shortcut As New ViewShortcut(GetType(HelpDocument), Nothing, ViewId)
shortcut(CriteriaKeyName) = viewNode.ModelClass.Name
Dim DocumentsNavigationGroup As New ChoiceActionItem( _
"CustomDocuments", "Task-Based Help", shortcut)
navigationItem.Items.Add(DocumentsNavigationGroup)
End If
End If
End If
End Sub
End Class
|
Handle the CustomShowNavigationItem Event
The CustomShowNavigationItem event occurs when a navigation item has been selected in the navigation control. In the event handler, you'll need to invoke a View containing the help documents corresponding to a particular business class. First, check whether the selected navigation item is a "Task-Based Help" navigation item. If it is, check its parent item to see what View it's pointing to, so that the business class' type can be resolved. Then, create a read-only List View and populate it with the help documents that have their ObjectType property set to the business class' type. Finally, set the created List View for the event handler's arguments property and the Handled property to true, to prohibit the default View from being displayed.
|
public class TaskBasedHelpController : WindowController {
private string parentViewClassName;
void showNavigationItemController_CustomShowNavigationItem(
object sender, CustomShowNavigationItemEventArgs e) {
if((e.ActionArguments.SelectedChoiceActionItem != null) &&
e.ActionArguments.SelectedChoiceActionItem.Id == "CustomDocuments") {
ChoiceActionItem parent =
e.ActionArguments.SelectedChoiceActionItem.ParentItem;
ObjectSpace objectSpace = Application.CreateObjectSpace();
CollectionSource collectionSource = new CollectionSource(
objectSpace, typeof(HelpDocument));
IModelView parentViewNode = ((IModelNavigationItem)parent.Model).View;
collectionSource.Criteria.Add("CustomDocumentsController",
CriteriaOperator.Parse("ObjectType == '" +
parentViewNode.ModelClass.Name + "'"));
View view = Application.CreateListView(
"HelpDocument_ListView_FewColumns", collectionSource, true);
e.ActionArguments.ShowViewParameters.CreatedView = view;
parentViewClassName = parentViewNode.ModelClass.Name;
view.CustomizeViewShortcut += new
EventHandler<CustomizeViewShortcutArgs>(view_CustomizeViewShortcut);
e.Handled = true;
}
}
void view_CustomizeViewShortcut(object sender, CustomizeViewShortcutArgs e) {
if(!string.IsNullOrEmpty(parentViewClassName)) {
e.ViewShortcut[CriteriaKeyName] = parentViewClassName;
}
}
}
|