For all I know, the following code may have disastrous side effects. However, it allows me to put action containers anywhere in my detail views just by creating items of the EmbeddedActionContainer type in the application model. You need to ensure that you assign the actions that you want to embed into the detail view to a unique category. Then set the ContainerId of your EmbeddedActionContainer detail view item to the name of this category. The view controller for your detail view needs to look something like:
public partial class MyDetailViewController : ViewController
{
private EmbeddedActionContainerHelper embeddedActionHelper;
public MyDetailViewController()
{
InitializeComponent();
RegisterActions(components);
embeddedActionHelper = new EmbeddedActionContainerHelper(this);
}
private void MyDetailViewController_Activated(object sender, EventArgs e)
{
embeddedActionHelper.CurrentDetailView = (DetailView)View;
}
private void MyDetailViewController_Deactivating(object sender, EventArgs e)
{
embeddedActionHelper.CurrentDetailView = null;
}
}
You also need to add the following code to your Module.cs file:
public override Schema GetSchema()
{
return new Schema(new DictionaryXmlReader().ReadFromString(
EmbeddedActionContainer.EmbeddedActionContainerAttributes));
}
It should be easy to produce a Winows forms version as well, but I don't have a requirement for this at the moment.
This code comes with absolutely no warranties whatsoever and hasn't been particularly well tested either.
EmbeddedActionContainer.cs:
using System;
using System.Collections.Generic;
using System.Text;
using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Actions;
using DevExpress.ExpressApp.Editors;
namespace MySolution.Module.Editors
{
public abstract class EmbeddedActionContainer : DetailViewItem
{
public EmbeddedActionContainer(Type objectType, DictionaryNode info)
: base(info, objectType)
{
Actions = new List<ActionBase>();
if (info != null)
ContainerId = info.GetAttributeValue("ContainerId");
}
public List<ActionBase> Actions { get; private set; }
public string ContainerId { get; private set; }
public const string EmbeddedActionContainerAttributes =
@"<Element Name=""Application"">
<Element Name=""Views"">
<Element Name=""DetailView"" >
<Element Name=""Items"" >
<Element Name=""EmbeddedActionContainer"" >
<Attribute Name=""ContainerId"" IsNewNode=""True"" />
</Element>
</Element>
</Element>
</Element>
</Element>";
}
public class EmbeddedActionContainerHelper
{
private Dictionary<string, EmbeddedActionContainer> actionContainers;
private ViewController controller;
private DetailView currentDetailView;
public EmbeddedActionContainerHelper(ViewController viewController)
{
controller = viewController;
actionContainers = new Dictionary<string, EmbeddedActionContainer>();
}
public DetailView CurrentDetailView
{
get { return currentDetailView; }
set
{
if (currentDetailView != value)
{
// Cleanup the current view, if any
if (currentDetailView != null)
{
foreach (KeyValuePair<string, EmbeddedActionContainer> item in actionContainers)
{
int i = 0;
while (i < item.Value.Actions.Count)
{
if (item.Value.Actions[ i ].Controller == controller)
item.Value.Actions.RemoveAt(i);
else
i++;
}
}
}
// Setup the new view, if any
currentDetailView = value;
actionContainers.Clear();
if (currentDetailView != null)
{
// First identify all the embedded action containers and keep track of them
// by their ContainerId.
foreach (DetailViewItem item in currentDetailView.Items)
{
if (item is EmbeddedActionContainer)
{
actionContainers[((EmbeddedActionContainer)item).ContainerId] =
(EmbeddedActionContainer)item;
}
}
// Then add all actions from the view controller with categories matching
// the container IDs of the embedded action controllers.
foreach (ActionBase action in controller.Actions)
{
EmbeddedActionContainer container;
if (actionContainers.TryGetValue(action.Category, out container))
container.Actions.Add(action);
}
}
}
}
}
}
}
WebEmbeddedActionController.cs:
using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI.WebControls;
using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Editors;
using DevExpress.ExpressApp.Web.Templates.ActionContainers;
using MySolution.Module.Editors;
namespace MySolution.Module.Web.Editors
{
[DetailViewItemName("EmbeddedActionContainer")]
public class WebEmbeddedActionContainer : EmbeddedActionContainer
{
public WebEmbeddedActionContainer(Type objectType, DictionaryNode info)
: base(objectType, info) { }
protected override object CreateControlCore()
{
HorizontalActionContainer result = new HorizontalActionContainer();
result.ContainerId = ContainerId;
for (int i = 0; i < Actions.Count; i++)
result.Register(Actions[ i ]);
return result;
}
}
}