Ticket T600913
Visible to All Users

Link / Unlink Actions Unavailable from List View Managed by Dialog Controller

created 7 years ago (modified 7 years ago)

We have a business object (EmploymentRecord) that can be linked to one or more objects representing skills (Skill) in a many to many relationship.  The Link / Unlink actions provided by the LinkUnlinkController are available from the EmploymentRecord_Skills_ListView and the Skill_EmploymentRecords_ListView.

In our object model each EmploymentRecord belongs to exactly one Employee record (aggregated relationship). An employee (Employee) can have one or more Employment Records, of which only one can be active at any time. The active employment record is made available via the Employee.CurrentEmploymentRecord property.  We'd like to make it easy for the user to view / manage the skills linked to the employee's active employment record. We'd like to add an action to the Employee view controller to pop-up a dialog that lists all the skills associated with the employee's active employment record. The List Skills action we coded in the attached sample program partially works. It lists the associated skills but is missing the Link and Unlink actions that would allow the user to adjust the list of skills linked to the active employment record.  What must we do to enable these actions?

Video of sample program

Answers approved by DevExpress Support

created 7 years ago (modified 7 years ago)

Hello Mick,

These actions belong to the Link Action Container that does not exist in the popup window template by default. You can place them to another container dynamically using the ActionControlsSiteController.CustomizeActionControl event:

C#
using DevExpress.ExpressApp; using DevExpress.ExpressApp.Actions; using DevExpress.ExpressApp.SystemModule; namespace LinkUnlinkExample.Module.Controllers { public class LinkSkillsController : ViewController { public LinkSkillsController() { TargetViewId = "EmploymentRecord_Skills_ListView"; } protected override void OnActivated() { base.OnActivated(); if (!(Frame is NestedFrame)) { Frame.GetController<ActionControlsSiteController>().CustomizeContainerActions += LinkSkillsController_CustomizeContainerActions; Frame.GetController<FillActionContainersController>().CustomizeContainerActions += LinkSkillsController_CustomizeContainerActions; } } void LinkSkillsController_CustomizeContainerActions(object sender, CustomizeContainerActionsEventArgs e) { ActionBase linkAction = e.AllActions.Find("Link"); ActionBase unlinkAction = e.AllActions.Find("Unlink"); if (e.Category == "PopupActions") { e.ContainerActions.Add(linkAction); e.ContainerActions.Add(unlinkAction); } } protected override void OnDeactivated() { base.OnDeactivated(); if (!(Frame is NestedFrame)) { Frame.GetController<ActionControlsSiteController>().CustomizeContainerActions -= LinkSkillsController_CustomizeContainerActions; Frame.GetController<FillActionContainersController>().CustomizeContainerActions -= LinkSkillsController_CustomizeContainerActions; } } } }

In addition, it is necessary to commit changes when this ListView is closed:

C#
private void ListSkills_CustomizePopupWindowParams(object sender, CustomizePopupWindowParamsEventArgs e) { Employee employee = View.CurrentObject as Employee; Debug.Assert(employee != null); if (employee.CurrentEmploymentRecord != null) { var nestedSpace = ObjectSpace.CreateNestedObjectSpace(); ITypeInfo type = Application.TypesInfo.FindTypeInfo(typeof(EmploymentRecord)); PropertyCollectionSource cs = new PropertyCollectionSource(nestedSpace, type.Type, nestedSpace.GetObject(employee.CurrentEmploymentRecord), type.FindMember("Skills")); e.View = Application.CreateListView("EmploymentRecord_Skills_ListView", cs, false); e.DialogController.Accepting += DialogController_Accepting; } } void DialogController_Accepting(object sender, DialogControllerAcceptingEventArgs e) { ((Controller)sender).Frame.View.ObjectSpace.CommitChanges(); }

The DialogController.SaveOnAccept property won't have an effect in a non-root ListView. Note that I have removed your code that populated the Collection Source manually. It is not required, since PropertyCollectionSource is filled with objects from the specified property (Skills) automatically.

Please let me know if you encounter any difficulty with the proposed solution.

    Comments (2)
    JM JM
    Johnathan McFarlane 7 years ago

      Works perfectly. Thank you so much!!

      Anatol (DevExpress) 7 years ago

        You are welcome!

        Disclaimer: The information provided on DevExpress.com and affiliated web properties (including the DevExpress Support Center) is provided "as is" without warranty of any kind. Developer Express Inc disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.

        Confidential Information: Developer Express Inc does not wish to receive, will not act to procure, nor will it solicit, confidential or proprietary materials and information from you through the DevExpress Support Center or its web properties. Any and all materials or information divulged during chats, email communications, online discussions, Support Center tickets, or made available to Developer Express Inc in any manner will be deemed NOT to be confidential by Developer Express Inc. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.