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

Forums / Developing with Sitefinity / A custom image control question

A custom image control question

26 posts, 0 answered
  1. Daniel Plomp
    Daniel Plomp avatar
    952 posts
    Registered:
    18 Feb 2004
    04 Feb 2010
    Link to this post
    Hi all,

    I've a challenge on how to create a custom control which could help me doing the following:

    1. Place an image on a page in a placeholder, defined on the master page.
    2. If there are any pages below that page, that don't have an image placed in that placeholder, it should show the image of the above page.

    So, it should be a control that could check if the parent page has also that control placed, and if possible, inherit its settings. (or something like that :) )

    I hope someone already have done this, but otherwise I really could use some advise. I've got this from a TYPO3 CMS system, where it is called 'content sliding' (sliding over 1 or more pages), and find it very usefull. Specially for banners i.e. that should be visible on all pages, but could be overwritten. So that is also the reason I would not place the image on the masterpage.

    Any idea's?

    Thanks!
    Daniel
  2. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    12 Sep 2017
    04 Feb 2010
    Link to this post
    Hello Daniel,

    Below is a sample code that illustrates how to add a control on a page programmatically and then add it to the first level pages of the collection.

        var Manager = new CmsManager();
       ICmsPage page = (ICmsPage)Manager.GetPage(ID), true);
       if (page != null)
       {
     
           IStagedPage staged = page.Staged.CheckOut();
           staged.AddControl("ImageHolder", "~/IamgeControl.ascx", 0, "ImageControl1");
           // Gets first level pages collection
           if(page.Pages.Count > 0)
           {
               // add the control to the other pages.
           }
            Manager.SaveControl(cntrl);
           ((ICmsPage)Manager.GetPage(page.ID, true)).Staged.CheckIn();
           Manager.SavePage(page);
        
       }


    You can also just get the curent ICms page from ICmsUrlContext and its first level pages then loop through the child pages.

    Sincerely yours,
    Ivan Dimitrov
    the Telerik team

    Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
    Follow the status of features or bugs in PITS and vote for them to affect their priority.
  3. Daniel Plomp
    Daniel Plomp avatar
    952 posts
    Registered:
    18 Feb 2004
    04 Feb 2010
    Link to this post
    Hello Ivan,

    Thanks for your reply!
    I was wondering where I should add this code?

    I am thinking like this: if a page doesn't have an image control on it, THEN it should look to it's parent and inherit its settings. But if the page has an image control, then it should do nothing.

    But do I have to implement this logic inside a custom image control, or somewhere on a page (define page?? )

    Thanks,
    Daniel
  4. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    12 Sep 2017
    04 Feb 2010
    Link to this post
    Hello Daniel,

    You can implement the logic in a control or in Application_Start of the Global.asax

    Kind regards,
    Ivan Dimitrov
    the Telerik team

    Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
    Follow the status of features or bugs in PITS and vote for them to affect their priority.
  5. Daniel Plomp
    Daniel Plomp avatar
    952 posts
    Registered:
    18 Feb 2004
    04 Feb 2010
    Link to this post
    Hello Ivan,

    I decided to place the logic inside my usercontrol.
    How can I get the PageID of the page where the control is loaded on?

    If I have this Page, then I should be able to check if the page has a parent and then do the trick?

    Thanks,
    Daniel
  6. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    12 Sep 2017
    04 Feb 2010
    Link to this post
    Hi Daniel,

    The code below gets the current page ID

    ICmsUrlContext pageKey = (ICmsUrlContext)this.Context.Items[Telerik.Cms.Web.UrlHelper.CmsPageKey];
    Guid currentPageID = pageKey.PageID;

    If you are looking for another page of the SiteMap you can use CmsManager adn GetPage method.

    Sincerely yours,
    Ivan Dimitrov
    the Telerik team

    Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
    Follow the status of features or bugs in PITS and vote for them to affect their priority.
  7. Daniel Plomp
    Daniel Plomp avatar
    952 posts
    Registered:
    18 Feb 2004
    04 Feb 2010
    Link to this post
    Hi Ivan,

    When running the code, it gives me an error back on the following line:

    IStagedPage page = currentPage.Staged.CheckOut();

    The error is: IOdbClass must be joined to a transaction.

    Any idea what that could be?

    Thanks,
    Daniel
  8. Daniel Plomp
    Daniel Plomp avatar
    952 posts
    Registered:
    18 Feb 2004
    04 Feb 2010
    Link to this post
    Sorry, forgot to set the Edit property on True on the CmsManager.GetPage() method.
    This one works.

    -Daniel-
  9. Daniel Plomp
    Daniel Plomp avatar
    952 posts
    Registered:
    18 Feb 2004
    04 Feb 2010
    Link to this post
    Hi Ivan,

    Maybe this is not quite what I'm looking for. I've some problems to define my question! :)

    If the control is placed on a page and if that page has children, then on runtime the child pages should show the image, that is defined on the first page. So I don't want that the control is actually added to a child page.

    I hope you understand what I mean? Hopefully something like this is possible. The only thing is how to set this up in a way, that it is a bit flexible (e.g. you could configure on how many levels the image should be visible etc...)

    -Daniel-
  10. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    12 Sep 2017
    04 Feb 2010
    Link to this post
    Hi Daniel,

    You should have some control on the child pages that will get data from the parent and show the image. You can use page.Parent and then loop through controls collection and check whether the control that will show the image is on the parent page. If it is there you have to read its property that sets the path to the image and set it to the another controls.

    Kind regards,
    Ivan Dimitrov
    the Telerik team

    Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
    Follow the status of features or bugs in PITS and vote for them to affect their priority.
  11. Daniel Plomp
    Daniel Plomp avatar
    952 posts
    Registered:
    18 Feb 2004
    19 Apr 2010
    Link to this post
    Hello Ivan,

    Well, still busy after a while to pickup this issue again.
    Ehm... what I want to achieve:

    1. Place an (custom) image control on a page inside a ContentPlaceHolder
    2. Place the control on every subpage.
    3. On the first page the control should have an image set.
    4. On the subpages, the control should 'read' the settings from the control on it's parent page.

    Do you think this is the right way to do this within Sitefinity? (regarding to performance issues etc.)

    The only thing is that when you have many subpages, you would have to add the control by hand to every page, and that isn't preferrable I think.

    Could you (or others) think with me for a good solution?

    Thanks!
    Daniel
  12. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    12 Sep 2017
    19 Apr 2010
    Link to this post
    Hi Daniel,

    You do not have to add the control by hand on each page. You have to add the control only on the parent page. You could use the code that I sent you and determine whether the control is on the Parent page or not. If the control is on the parent, use AddControl method to add the same user control on each child page. Then read the property that is used to set the Image data from the parent control and set it to the child control.

    Regards,
    Ivan Dimitrov
    the Telerik team

    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
  13. Daniel Plomp
    Daniel Plomp avatar
    952 posts
    Registered:
    18 Feb 2004
    19 Apr 2010
    Link to this post
    Hi Ivan,

    Thanks for your reply.
    One thing is that on a subpage, I want to be able to override the image that is set on it's parent page.

    So, then I think it is not possible to automatically add the control from the parent page?

    Regards,
    Daniel
  14. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    12 Sep 2017
    19 Apr 2010
    Link to this post
    Hi Daniel,

    You can add the control on the sub page, but AddControl method does not duplicate it, which will allow you to use a public property of your Image control that has setter.

    Sincerely yours,
    Ivan Dimitrov
    the Telerik team

    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
  15. Daniel Plomp
    Daniel Plomp avatar
    952 posts
    Registered:
    18 Feb 2004
    19 Apr 2010
    Link to this post
    Okay, thanks!
  16. Daniel Plomp
    Daniel Plomp avatar
    952 posts
    Registered:
    18 Feb 2004
    19 Apr 2010
    Link to this post
    I tried to loop through the pages collection of a page.
    Then I'm getting an error that says the collection has been modified.

    // Get the pagekey
            ICmsUrlContext pageKey = (ICmsUrlContext)this.Context.Items[Telerik.Cms.Web.UrlHelper.CmsPageKey];
            Guid currentPageID = pageKey.PageID;
     
            var Manager = new CmsManager();
     
            // Get the current page
            ICmsPage page = (ICmsPage)Manager.GetPage(currentPageID);
     
            // Check if there are childpages
            if (page.Pages.Count > 0)
            {
                // Loop through the page collection
                foreach (ICmsPage p in page.Pages)
                {
                    IStagedPage staged = p.Staged.CheckOut();
                    staged.AddControl("ContentIntroBox", "~/UserControls/Damar/ImageSlide.ascx", 0, "ImageSlide");
     
                    ((ICmsPage)Manager.GetPage(p.ID, true)).Staged.CheckIn();
                    Manager.SavePage(p);
                }
            }

    I see page.Pages is an IList.
    Maybe I have to use something else?

    Thanks,
    Daniel
  17. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    12 Sep 2017
    19 Apr 2010
    Link to this post
    Hi Daniel,

    You have to get the page for editing before adding the controls on it

    ICmsPage = (ICmsPage)cmsManager.GetPage(cmsPage.ID, true);

    Sincerely yours,
    Ivan Dimitrov
    the Telerik team

    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
  18. Daniel Plomp
    Daniel Plomp avatar
    952 posts
    Registered:
    18 Feb 2004
    19 Apr 2010
    Link to this post
    Okay, that works.
    This is my code now:
    // Get the image
            this.imgSlide.ImageUrl = GetUrl(this.Image);
     
            // Get the pagekey
            ICmsUrlContext pageKey = (ICmsUrlContext)this.Context.Items[Telerik.Cms.Web.UrlHelper.CmsPageKey];
             
            // Get the current PageID
            Guid currentPageID = pageKey.PageID;
     
            // Create an instance of the CmsManager
            var Manager = new CmsManager();
     
            // Get the current page
            ICmsPage page = (ICmsPage)Manager.GetPage(currentPageID, true);
     
            // Check if there are childpages
            if (page.Pages.Count > 0)
            {
                // Loop through the page collection
                for (int i = 0; i < page.Pages.Count; i++)
                {
                    // Cast to an ICmsPage
                    ICmsPage p = (ICmsPage)Manager.GetPage(((ICmsPage)page.Pages[i]).ID, true);
     
                    // Get the staged version of the page
                    IStagedPage staged = p.Staged.CheckOut();
     
                    // Add an instance of this control to the page
                    staged.AddControl("ContentIntroBox", this);
     
                    // Check in the current page
                    ((ICmsPage)Manager.GetPage(p.ID, true)).Staged.CheckIn();
     
                    // Save the changes
                    Manager.SavePage(p);
                }
            }

    Unfortunately it is duplicating the image every time I access the parent page?

    Daniel
  19. Daniel Plomp
    Daniel Plomp avatar
    952 posts
    Registered:
    18 Feb 2004
    20 Apr 2010
    Link to this post
    I think I should check somehow if the Custom Control is already loaded on the childpage? How can I achieve this?
    And... aren't these CheckOut() and CheckIn() functions killing for the performance on every pageload?

    -Daniel-
  20. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    12 Sep 2017
    20 Apr 2010
    Link to this post
    Hello Daniel,

    Before adding the ContentIntroBox control you need to check whether you have a control with the same type on the child pages.

    if(c.GetType() == typeof(ContentIntrobox))
    {
    }

    or use "c is ContentIntrobox"

    Kind regards,
    Ivan Dimitrov
    the Telerik team

    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
  21. Daniel Plomp
    Daniel Plomp avatar
    952 posts
    Registered:
    18 Feb 2004
    20 Apr 2010
    Link to this post
    Hi Ivan,

    I've got it working now. There's only one problem left: deleting the control.

    This is the code so far:
    protected void Page_Load(object sender, EventArgs e)
        {
            // Variables used
            bool isUsed = false;
      
            try
            {
                // Set the image
                if (this.ContentImage != string.Empty)
                    this.imgSlide.ImageUrl = GetUrl(this.ContentImage);
      
                // Get the pagekey
                ICmsUrlContext pageKey = (ICmsUrlContext)this.Context.Items[Telerik.Cms.Web.UrlHelper.CmsPageKey];
      
                // Create an instance of the CmsManager
                var Manager = new CmsManager();
      
                // Get the current page in 'Edit' mode
                ICmsPage page = (ICmsPage)Manager.GetPage(pageKey.PageID, true);
      
                // Check if there are childpages
                if (page.Pages.Count > 0)
                {
                    // Loop through the page collection
                    for (int i = 0; i < page.Pages.Count; i++)
                    {
                        // Get the page in 'Edit' mode
                        ICmsPage p = (ICmsPage)Manager.GetPage(((ICmsPage)page.Pages[i]).ID, true);
      
                        // Get the controls on the current page
                        IList<ICmsWebControl> pageControls = p.Controls;
                        foreach (ICmsWebControl webCtrl in pageControls)
                        {
                            // Check if there already is a ContentSlideImage
                            if (webCtrl.ControlType == typeof(Image))
                            {
                                if (webCtrl.LoadControl().UniqueID == "ContentSlideImage")
                                    isUsed = true;    
                            }
      
                            if (isUsed == true && this.Slide == false)
                            {
                                // Get the staged version of the page
                                IStagedPage staged = p.Staged.CheckOut();
                                  
                                // Remove the control
                                staged.RemoveControl(webCtrl);
      
                                // Check in the current page
                                ((ICmsPage)Manager.GetPage(p.ID, true)).Staged.CheckIn();
                            }
                        }
      
                        // If the ContentSlideImage isn't placed yet, checkout the page and add
                        // an image to the container.
                        if (isUsed == false && this.Slide == true)
                        {
                            // Get the staged version of the page
                            IStagedPage staged = p.Staged.CheckOut();
      
                            // Add a new image to the container
                            Image img = new Image();
                            img.ImageUrl = GetUrl(this.ContentImage);
                            img.ID = "ContentSlideImage";
                            staged.AddControl("ContentIntroBox", img);
      
                            // Check in the current page
                            ((ICmsPage)Manager.GetPage(p.ID, true)).Staged.CheckIn();
                        }
      
                        // Save the changes
                        Manager.SavePage(p);
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

    If I try to delete the control, when 'Sliding' is turned off, an exception is thrown. (ID is not valid)
    I thought this is the right way to do this?

    -Daniel-
  22. Daniel Plomp
    Daniel Plomp avatar
    952 posts
    Registered:
    18 Feb 2004
    20 Apr 2010
    Link to this post
    Another question that raises now is:
    Can I have any influence on when I delete the control from the first page? Because then I want to loop through the childpages and delete the images...

    Is there an event that fires when deleting controls from the page?

    -Daniel-
  23. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    12 Sep 2017
    20 Apr 2010
    Link to this post
    Hello Daniel,

    Get the control you want to remove as ICmsWebControl and use  void RemoveControl(ICmsWebControl control);

    Sincerely yours,
    Ivan Dimitrov
    the Telerik team

    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
  24. Daniel Plomp
    Daniel Plomp avatar
    952 posts
    Registered:
    18 Feb 2004
    20 Apr 2010
    Link to this post
    Hi Ivan,

    I use the RemoveControl method from my checkout page. That is what you mean, right?
    And webCtrl is of type 'ICmsWebControl'.

    if (isUsed == true && this.Slide == false && this.DeleteNonSlidingImages == true)
    {
         // Get the staged version of the page
         IStagedPage staged = p.Staged.CheckOut();
                                  
         // Remove the control
         staged.RemoveControl(webCtrl);
      
         // Check in the current page
         ((ICmsPage)Manager.GetPage(p.ID, true)).Staged.CheckIn();
    }

    The RemoveControl throws an error:

    "Invalid Control ID parameter name: id"

    -Daniel-

  25. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    12 Sep 2017
    20 Apr 2010
    Link to this post
    Hello Daniel,

    The RemoveControl has two overloads

    • RemoveControl(ICmsWebControl control);
    • RemoveControl(Guid id);
    Most probably somehow you are using the second one, so specify the ID  ( cntr.ID) instead.
    Greetings,
    Ivan Dimitrov
    the Telerik team

    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
  26. Daniel Plomp
    Daniel Plomp avatar
    952 posts
    Registered:
    18 Feb 2004
    20 Apr 2010
    Link to this post
    Hi Ivan,

    I created a support ticket with a sample project.
    Hope you could look at that?

    Thanks,
    Daniel
Register for webinar
26 posts, 0 answered