Sitefinity 7 comes with a very cool new feature that enables us to add custom fields to Pages module through UI. Although this feature was previously not available in version 6.3, but its effect could be achieved by using Page Attributes. Also, in version 7, its called Custom Fields. Following is the helper class.
ModuleHelper.cs
public class ModuleHelper { public static void RegisterGuidArrayFieldSelectorForPages<C>(string fieldName) where C : FieldControlDefinitionElement { RegisterPageNodeDynamicData(); string itemType = typeof(PageNode).FullName; var fieldExists = GetMetaFieldsForType(itemType).Where(f => f.FieldName == fieldName).SingleOrDefault() != null; if (!fieldExists) { var metaManager = MetadataManager.GetManager(); var field = metaManager.CreateMetafield(fieldName); field.FieldName = fieldName; field.Title = fieldName; field.Hidden = false; field.ClrType = typeof(System.Guid[]).FullName; var metaType2 = metaManager.GetMetaType(typeof(PageNode)); metaType2.Fields.Add(field); metaManager.SaveChanges(); var manager = ConfigManager.GetManager(); manager.Provider.SuppressSecurityChecks = true; var section = manager.GetSection<ContentViewConfig>(); var backendSection = section.ContentViewControls[PagesDefinitions.BackendPagesDefinitionName]; var views = backendSection.ViewsConfig.Values.Where(v => v.ViewType == typeof(DetailFormView)); foreach (DetailFormViewElement view in views) { var sectionToInsert = CustomFieldsContext.GetSection(view, CustomFieldsContext.customFieldsSectionName, itemType); var fieldConfigElementType = TypeResolutionService.ResolveType(typeof(C).FullName); C newElement; newElement = Activator.CreateInstance(fieldConfigElementType, new object[] { sectionToInsert.Fields }) as C; newElement.DataFieldName = "CustomFields." + fieldName; newElement.FieldName = fieldName; newElement.Title = fieldName; newElement.DisplayMode = FieldDisplayMode.Write; newElement.Hidden = false; sectionToInsert.Fields.Add(newElement); } var frontendSection = section.ContentViewControls[PagesDefinitions.FrontendPagesDefinitionName]; views = frontendSection.ViewsConfig.Values.Where(v => v.ViewType == typeof(DetailFormView)); foreach (DetailFormViewElement view in views) { var sectionToInsert = CustomFieldsContext.GetSection(view, CustomFieldsContext.customFieldsSectionName, itemType); var fieldConfigElementType = TypeResolutionService.ResolveType(typeof(C).FullName); C newElement; newElement = Activator.CreateInstance(fieldConfigElementType, new object[] { sectionToInsert.Fields }) as C; newElement.DataFieldName = "CustomFields." + fieldName; newElement.FieldName = fieldName; newElement.Title = fieldName; newElement.DisplayMode = FieldDisplayMode.Write; newElement.Hidden = false; sectionToInsert.Fields.Add(newElement); } manager.SaveSection(section); manager.Provider.SuppressSecurityChecks = false; RestartApplication(); } } private static void RegisterPageNodeDynamicData() { var pageNodeType = App.WorkWith().DynamicData().Types().Where(s => s.ClassName == "PageNode").Get().FirstOrDefault(); if (pageNodeType != null) return; App.WorkWith() .DynamicData() .Type() .CreateNew("PageNode", "Telerik.Sitefinity.Pages.Model") .Do(dt => dt.DatabaseInheritance = DatabaseInheritanceType.vertical) .SaveChanges(true); } private static IList<MetaField> GetMetaFieldsForType(string type) { var existingType = TypeResolutionService.ResolveType(type); var existingClassName = existingType.Name; var existingNamespace = existingType.Namespace; var mgr = MetadataManager.GetManager(); var types = mgr.GetMetaTypes().FirstOrDefault(dt => dt.ClassName == existingClassName && dt.Namespace == existingNamespace); var fields = types != null ? types.Fields : new List<MetaField>(); return fields; } private static void RestartApplication() { if (SystemManager.Initializing) return; SystemManager.RestartApplication(true, true); } }
Usage
Add new field on Bootstrapped event.
protected static void OnBootstrapperInitialized(object sender, ExecutedEventArgs e) { if (e.CommandName == "Bootstrapped") { ModuleHelper.RegisterGuidArrayFieldSelectorForPages<ControlToUse>("YOUR_FIELD"); } }
Where ControlToUse is a Field Control which inherits FieldControlDefinitionElement and implements IRolesFieldSelectorDefinition. Happy Coding! And want to learn more? Register now for FalafelCon 2014 and perfect your skills, expand your horizons, and get inspired.
The post Programmatically add fields to Pages module in Sitefinity 6.3 and 7 appeared first on Falafel Software Blog.