Hiding properties in edit mode programmatically

Vote:
 

I have a page which resides in a common library and it is used by multiple sites. However, not all properties on the page is relevant to all sites and therefore I'd like to hide different properties in different sites. One way to do that is to inherit the page and use the Ignore/ScaffoldColumn attribute; however doing this is not feasible on sites that already has content.

Is there any other way to programatically hide a chosen property in a particular page from editors? Being able to read and override the value of "Display in edit view" option in Admin view programmatically would be easier to implement and maintain in the long run.

#209488
Edited, Nov 15, 2019 9:16
Vote:
 

Hi,

Yes, this is certainly possible. I wrote a post along those lines here:

https://world.episerver.com/blogs/paul-gruffydd/dates/2019/3/language-based-feature-switching/

The basics are that you create an attribute which implements IMetadataAware then, in your implementation of OnMetadataCreated, you work out whether you want to show the property you've applied the attribute to and set the value of metadata.ShowForEdit.

#209496
Edited, Nov 15, 2019 10:58
Vote:
 

You could also do something like:

    [EditorDescriptorRegistration(TargetType = typeof(MyPageType))]
    public class MyEditorDescriptor : EditorDescriptor
    {
        public override void ModifyMetadata(ExtendedMetadata metadata, IEnumerable<Attribute> attributes)
        {
            foreach (var modelMetadata in metadata.Properties)
            {
                var property = (ExtendedMetadata)modelMetadata;
                if (property.PropertyName == nameof(MyPageType.PropertyToBeHidden1))
                {
                    property.ShowForEdit = false;
                }

                if (property.PropertyName == nameof(MyPageType.PropertyToBeHidden2))
                {
                    property.ShowForEdit = false;
                }
            }
        }
    }
#209498
Edited, Nov 15, 2019 12:48
Vote:
 

Thanks for the answers! They gave me inspiration and I was able to find a solution.

Here's how:

Create a custom metadata extender class and implement IMetadataExtender

    public class TestMetadataExtender : IMetadataExtender
    {
        public void ModifyMetadata(ExtendedMetadata metadata, IEnumerable<Attribute> attributes)
        {
            var contentDataMetadata = (ContentDataMetadata)metadata;
            if (!(contentDataMetadata.Model is MyStartPagestartpage)) return;

            foreach (var metadataProperty in metadata.Properties)
            {
                var mp = metadataProperty;
                if (mp.PropertyName == "MyProperty")
                {
                    mp.ShowForEdit = false;
                }
            }
        }
    }

This class should be registered in an initialization module:

[InitializableModule]
[ModuleDependency(typeof(EPiServer.Cms.Shell.InitializableModule))]
public class MetadataExtenderInit : IInitializableModule
{
    public void Initialize(InitializationEngine context)
    {
        var registry = context.Locate.Advanced.GetInstance<MetadataHandlerRegistry>();
        registry.RegisterMetadataHandler(typeof(ContentData), new TestMetadataExtender());
    }

    public void Uninitialize(InitializationEngine context)
    {
    }
}

This implementation worked without problems.

@Tomas, I noticed that EditorDescriptor solution is very similar since it uses the same ModifyMetadata method. However just creating the editor descriptor and setting the type to a specific page type did not work. Setting the type to ContentData however works without problem. Editor descriptor solution is simpler therefore I'd like to use it but do I need to register the target type seperately for an individual page type? Checking contentDataMetadata.Model type manually works, but would be even better to be able to skip it.

#209502
Nov 15, 2019 13:26
Vote:
 

If you prefer EditorDescriptor, this should work?

    [EditorDescriptorRegistration(TargetType = typeof(ContentData))]
    public class MoveFormsPropertyEditorDescriptor : EditorDescriptor
    {
        public override void ModifyMetadata(ExtendedMetadata metadata, IEnumerable<Attribute> attributes)
        {
            var contentDataMetadata = (ContentDataMetadata)metadata;
            if (!(contentDataMetadata.Model is MyStartPagestartpage))
            {
                return;
            }

            foreach (var metadataProperty in metadata.Properties)
            {
                var mp = metadataProperty;
                if (mp.PropertyName == nameof(MyStartPagestartpage.MyProperty))
                {
                    mp.ShowForEdit = false;
                }
            }
        }
    }
#209504
Edited, Nov 15, 2019 14:15
Vote:
 

Yes, it works as I explained above. I guess it should do the trick! Thanks for the code example!

#209505
Nov 15, 2019 14:18
Vote:
 

EditorDescriptor actually implements IMetadataExtender (as a virtual method), so it does not really matter if you are using EditorDescriptor or IMetadataExtender

#209506
Nov 15, 2019 14:19
Vote:
 

Hi, It works in hiding some of Episerver Forms inbuilt properties.

But i would appreciate,running this function, only once, at the time of Initialization. This seems to enter the loop and go through all properties even if editor refreshes page.

#209587
Nov 19, 2019 10:38