Get image referenced from custom module - Front- & Back-End Development - Front- & Back-End Development - Progress Community
 Front- & Back-End Development

Get image referenced from custom module

  • Get image referenced from custom module
  • Hello,

    I have a custom module that has a reference to image:
    if (!type.Fields.ToList().Any(fld => fld.FieldName == "ItemThumbnail"))
        type.Fields.Add(ContentLinksExtensions.CreateContentLinkField("ItemThumbnail", "OpenAccessDataProvider", metaMan, RelationshipType.OneToOne));

    Backend works as expected. And I can create items and assign images to it.

    Now I create widget that lists custom module items and I need to pull images information.
    But! Custom module item doen'st have "ItemThumbnail" field. I guess because it is just a link.

    Question is probably simple:
    How do I get image information that is referenced from custom module item.

    Thanks,
    Denis.
  • Hello Denis,

     Thank you for contacting us.
    If the field is of type ContentLink, you can use the ImageField to display the image on the frontend like this:

    <sf:ImageField ID="predefinedImageField" runat="server" DataFieldType="Telerik.Sitefinity.Model.ContentLinks.ContentLink"
                        DisplayMode="Read" ShowDeleteImageButton="false" DataFieldName="ItemThumbnail" />
    Let me know if this didn't work for you.

    Greetings,
    Svetoslav Petsov
    the Telerik team
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  • 318213_img.PNG
    Svetoslav,
    Thank you for reply. It worked.

    Two quick questions:
    1) Is there any way to avoid two extra divs that ImageField generates (see attachment).
    2) What other way to have image as field for custom module. I thought contentlink is there only way. But looks like there is other way to do it. Can you please give me a hint here. If you have example this is the best.

    Thanks!
    Denis.
  • Hi Denis,

    1) The only way to do that would be to change the template of the ImageField and remove/hide some of the elements there, but this could break the field. However, here's the default template for the ImageField:

    <%@ Control Language="C#" %>
    <%@ Register Namespace="Telerik.Web.UI" Assembly="Telerik.Web.UI" TagPrefix="telerik" %>
    <%@ Register Assembly="Telerik.Sitefinity" Namespace="Telerik.Sitefinity.Web.UI" TagPrefix="sf" %>
    <%@ Register Assembly="Telerik.Sitefinity" Namespace="Telerik.Sitefinity.Web.UI.Fields" TagPrefix="sf" %>
    <%@ Register Assembly="Telerik.Sitefinity" Namespace="Telerik.Sitefinity.Web.UI.ControlDesign" TagPrefix="sf" %>
    <%@ Register Assembly="Telerik.Sitefinity" Namespace="Telerik.Sitefinity.Modules.Libraries.Web.UI.Designers" TagPrefix="sf" %>
     
    <sf:ConditionalTemplateContainer ID="conditionalTemplateImageField" runat="server">
      <Templates>
     
        <sf:ConditionalTemplate Left="DisplayMode" Operator="Equal" Right="Read" runat="server">
            <div class="sfImg"><img ID="img_read" runat="server" alt="" /></div>
        </sf:ConditionalTemplate>
     
        <sf:ConditionalTemplate Left="DisplayMode" Operator="Equal" Right="Write" runat="server">
            <sf:ResourceLinks id="resourcesLinks" runat="server" UseEmbeddedThemes="True"  Theme="Default">
                <sf:ResourceFile Name="Telerik.Sitefinity.Resources.Themes.Default.Styles.jQuery.jquery.ui.core.css"  Static="True"/>
                <sf:ResourceFile Name="Telerik.Sitefinity.Resources.Themes.Default.Styles.jQuery.jquery.ui.dialog.css" Static="True"/>
                <sf:ResourceFile Name="Telerik.Sitefinity.Resources.Themes.Default.Styles.jQuery.jquery.ui.theme.sitefinity.css"  Static="True"/>
            </sf:ResourceLinks>
     
            <div id="viewPanel" runat="server" class="sfImgPreviewWrp">
                <asp:Label ID="titleLabel_write" runat="server" CssClass="sfTxtLbl" />
                <div class="sfPreviewImgFrame">
                    <img ID="img_write" runat="server" alt="" />
                </div>
                <asp:LinkButton ID="replaceImage" OnClientClick="return false;" runat="server" CssClass="sfLinkBtn sfChange sfSecondaryBtn">
                    <span class="sfLinkBtnIn"><asp:Literal runat="server" ID="lReplaceImage" Text="<%$Resources:ImagesResources, ChangePhoto %>" /></span>
                </asp:LinkButton>
                <asp:LinkButton ID="deleteImage" OnClientClick="return confirm('Are you sure you want to remove your avatar?')" runat="server" CssClass="sfLinkBtn sfChange">
                    <span class="sfLinkBtnIn"><asp:Literal runat="server" ID="lDeleteImage" Text="<%$Resources:ImagesResources, DeletePhoto %>" /></span>
                </asp:LinkButton>
                <sf:SitefinityLabel id="descriptionLabel_write" runat="server" WrapperTagName="div" HideIfNoText="true" CssClass="sfDescription" />
            </div>
     
            <div id="PostbackUploadPanel" runat="server">
                <div id="uploadPanel" runat="server" style="display:none" class="sfReuploadImgWrp">
                    <telerik:RadUpload ID="photoUpload" runat="server" AllowedFileExtensions="jpg,jpeg,png,gif" ControlObjectsVisibility="None" MaxFileInputsCount="1" />
                    <asp:LinkButton ID="cancelUpload" OnClientClick="return false;" runat="server" CssClass="sfCancel" Text="<%$Resources:ImagesResources, DontChangePhoto %>" />
                </div>
            </div>
            <div id="AsyncUploadPanel" runat="server">
                <sf:EditorContentManagerDialog runat="server" ID="asyncImageSelector" DialogMode="Image" HostedInRadWindow="false"  BodyCssClass="" />
            </div>
        </sf:ConditionalTemplate>
     
      </Templates>
    </sf:ConditionalTemplateContainer>

    What you can do is inherit the ImageField, override the LayoutTemplateName property and specify the path to your new template there. Then you can use your control instead of the default image field.
    2) The way you did it is the best way. Another way would be to use a selector with a textfield and inside the textfield save the url or the id of the image, but this is mostly used when the ImageField is added as a custom field to the module.

    Best wishes,
    Svetoslav Petsov
    the Telerik team
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  • Svetoslav,

    I have one more question.
    I have requirement to have links as images (in custom module master list).
    On the other hand sf:DetailsViewHyperLink control doesn't support images inside itself.
    I can override this control (OnDataBinding) and put <img> tag inside.
    But I don't know how to get image URL information in the overridden OnDataBinding.
    The way I reference image in my custom module you can find in the first message in this thread.

    Please advice best way to achieve this.

    Thanks!
    Denis.
  • Hello Denis,

     You will have to use the manager for your module, get the desired item, then use the Telerik.Sitefinity.Model's extension method GetValue to get the value of the content link (Thumbnail in your case) and after you do that, you will find a property of the content link, called ChildItemID, which is the ID of the linked item - in this case the image (This is an example with a module that I have, called "Projects"):

    ProjectsManager mng = ProjectsManager.GetManager();
                var project = mng.GetProjects().Where(p => p.Title == "Test").FirstOrDefault();
                var link = project.GetValue("Thumbnail") as ContentLink;
                 
                LibrariesManager libMng = LibrariesManager.GetManager();
                var image = libMng.GetImage(link.ChildItemId);
    Now you have all the properties that you need in the image object, including the URL.

    All the best,
    Svetoslav Petsov
    the Telerik team
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  • Hello Svetoslav,

    Thank you for information, but I can't get GetValue extension function work:
    PortfolioItem p = dataItem as PortfolioItem;
    var link = p.GetValue("Thumbnail") as ContentLink;
    It  fails with the following message:
    PortfolioItemsModule.Model.PortfolioItem' does not contain a definition for 'GetValue' and no extension method 'GetValue' accepting a first argument of type 'PortfolioItemsModule.Model.PortfolioItem' could be found (are you missing a using directive or an assembly reference?)   

    In order to use extension method, I use
    using Telerik.Sitefinity.Model;
    
    And I have data item derived from IDynamicFieldsContainer:
    
    [DataContract(Namespace = "http://blah.com", Name = "PortfolioItem")]
    [ManagerType("PortfolioItemsModule.Data.PortfolioItemsManager, PortfolioItemsModule")]
    public class PortfolioItem : Content, ILocatable, ILifecycleDataItemGeneric, IDynamicFieldsContainer
    What else should I do to make GetValue work? It there any other ways to get this value? Thanks! Denis.
  • Hello Denis,

     Are you sure you have a reference to Telerik.Sitefinity.Model and Telerik.Sitefinity? As far as I see this is a compiler error, which can only be caused by a missing reference. I also see that you have implemented everything needed for your class to have such an extension method.
    Another thing you could try is directly use DataExtensions.GetValue(obj item, string name) method.  

    Kind regards,
    Svetoslav Petsov
    the Telerik team
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  • Hi Svetoslav,

    I made sure I have references to
    using Telerik.Sitefinity;
    using Telerik.Sitefinity.Model;
    using Telerik.Sitefinity.Model.ContentLinks;
    using Telerik.Sitefinity.Modules.Libraries;
    using Telerik.Sitefinity.Web;
    using Telerik.Sitefinity.Web.UI.ContentUI;

    Also I tried to call extension method directly
    IDynamicFieldsContainer p = dataItem as IDynamicFieldsContainer; // verified - this is not null
    var link = DataExtensions.GetValue(p, "Thumbnail") as ContentLink;

    It fails with "Object reference not set to an instance of an object."
    If I try to use "GetValue" it fails with the same error (see previous message).
    Should I file support ticket and send you project?

    Thanks,
    Denis.
  • Hi,

     Can you send me the whole code that you are executing? Where is this "dataItem" that you are casting coming from? I suppose this is what causes the problem.

    All the best,
    Svetoslav Petsov
    the Telerik team
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  • Hi Svetoslav,

    Posting whole code as you asked:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Web.UI;
    using PortfolioItemsModule;
    using PortfolioItemsModule.Model;
    using Telerik.Sitefinity;
    using Telerik.Sitefinity.Model;
    using Telerik.Sitefinity.Model.ContentLinks;
    using Telerik.Sitefinity.Modules.Libraries;
    using Telerik.Sitefinity.Web;
    using Telerik.Sitefinity.Web.UI.ContentUI;
     
    namespace PortfolioItemsModule.Controls
        public class WWDetailsViewHyperLink : DetailsViewHyperLink
        
            protected override void CreateChildControls()
            
                base.CreateChildControls();
            
     
            protected override void OnDataBinding(EventArgs e)
            
                base.OnDataBinding(e);
                var container = this.GetDataItemContainer();
                object dataItem = null;
                if (container == null && this.DataItem != null)
                
                    dataItem = this.DataItem;
                
                if (container == null && this.DataItem == null)
                    throw new InvalidOperationException("This control can be used only within a data bound item template.");
     
                if (container != null)
                    dataItem = container.DataItem;
     
                if (dataItem != null)
                
                    var host = this.GetHostControl<ContentView>();
                    if (host == null)
                        throw new InvalidOperationException("This control must be hosted by ContentView control or one that derives form it.");
     
                    if (!String.IsNullOrEmpty(this.TextDataField))
                    
                        PortfolioItem p = dataItem as PortfolioItem;
                        //var link = DataExtensions.GetValue(p, "Thumbnail") as ContentLink;
                        var link = p.GetValue("Thumbnail") as ContentLink;
     
                        LibrariesManager libMng = LibrariesManager.GetManager();
                        var image = libMng.GetImage(link.ChildItemId);
                        this.ImageUrl = image.Url;
                    
                
     
                string url = this.NavigateUrl;
            
        

    As you can see I'm getting data item as this.DataItem.

    Thanks,
    Denis.

    PS: just upgraded to 4.4 the issues remains.
  • Hi,

     Can you try using the GetValue method with another property and see if it will succeed (try with something that can give us 100% insurance that it should be working, for example "Title" or another property that you have exposed in your module items' model class.). Also, try calling the GetValue method outside of this control, just create a test .aspx page in your solution and in the Code Behind, use your manager to get a "Porftolio Item" and then call the GetValue method for some property. If this fails again, then you can open a support ticket and send me the project, together with the module, so I can inspect where this could be coming from.

    Greetings,
    Svetoslav Petsov
    the Telerik team
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  • I have the same problem trying to get the image. Is this figured out already?

    Thanks!
    Daniel
  • Hi Daniel,

     What is your specific case? Is the image again registered as a field for the content items of a custom module or you have added it as a custom field to the built-in modules?

    Kind regards,
    Svetoslav Petsov
    the Telerik team
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items