I have found another way, this time still using the property tag. I now have:
<div class="image"> <EPiServer:Property runat="server" ID="Image" PropertyName="Image" Width="150" /> </div>
var prop = new PropertyContentReference(this.CurrentPage.Image); prop.Name = "Image"; Image.InnerProperty = prop; Image.Editable = true; Image.RenderSettings.Tag = UIHint.Image;
I've not done extensive testing but this seem to work, still hoping there is a better way though as it seems a little hacky.
Since your property is of type ContentReference, you need to create a renderer for that type instead. E.g.:
[TemplateDescriptor(
Default = true,
Inherited = true,
Tags = new[] // We specify as much as possible to make this
{ // renderer more specific, so it overrides the default one.
UIHint.Image,
RenderingTags.Edit,
RenderingTags.Preview,
})]
public partial class ImagePropertyControl : PropertyContentReferenceControl, IRenderTemplate<ContentReference>
{
#region Member Fields
private ImageFile currentImage;
#endregion
protected ImageFile CurrentImage
{
get
{
if (this.currentImage == null)
{
var repository = ServiceLocator.Current.GetInstance<IContentRepository>();
repository.TryGet<ImageFile>(this.ContentLink, out this.currentImage);
}
return this.currentImage;
}
}
public override void CreateOnPageEditControls()
{
var image = this.GetControl();
this.Controls.Add(image);
if (base.PropertyIsEditableForCurrentLanguage())
{
base.ApplyEditAttributes();
}
}
public override void CreateDefaultControls()
{
var image = this.GetControl();
this.Controls.Add(image);
}
private HtmlImage GetControl()
{
var image = new HtmlImage();
if (this.CurrentImage == null)
{
// Set a place holder image so we get the correct ratio on the image in edit mode.
image.Src = PlaceHolderImageHandler.GetUrlToPlaceholderImage(width, height);
return image;
}
var urlResolver = ServiceLocator.Current.GetInstance<UrlResolver>();
image.Src = urlResolver.GetUrl(this.ContentLink);
image.Alt = this.CurrentImage.AlternativeText;
return image;
}
}
It seems to me this still suffers from the fact that it doesn't get the fall back from the model but rather provides a generic placeholder - unfortunately for my needs the fall back is instance dependant (grabbing an image from the associated author page).
Even if it wasn't instance dependant I couldn't imagine the use of a fallback image that wasn't at least model dependant (i.e. one fallback for a profile image, another for a product image) and unfortunately I think this approach lacks the context to know where exactly it is trying to provide a fall back for.
In fact I'm already achieveing pretty much the same thing by declaring a my ImageReferenceProperty which inherits from PropertyControlBase<ContentReference> with the UIHint.Image tag, and could already implement the same sort of site-wide fallback there.
I think one of the main issues is that the Property control pulls the data of the PropertyDataCollection, which I'm guess is the backing stored use by the page models, this then bypasses any custom getter/setter logic. Perhaps property resolution that is more relection based is the answer.
You could have a fallback on images based on settings in the GetControl() method. E.g. specifying the fallback in the property control:
<EPiServer:Property PropertyName="Image" runat="server">
<RenderSettings FallbackPropertyName="Image" FallbackPage="3" />
</EPiServer:Property>
RenderingSettings are available in PropertyControlBase.
By doing it this way, it's not a global fallback and you can change it in every rendering instance.
So I've kind of got a grasp on fallback for textusing the below for properties in my model:
And realised that they don't work with the <EPiServer:Property /> tag and so sorted that in my views.
Now I'm tackling images and it has raised some interesting questions when it comes to rendering an image.
What I have is:
Now what this is essentially trying to do is default the image to an associated author is one exists, and it works and does the job - but the rendering has been the interesting part.
What I've done is changed from:
To:
And added to my code behind:
Now the problem comes in with the fact previosly this was rendered using my property control (inheriting from PropertyControlBase) and now it renders using the content control (inheriting from ContentControlBase)
Code for each is:
(I have extra logic in the base classes to get and merge attributes with the parent property or content renderer)
The problem is though that my content control renders was written to cope with how and image could be dragged into a content renderer, which is different to if I'm just rendering an image as part of page i.e. as a property.
Is there a better way to handle image fallback? I'm thinking maybe if I create a copy of the Image inheriting content control using UIHint.Image as the tag that may handle it but was wondering if there was a nicer way without so much duplication.