Tag Archives: EPiServer

Display Help text in All Properties Editing

To see a property’s help text in EPiServer 7, the editor needs to hover the property label.
Helptext visible by hover
This is not always an intuitive behavior for the editor but I’ve found a way to it by making the help text visible next to the property.

Create css file

Create a .css file in /ClientResources/Styles, I call mine “editorhelp.css”.

Add the following styles : UPDATED FOR EPISERVER 9 and 10 (verified on 10.3.1)

.Sleek .dijitTabPaneWrapper .epi-form-container__section__row label[title]:after {
    content: attr(title);
    display: block;
    font-size: 0.8em;
    font-style: italic;
    margin: 0.3em 0 0 0;
}

Register your .css file

Add the following to module.config

<module>
	<clientResources>
		<add name="epi-cms.widgets.base"
				 path="Styles/editorhelp.css"
				 resourceType="Style"/>
	</clientResources>
</module>

Tadaa!

Go to edit mode and your Help text should be visible.
Help text displayed

Note that EPiServer is very good on caching this. You might need to clear your cache and restart your website.

Tagged

Simplifying event handling in EPiServer 7 CMS

While adding some Blocks to a project I was thinking of a concept that I’ve had in mind for a while. Some way to make it easier to hook your logic to EPiServer events such as creating pages, publishing pages.

The project can be downloaded from my repository on GitHub. I hope this will make your event handling in EPiServer much easier!

My example is a block that represents a header to group blocks.

[ContentType(DisplayName = "Column Heading", Description = "A heading in the column", GUID = "0A9BEC10-5795-43D5-B305-130ED6222D8A")]
public class ColumnHeadingBlock : BlockData
{
  [Display(GroupName = SystemTabNames.Content, Order = 1)]
  public virtual string Heading { get; set; }
}

Since it only has one property, it would be nice that it would be populated with the name given when the Block was created.

column heading

First approach: override SetDefaultValues

I noticed that the instance of my ColumnHeadingBlock is a ColumnHeadingBlockProxy that seems to be created  by EPiServer.Construction.SharedBlockFactory.CreateSharedBlock and that the proxy also is implementing the IContent Interface. Hence I can Cast my to IContent and retrieve the IContent.Name implementation.

Sadly SetDefaultValues are run before the Name is set and returns null.

Second approach: EPiServer.DataFactory.CreatingContent Event

This seems to do the trick. CreatingContent is triggered after SetDefaultValues and contentEventArgs.Content.Name returns the name I gave when creating the Block.

Wrapping things up: Initialization and reusability

The idea that have been growing inside my head is that I shouldn’t need to clutter global.asax or create InitializationModules everytime I want something to happen when I create, save, publish, move a page.

Therefore I created my EventHelper where I only need to implement an Interface to my Page Type Class where I add the logic to be run under certain Events. This could be re-registering Routes, notifying people, logging things etc when something is done in EPiServer.

In my example where I want to set a value to a Block Property when it is created, the implementation would look like this:

[ContentType(DisplayName = "Column Heading", Description = "A heading in the column", GUID = "0A9BEC10-5795-43D5-B305-130ED6222D8A")]
public class ColumnHeadingBlock : BlockData, ICreatingContent
{
  [Display(GroupName = SystemTabNames.Content, Order = 1)]
  public virtual string Heading { get; set; }

  public void CreatingContent(object sender, ContentEventArgs contentEventArgs)
  {
    Heading = contentEventArgs.Content.Name;
  }
}

Behind the scenes

The project contains an InitializationModule where I hookup basically all Events I could find in the DataFactory. I excluded the LoadingChildren Events since I don’t really know what the best implementation of this could be. Maybe something for a later version?

The CreatingContent Event is hooked up to the method DataFactoryEvents.CreatingContent.

DataFactory.Instance.CreatingContent += DataFactoryEvents.CreatingContent;

The DataFactoryEvents.CreatingContent method looks like this:

public static void CreatingContent(object sender, ContentEventArgs e)
{
  var content = e.Content as ICreatingContent;
  if (content == null)
    return;
  content.CreatingContent(sender, e);
}

Here is a list of the other Events I’m using – as you can see I’ve also implemented Page Events as well as the Content Events.

I have not yet given myself time to see if it’s necessary to be able to implement both Content and Page, but since the Page Event is not obsolete I guess both would be good.

  • CheckedInContent
  • CheckedInPage
  • CheckingInContent
  • CheckingInPage
  • CreatedContent
  • CreatedPage
  • CreatingContent
  • CreatingPage
  • DeletedContent
  • DeletedContentLanguage
  • DeletedContentVersion
  • DeletedPage
  • DeletedPageLanguage
  • DeletingContent
  • DeletingContentLanguage
  • DeletingContentVersion
  • DeletingPage
  • DeletingPageLanguage
  • FailedLoadingContent
  • FailedLoadingPage
  • FinishedLoadingPage
  • LoadedContent
  • LoadedDefaultContent
  • LoadedDefaultPageData
  • LoadedPage
  • LoadingContent
  • LoadingDefaultContent
  • LoadingDefaultPageData
  • LoadingPage
  • MovedContent
  • MovedPage
  • MovingContent
  • MovingPage
  • PublishedContent
  • PublishedPage
  • PublishingContent
  • PublishingPage
  • SavedContent
  • SavedPage
  • SavingContent
  • SavingPage
Tagged