Skip to main content

How to: Access Nested List View or Master Detail View Environment (ASP.NET Core Blazor and Windows Forms)

  • 5 minutes to read

This topic explains how to use Controllers to access a nested List View‘s or a master Detail View‘s environment (Frames, Controllers, Actions, Objects) in XAF ASP.NET Core Blazor and Windows Forms applications.

The topic describes two scenarios:

This topic uses an Employee Detail View and Tasks nested List View. You can find the corresponding Employee and DemoTask business classes in the XAF MainDemo application (%PUBLIC%\Documents\DevExpress Demos 23.2\Components\XAF\MainDemo).

ASP.NET Core Blazor
XAF ASP.NET Core Blazor Master Detail View with a Nested List View, DevExpress
Windows Forms
XAF ASP.NET Core Blazor Master Detail View with a Nested List View, DevExpress

Note

XAF creates nested List Views for collection properties. These properties are often used in relationships between persistent objects.

How to: Access a Master Detail View’s Environment from a Nested List View Controller

Choose the method most suitable for your scenario:

If you need to access the master View from the DashboardViewItem or the DetailPropertyEditor, use the Access a Master Detail View’s Frame and its Controllers approach. See the E4916 article for an example.

Access a Master Detail View’s Frame and its Controllers

  1. In the required project of your application, create a nested List View Controller that receives the parent Frame in the AssignMasterFrame method. Use this Frame to customize its Controllers and Actions. For more information, refer to the following topic: Customize Controllers and Actions.

    Note

    Nested List View Controllers cannot access the parent Detail View Frame, Controllers, and Actions unless the Detail View‘s Controller passes the Detail View Frame to the nested List View Controller.

    using DevExpress.ExpressApp;
    
    namespace MainDemo.Module.Controllers;
    
    public class NestedListViewFrameController : ViewController<ListView> {
        private Frame masterFrame;
        public NestedListViewFrameController() {
            TargetViewNesting = Nesting.Nested;
        }
        public void AssignMasterFrame(Frame masterFrame) {
            this.masterFrame = masterFrame;
            // Use this Frame to get Controllers and Actions. 
        }
    }
    
  2. In the required project of your application, create a master Detail View Controller that acquires the Detail View Frame and passes it to the NestedListViewFrameController. Use the ListPropertyEditor.FrameChanged event subscription to ensure the nested List View exists.

    using DevExpress.ExpressApp;
    using DevExpress.ExpressApp.Editors;
    
    namespace MainDemo.Module.Controllers;
    
    public class MasterDetailViewController : ViewController<DetailView> {
        private void PushFrameToNestedController(Frame frame) => frame.GetController<NestedListViewFrameController>()?.AssignMasterFrame(frame);
        private void ListPropertyEditor_FrameChanged(object sender, EventArgs e) => PushFrameToNestedController(((ListPropertyEditor)sender).Frame);
        protected override void OnActivated() {
            base.OnActivated();
            foreach(var listPropertyEditor in View.GetItems<ListPropertyEditor>()) {
                if(listPropertyEditor.Frame is not null) {
                    PushFrameToNestedController(listPropertyEditor.Frame);
                }
                else {
                    listPropertyEditor.FrameChanged += ListPropertyEditor_FrameChanged;
                }
            }
        }
        protected override void OnDeactivated() {
            foreach(var listPropertyEditor in View.GetItems<ListPropertyEditor>()) {
                listPropertyEditor.FrameChanged -= ListPropertyEditor_FrameChanged;
            }
            base.OnDeactivated();
        }
        public MasterDetailViewController() {
            TargetViewType = ViewType.DetailView;
        }
    }
    

    Tip

    For more information about this technique, refer to the following example on GitHub: XAF - How to access the master Detail View information from a nested List View controller.

Access a Master Detail View’s Current Object (the View Item Approach)

  1. In the required project of your application, create a nested List View Controller. Use the CurrentObjectChanged event to update the master Detail View Caption each time the CurrentObject changes.

    using DevExpress.ExpressApp;
    using MainDemo.Module.BusinessObjects;
    
    namespace MainDemo.Module.Controllers;
    
    public class AccessParentDetailViewController : ObjectViewController<ListView, DemoTask> {
        public AccessParentDetailViewController() {
            TargetViewNesting = Nesting.Nested;
        }
        private void UpdateDetailViewCaption() {
            if(Frame is NestedFrame frame && View.CurrentObject is DemoTask task) {
                frame.ViewItem.View.Caption = task.Subject;
            }
        }
        private void View_CurrentObjectChanged(object sender, EventArgs e) => UpdateDetailViewCaption();
        protected override void OnActivated() {
            base.OnActivated();
            View.CurrentObjectChanged += View_CurrentObjectChanged;
            UpdateDetailViewCaption();
        }
        protected override void OnDeactivated() {
            base.OnDeactivated();
            View.CurrentObjectChanged -= View_CurrentObjectChanged;
        }
    }
    

Access a Master Detail View’s Current Object (the Property Collection Source Approach)

  1. In the required project of your application, create a nested List View Controller. The nested List View’s CollectionSource type is PropertyCollectionSource because the List View is a collection property.

  2. Handle the MasterObjectChanged event and process the current MasterObject when the master object changes.

    using DevExpress.ExpressApp;
    using MainDemo.Module.BusinessObjects;
    
    namespace MainDemo.Module.Controllers;
    
    public class AccessMasterObjectController : ObjectViewController<ListView, DemoTask> {
        private void UpdateMasterObject(object masterObject) {
            Employee employee = (Employee)masterObject;
            // Use the master object as required.            
        }
        private void OnMasterObjectChanged(object sender, EventArgs e) => UpdateMasterObject(((PropertyCollectionSource)sender).MasterObject);
        protected override void OnActivated() {
            base.OnActivated();
            if(View.CollectionSource is PropertyCollectionSource collectionSource) {
                collectionSource.MasterObjectChanged += OnMasterObjectChanged;
                if(collectionSource.MasterObject is not null) {
                    UpdateMasterObject(collectionSource.MasterObject);
                }
            }
        }
        protected override void OnDeactivated() {
            if(View.CollectionSource is PropertyCollectionSource collectionSource) {
                collectionSource.MasterObjectChanged -= OnMasterObjectChanged;
            }
            base.OnDeactivated();
        }
        public AccessMasterObjectController() {
            TargetViewNesting = Nesting.Nested;
        }
    }
    

How to: Access a Nested List View’s Environment from a Detail View Controller

  1. In the required project of your application, create a Detail View Controller.

  2. Handle the CurrentObjectChanged event and use the CustomizeViewItemControl<T>(DetailView, Controller, Action<T>, String[]) method to obtain the current nested List View‘s Frame and object. For more information about the use of PerformLogicWithCurrentListViewObject and PerformLogicInNestedListViewController methods, refer to the following topic: Customize Controllers and Actions.

    Note

    You can also use this technique to customize a DashboardViewItem and DetailPropertyEditor because these View Items contain a Frame with an inner View. For more information, refer to the following example: XAF - How to implement dependent views in a DashboardView (filter based on selection).

    using DevExpress.ExpressApp.Editors;
    using DevExpress.ExpressApp;
    using MainDemo.Module.BusinessObjects;
    
    namespace MainDemo.Module.Controllers;
    
    public class AccessNestedListViewController : ObjectViewController<DetailView, Employee> {
        private void PerformLogicWithCurrentListViewObject(object currentListViewObject) {
            DemoTask task = (DemoTask)currentListViewObject;
            // Use the object in the nested List View as required.
        }
        private void PerformLogicInNestedListViewController(Frame nestedFrame) {
            // Use the nested Frame as required.
        }
        private void NestedListView_SelectionChanged(object sender, EventArgs e) {
            var listView = (ListView)sender;
            PerformLogicWithCurrentListViewObject(listView.CurrentObject);
        }
        private void ProcessListPropertyEditor(ListPropertyEditor listPropertyEditor) {
            var nestedListView = listPropertyEditor.ListView;
            PerformLogicWithCurrentListViewObject(nestedListView.CurrentObject);
            PerformLogicInNestedListViewController(listPropertyEditor.Frame);
            nestedListView.SelectionChanged += NestedListView_SelectionChanged;
        }
        protected override void OnActivated() {
            base.OnActivated();
            View.CustomizeViewItemControl<ListPropertyEditor>(this, ProcessListPropertyEditor, nameof(Employee.Tasks));
        }
    }
    
See Also