How to Add an Unbound Control (Button) to the Form Layout in an XAF View (with a Fully Custom ViewItem)
- 6 minutes to read
This article describes how to add a custom control to a Detail View. If you want to display standard XAF Actions in a Detail View, use the technique described in the following topic: How to Add an Unbound Control (Button) to the Form Layout in an XAF View (with a Built-in ActionContainerViewItem).
A custom View Item should be a ViewItem descendant. You can also inherit it from any of the built-in View Items that XAF supplies. For more information about View Items, refer to the following topic: View Items
#Implementation Considerations
This is an advanced customization method that requires coding. Use it when you want to add an existing or custom control to the client area of a Detail View or Dashboard View. This approach allows you to obtain data from the current View object if necessary. Your control can be unbound or can load data from external sources.
If you want to bind a control to a business class property and add that control to both List View and Detail View, then consider the custom Property Editor approach.
This approach does not impose any restrictions on UI Control and XAF View interaction. You can implement custom logic in a ViewController
or a custom UI control. ViewItem descendants may implement their own inner logic.
#Create an ASP.NET Core Blazor-Specific View Item
Add a Razor component (ButtonRenderer in this example) to the ASP.NET Core Blazor application project (MySolution.Blazor.Server). In this component, configure the DxButton component, add the
Create
method that creates RenderFragment, and handle theClick
event.Note
The component name and its file name should be the same. For more information on Razor component naming conventions, refer to the following section: Names.
@using DevExpress.Blazor @namespace MySolution.Blazor.Server <DxButton Text=@ComponentModel.Text Click=@(() => ComponentModel.ClickFromUI()) /> @code { [Parameter] public ButtonModel ComponentModel { get; set; } public static RenderFragment Create(ButtonModel componentModel) => @<ButtonRenderer ComponentModel=@componentModel />; }
Ensure that the component’s Build Action property is set to
Content
.Create a ComponentModelBase descendant and name it ButtonModel. In this class, add properties and methods that describe your component.
using System; using DevExpress.ExpressApp.Blazor.Components.Models; namespace MySolution.Blazor.Server { public class ButtonModel : ComponentModelBase { public string Text { get => GetPropertyValue<string>(); set => SetPropertyValue(value); } public void ClickFromUI() { Click?.Invoke(this, EventArgs.Empty); } public event EventHandler Click; } }
Add the ButtonDetailViewItemBlazor View Item to the ASP.NET Core Blazor application project (MySolution.Blazor.Server). Decorate this View Item with ViewItemAttribute to make this View Item appear in the Application Model’s ViewItems node.
Override the
CreateControlCore
method to get aButtonHolder
instance.ButtonHolder
returns a render fragment with the custom component. Note that in the XAF Blazor application,CreateControlCore
should return an instance that implements theIComponentContentHolder
interface.Override the
OnControlCreated
method. In this method, subscribe to the component model’sClick
event. Implement the logic in theComponentModel_Click
event handler (in our example, the ShowMessage(String, InformationType, Int32, InformationPosition) is called).Override the BreakLinksToControls() method. In this method, unsubscribe from the component model’s
Click
event to release resources.using System; using DevExpress.ExpressApp; using DevExpress.ExpressApp.Blazor; using DevExpress.ExpressApp.Editors; using DevExpress.ExpressApp.Model; using Microsoft.AspNetCore.Components; using DevExpress.ExpressApp.Blazor.Components; namespace MySolution.Bazor.Server { public interface IModelButtonDetailViewItemBlazor : IModelViewItem { } [ViewItem(typeof(IModelButtonDetailViewItemBlazor))] public class ButtonDetailViewItemBlazor : ViewItem, IComplexViewItem { public class ButtonHolder : IComponentContentHolder { public ButtonHolder(ButtonModel componentModel) { ComponentModel = componentModel; } public ButtonModel ComponentModel { get; } RenderFragment IComponentContentHolder.ComponentContent => ComponentModelObserver.Create(ComponentModel, ButtonRenderer.Create(ComponentModel)); } private XafApplication application; public ButtonDetailViewItemBlazor(IModelViewItem model, Type objectType) : base(objectType, model.Id) { } void IComplexViewItem.Setup(IObjectSpace objectSpace, XafApplication application) { this.application = application; } protected override object CreateControlCore() => new ButtonHolder(new ButtonModel()); protected override void OnControlCreated() { if (Control is ButtonHolder holder) { holder.ComponentModel.Text = "Click me!"; holder.ComponentModel.Click += ComponentModel_Click; } base.OnControlCreated(); } public override void BreakLinksToControl(bool unwireEventsOnly) { if (Control is ButtonHolder holder) { holder.ComponentModel.Click -= ComponentModel_Click; } base.BreakLinksToControl(unwireEventsOnly); } private void ComponentModel_Click(object sender, EventArgs e) { application.ShowViewStrategy.ShowMessage("Action is executed!"); } } }
#Create a WinForms-Specific View Item
Add the ButtonDetailViewItemWin View Item to the WinForms application project (MySolution.Win). Decorate this View Item with ViewItemAttribute to make this View Item appear in the Application Model‘s ViewItems node.
using System; using System.Windows.Forms; using DevExpress.ExpressApp.Editors; using DevExpress.ExpressApp.Model; using DevExpress.ExpressApp; namespace MySolution.Win { public interface IModelButtonDetailViewItemWin : IModelViewItem { } [ViewItemAttribute(typeof(IModelButtonDetailViewItemWin))] public class ButtonDetailViewItemWin : ViewItem { public ButtonDetailViewItemWin(IModelViewItem model, Type objectType) : base(objectType, model.Id) { } protected override object CreateControlCore() { Button button = new Button(); button.Text = "Click me!"; button.Click += button_Click; return button; } void button_Click(object sender, EventArgs e) { throw new UserFriendlyException("Action is executed!"); } } }
Add the new View Item to the Detail View. Open the Model Editor and navigate to the Views | MySolution.Module.BusinessObjects | <Class> | <Class>_DetailView | Items node. Right-click the node and select ControlDetailItem from the Add context menu options.
- Navigate to the Views | MySolution.Module.BusinessObjects | <Class> | <Class>_DetailView | Layout node. Right-click the layout area and select the Customize Layout option from the context menu. Drag the new View Item from the Customization window to the layout area.
#Create an ASP.NET Web Forms-Specific View Item
In the MySolution.Module.Web project, create a ButtonDetailViewItemWeb View Item and decorate it with ViewItemAttribute to make this View Item appear in the Application Model’s ViewItems node.
using System; using DevExpress.ExpressApp.Editors; using DevExpress.ExpressApp.Model; using DevExpress.ExpressApp.Web; using DevExpress.Web.ASPxEditors; namespace MySolution.Module.Web { public interface IModelButtonDetailViewItemWeb : IModelViewItem { } [ViewItemAttribute(typeof(IModelButtonDetailViewItemWeb))] public class ButtonDetailViewItemWeb : ViewItem { public ButtonDetailViewItemWeb(IModelViewItem model, Type objectType) : base(objectType, model.Id) { } protected override object CreateControlCore() { ASPxButton button = new ASPxButton(); button.Text = "Click me!"; button.EnableClientSideAPI = true; button.Click += button_Click; return button; } void button_Click(object sender, EventArgs e) { WebWindow.CurrentRequestWindow.RegisterClientScript("ShowAlert", @"alert('Action is executed!');"); } } }
Add the new View Item to the Detail View. Open the Model Editor and navigate to the Views | MySolution.Module.BusinessObjects | <Class> | <Class>_DetailView | Items node. Right-click the node and select ControlDetailItem from the Add context menu options.
- Navigate to the Views | MySolution.Module.BusinessObjects | <Class> | <Class>_DetailView | Layout node. Right-click the layout area and select the Customize Layout option from the context menu. Drag the new View Item from the Customization window to the layout area.