Search code examples
orchardcmsshapes

How to change DisplayType of List item shape in Orchard?


I have a content MyContainer which has a ​Container part attached to it.

Then i have several MyContainerItem contents which have a Containable part attached to it and these are assigned to MyContainer.

Now, if the content MyContainer is rendered, it internally uses the List shape and therefore each MyContainerItem content is rendered with the Summary display type, which seems hard-coded in Orchard.

Is there any way to change the display type of MyContainerItem to Detail without altering the core code?

I tried the shape shifting technique in my alternates but to no avail.


Solution

  • I've had this issue before on other content parts (don't remember which), but what you could do is take the following steps:

    1 Create a custom part and record to attach to the content types that have the ContainerPart:

    public CustomContainerPart : ContentPart<CustomContainerPartRecord> {
        public string DisplayType {
            // property setter and getter
        }
    }
    

    2 Create a handler that attaches the CustomContainerPart on the content types that have the ContainerPart:

    public class CustomContainerPartHandler : ContentHandler {
        private readonly IContentDefinitionManager _contentDefinitionManager;
    
        public CustomContainerPartHandler(IContentDefinitionManager contentDefinitionManager) {
            _contentDefinitionManager = contentDefinitionManager;
        }
    
        protected override void Activating(ActivatingContentContext context) {
            base.Activating(context);
    
            // weld the CustomContainerPart dynamically, if the type has the ContainerPart
            var contentTypeDefinition = _contentDefinitionManager.GetTypeDefinition(context.ContentType);
            if (contentTypeDefinition == null) {
                return;
            }
    
            if (contentTypeDefinition.Parts.Any(part => part.PartDefinition.Name == typeof(ContainerPart).Name)) {
                context.Builder.Weld<CustomContainerPart>();
            }
        }
    }
    

    3 Create the driver for the custom part and use this Display method:

    protected override DriverResult Display(CustomContainerPart part, string displayType, dynamic shapeHelper) {    
        return ContentShape("Parts_Container_CustomContained", () => {
            var containerPart = part.As<ContainerPart>();
            // copy code from Orchard.Core/Containers/Drivers/ContainerPartDriver.cs here and tweak it to use the CustomContainerPart display type property
            // ..
            var listShape = shapeHelper.List();
            listShape.AddRange(pageOfItems.Select(item => _contentManager.BuildDisplay(item, part.DisplayType))); // here use your custom part setting
            // ..
        });
    }
    

    4 And finally your Placement.info:

    <Place Parts_Container_Contained="-" />
    <Match DisplayType="Detail">
      <Place Parts_Container_CustomContained="Content:7.5"/>
    </Match>