1-888-365-2779
+1-888-365-2779
Try Now
More in this section

Forums / Developing with Sitefinity / Ideas on how to use a MediaContentSelectorView in a User Control

Ideas on how to use a MediaContentSelectorView in a User Control

2 posts, 0 answered
  1. Brett Whittington
    Brett Whittington avatar
    89 posts
    Registered:
    10 Aug 2012
    23 Mar 2012
    Link to this post
    I've been banging my head against the wall for a weeks trying to get a MediaContetSelectorView to work directly on a page without putting it in a custom control and I've finally succeeding in part.  I hope to put my findings in this thread so that others who have been asking the same questions as I, can try to glean the key information from my findings to apply it to their own code.  I do not however claim that this is the best approach or the even the most elegant solution as I had to cludge my way along to get here so any suggestion would be wonderful.

    The most difficult piece for me to find to put together was how to get my user control to "act" like a custom control.  What tipped me off that this might be possible was the Page Selector Events thread.  Which then lead me to IScriptControl Tutorial from Microsoft.  From these two articles I was able to parse together what I needed to do. So off to the code:

    So I have my user control (mine happened to be an admin add/edit page of a module) and I added the MediaContentSelectorView to the page.

    <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="FeaturedMessagesAddEditView.ascx.cs" Inherits="CorpComWeb.Modules.FeaturedMessages.Admin.FeaturedMessagesAddEditView"  %>
    <%@ Register Assembly="Telerik.Sitefinity" Namespace="Telerik.Sitefinity.Web.UI" TagPrefix="sitefinity" %>
    <%@ Register Assembly="Telerik.Sitefinity" Namespace="Telerik.Sitefinity.Modules.Libraries.Web.UI.Designers" TagPrefix="sf1" %>
      
    <telerik:RadScriptManager ID="manager" runat="server"></telerik:RadScriptManager>
    <!-- Need this to prevent javascript error "DateCreated.sitefinityLocaleFormat is not a function" -->
    <sitefinity:UserPreferences ID="userPreferences" runat="server" />
    <div class="sfMain sfClearfix">
        <div class="sfContent">
            <div class="rgTopOffset sfWorkArea">
                <div class="sfFormIn">
                    <sf1:MediaContentSelectorView id="selectorView" runat="server" 
                        ContentType="Telerik.Sitefinity.Libraries.Model.Image"
                        ParentType="Telerik.Sitefinity.Libraries.Model.Album"
                        LibraryBinderServiceUrl="~/Sitefinity/Services/Content/AlbumService.svc/"
                        MediaContentBinderServiceUrl="~/Sitefinity/Services/Content/ImageService.svc/"
                        MediaContentItemsListDescriptionTemplate="Telerik.Sitefinity.Resources.Templates.Designers.Libraries.Images.ImageItemDescriptionTemplate.htm"
                        DisplayResizingOptionsControl="false"
                        ShowOpenOriginalSizeCheckBox="false">
                    </sf1:MediaContentSelectorView> <br />
                         <asp:HiddenField ID="imageId" runat="server" ClientIDMode="Static" />
                    <p><asp:Button ID="btnSave" runat="server" Text="Save" onclick="btnSave_Click" /></p>
                </div>
            </div>
        </div>
    </div>

    So the above is pretty easy right?  This is a stripped down user control just to get idea across.  All of the registered assemblys are required as far as I know.  The hidden field is used to store the ID of the image that is selected in the MediaContentSelectorView.

    Next is the code behind and this is where it starts getting difficult:
    UserControl.ascx.cs
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using Telerik.Sitefinity;
    using Telerik.Sitefinity.Data;
    using Telerik.Sitefinity.Model;
    using Telerik.Sitefinity.Modules;
    using Telerik.Sitefinity.Libraries;
    using Telerik.Sitefinity.Libraries.Model;
    using Telerik.Sitefinity.Modules.Libraries;
    using Telerik.Sitefinity.Modules.Libraries.Images;
    using Telerik.Sitefinity.Modules.Pages;
    using Telerik.Sitefinity.Modules.Pages.Web.UI;
    using Telerik.Sitefinity.Taxonomies;
    using Telerik.Sitefinity.Taxonomies.Model;
    using Telerik.Sitefinity.Web;
    using Telerik.Sitefinity.Web.UI.ControlDesign;
    using Telerik.Sitefinity.Web.UI.Fields;
    using Telerik.Sitefinity.Resources;
    using Telerik.Web.UI;
      
    namespace Sample
    {
        public partial class ImageSelector: System.Web.UI.UserControl, IScriptControl
        {
            private ScriptManager sm;
            /// <summary>
            /// Handles the Load event of the Page control.
            /// </summary>
            /// <param name="sender">The source of the event.</param>
            /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
            protected void Page_Load(object sender, EventArgs e)
            {
                  
            }
      
            //This is needed to verify a scriptmanager is on the page.  I used a RadScriptManager but you can probably use others.
            protected override void OnPreRender(EventArgs e)
            {
                if (!this.DesignMode)
                {
                    // Test for ScriptManager and register if it exists
                    sm = RadScriptManager.GetCurrent(this.Page);
      
                    if (sm == null)
                        throw new HttpException("A ScriptManager control must exist on the current page.");
      
                    sm.RegisterScriptControl(this);
                }
      
                base.OnPreRender(e);
            }
      
        //This is probably required, I found this from the code from the microsoft site.  Experiment it might not be required.
            protected override void Render(HtmlTextWriter writer)
            {
                if (!this.DesignMode)
                    sm.RegisterScriptDescriptors(this);
      
                base.Render(writer);
            }
      
        //Must be implemented to use the IScriptControl interface.
            protected virtual IEnumerable<ScriptReference> GetScriptReferences()
            {
            //This is where you load the javascript file just like you would in a javascript control.
                ScriptReference imageReference = new ScriptReference();
                imageReference.Path = "~/Modules/FeaturedMessages/Admin/JavaScript/FeaturedMessagesAddEditView.js";
      
                return new ScriptReference[] { imageReference };
            }
      
            //Must be implemented to use the IScriptControl interface.
            protected virtual IEnumerable<ScriptDescriptor> GetScriptDescriptors()
            {
                //Must declare your control as the client.  Normaally you would put the custom control in here but instead you would put the client ID of your control
                ScriptControlDescriptor imageDescriptor = new ScriptControlDescriptor("CorpComWeb.Modules.FeaturedMessages.Admin.FeaturedMessagesAddEditView", this.ClientID);
                //Send the MediaContentSelectorView clientside object to the page.
                imageDescriptor.AddComponentProperty("selectorView", selectorView.ClientID);
      
                return new ScriptDescriptor[] { imageDescriptor };
            }
                  
      
            IEnumerable<ScriptReference> IScriptControl.GetScriptReferences()
            {
                return GetScriptReferences();
            }
      
            IEnumerable<ScriptDescriptor> IScriptControl.GetScriptDescriptors()
            {
                return GetScriptDescriptors();
            }
      
      
            /// <summary>
            /// Handles the Click event of the btnSave control.
            /// </summary>
            /// <param name="sender">The source of the event.</param>
            /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
            protected void btnSave_Click(object sender, EventArgs e)
            {
                 
            }
      
            protected override void OnUnload(EventArgs e)
            {
                base.OnUnload(e);
                if (context != null)
                    context.Dispose();
            }
        }
    }

    The key to this code was to inherit from IScriptControl and implement the methods that it needs to fullfill its contract, which are the GetScriptDescripters and GetScriptReferences.

    Finally, the Javascript File that will connect all of this together.  This is where things got really hairy for me as stuff that failed would through javascript messages.

    Type.registerNamespace("Sample.ImageSelector");
      
    Sample.ImageSelector = function (element) {
       Sample.ImageSelector.initializeBase(this, [element]);
      
        this._imageId = null;
    }
      
    Sample.ImageSelector.prototype = {
        initialize: function () {
            Sample.ImageSelector.callBaseMethod(this, 'initialize');
            this._itemSelectDelegate = Function.createDelegate(this, this._itemSelect);
            this._selectorView.add_onItemSelectCommand(this._itemSelectDelegate);
      
        },
        dispose: function () {
            Sample.ImageSelector.callBaseMethod(this, 'dispose');
            if (this._selectorView) {
                this._selectorView.add_onItemSelectCommand(this._itemSelectDelegate);
            }
        },
        get_selectorView: function () {
            return this._selectorView;
        },
        set_selectorView: function (value) {
            this._selectorView = value;
        },
      
        _itemSelect: function (sender, args) {
        //Get the date from the image.  I wanted the ID of the image.
            this._imageId = args.get_dataItem().Id;
        //Save this in a hidden field on the page.  This allows it to get passed back to the server.
            $("#imageId").val(this._imageId);
        },
      
        add_onItemSelectCommand: function (delegate) {
            this.get_events().addHandler('onItemSelectCommand', delegate);
        }
    }
      
    CorpComWeb.Modules.FeaturedMessages.Admin.FeaturedMessagesAddEditView.registerClass('CorpComWeb.Modules.FeaturedMessages.Admin.FeaturedMessagesAddEditView', Sys.Component);
      
    if (typeof (Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();

    The biggest key here is the _itemSelect Method.  In this method is where the selected object stores the ID of the image to a hidden variable on the control.  This could be any property of the image however. 

    *DISCLAIMER*  All the code above is stripped down portions of the control I wrote for my client and I am not able to give the entire source.  I will try to include a working piece for others to look at when I have time.  I do not guarantee that the above code will even work/compile.  My purpose for writing this guide was to help others have a "Eureka!" moment and they can apply this to there own work.

    All in all I got this to work through sure diligence, any suggestions on how to better this would greatly be appreciated and I hope this will help others accomplish what they have been trying to do!
  2. Svetoslav Petsov
    Svetoslav Petsov avatar
    456 posts
    Registered:
    24 Sep 2012
    28 Mar 2012
    Link to this post
    Hi Brett,

     Thank you very much for sharing your findings with the community. I am sure this can help a lot of people. I updated your Telerik points.

    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
2 posts, 0 answered