none
customize out-of-the-box webpart

    Question

  • We want to customize the functionality / working out-of-the-box webpart. We are not interested right now in style and appearance of the webpart. Any resources for Visual Studio 2010?
    http://farhanfaiz.wordpress.com
    Wednesday, June 15, 2011 2:51 PM

Answers

  • I see, so your trying to do a string replace on the url in the list item and change it to title?

    The html generation is hard coded into the webpart, it relies on two methods

     

    CreateHTML

    and

    CreateHTMLListItems

     

    Render calls CreateHTML, and CreateHTML calls CreateHTMLListItems.

    CreateHTMLListItems is what's generating the <a href html with the Url's, heres what the code looks like,

              case WhatsPopularType.SearchCenterQueries:
              {
                sb.Append("<li value='");
                sb.Append(Convert.ToString(num2, 10));
                sb.Append("'>");
                sb.Append("<a href=\"");
                sb.Append(searchUrl + "k=");
                sb.Append(SPEncode.UrlEncode((string) row["QueryText"]));
                sb.Append("\">");
                sb.Append(row["QueryText"]);
                sb.Append("</a>");
                this.AddFrequency(sb, row, frequencyColName);
                this.AddTrend(sb, row, i + 1);
                sb.Append("</li>");
    
    


    It generates different html for each type of WhatsPopularType, ContentType's, SearchCenterQueries, and SiteSearchQueries.

     

    Theres no pretty way to do what your trying to do, the fact that it's still displaying URL's in your code means your regex expression isn't finding a match, this your string replace doesn't happen.

     

    What I would do, is get a copy of RegExBuilder from http://renschler.net/RegexBuilder/.  Then in the Text 1 box, enter in the html for one of the List Items.

    Then modify your reg ex till you get a match.

    1. Don't rely on an auto generated id, your reg ex should be able to match the base html tags ignoring any id attributes, otherwise it will only match that one ID and the rest will still be Url's.  It's possible to match part of an ID, e.g. "mypage_mywebpart_whatspopularwebpart"  if the end of the id is always the same, you could match just that part etc.

    you can use a reg ex cheat sheet to help you, in combination with RegExBuilder.  You can build your reg ex and make sure it works before you try it in sharepoint again (saves a ton of time on site spinups.)

    http://www.hci-matters.com/blog/wp-content/uploads/2009/08/RegEx_Chart_Barnes_v2.pdf

     

    Optionally, you can use reflection to analyze what CreateHtml and CreateHtmlListItems does exactly, including it's two boolean parameters, then override Render, and rewrite it from scratch, then you have complete control over what it renders.

     


    My Blog: http://www.thesug.org/Blogs/ryan_mann1/default.aspx Website: Under Construction
    • Marked as answer by Shimin Huang Monday, June 20, 2011 8:28 AM
    Thursday, June 16, 2011 3:45 PM

All replies

  • Hi Malikfarhan,

     

    According to your description, you want to customize the out of the box web part in Visual Studio 2010. If I misunderstood you, please feel free to let me know.

     

    As far as I know, there is no option to customize the out of the box web part in Visual Studio, you should develop the custom web part instead of out of the box web part. And for the style and appearance of the out of the box web part, you could use the customize technology to change its style and appearance.

     

    For more information, please refer to:

    http://www.thesharepointmuse.com/2010/05/sharepoint-2010-customization-resources/

     

    Thanks,

    Simon

    Thursday, June 16, 2011 12:12 PM
  • It depends on which OOTB Webpart you want to customize.  Assuming you want to customize it in code to add or remove functionality.

     

    IN order to do it in code the OOTB webpart needs to be inheritable.  For example, consider the following OOTB WebPart called "ListFormWebPart".  This webpart is sealed and it cannot be inherited.  As a result the only way to customize it with code is to Wrap it.

     

    Wrapping WebParts-

    The Process of Creating a Custom Visual Webpart where you take an OOTB webpart that is sealed, like the ListFormWebPart and add it to your Custom WebPart's control Collection.  Doing this you can change the webpart's template name property to cause it to use a different rendering template.  You can also develop your own Editor Part's for it and pass your Editor Part's Values to the ListFormWebPart's Property settings.  Mimicing the OOTB ToolPane for a Wrapped webpart is very difficult because you need to duplicate it's toolpane on your custom wrapper webpart.

     

    Inheriting WebParts-

    The preferred method, if possible, refers to creating a new WebPart (not visual webpart) and then changing it's code behind to inherit from an OOTB WebPart instead of  System.Web.UI.WebParts.WebPart.  This method offers everything the OOTB webpart offers without having to try to duplicate the toolpane.  However some items you want to customize on the inherited webpart might be sealed or non overrideable.  For example, if you want to override a Property called "XslPath" and it's not a virtual property, you can't.  You can only hide it, by creating a new property with the same name.

     

    Exporting WebParts-

    If all your trying to do is automatically configure an OOTB WebPart and make it deployable, you can build the webpart in the browser, and then export it's .webpart file to disk.  Then you can add that .WebPart file to visual studio.

     

    <?xml version="1.0" encoding="utf-8"?>
    <Elements xmlns="http://schemas.microsoft.com/sharepoint/" >
     <Module Name="ListFormWebPart" List="113" Url="_catalogs/wp">
     <File Path="ExportedWebParts\ListFormWebPart.webpart" Url="ListFormWebPart.webpart" Type="GhostableInLibrary">
      <Property Name="Group" Value="Exported WebParts />
     </File>
     </Module>
    </Elements>
    
    

     

    In the above example, I've created a Folder called WebParts in the root of my solution, and in there I created another folder called ExportedWebParts.  Then in the ExportedWebParts folder I added my ListFormWebPart.webpart which I exported from my SharePoint site in the browser.  Then I created an elements file pointing to my .WebPart file.  There is no actual webpart Class or usercontrol in my solution, the webpart is actually in Microsoft.SharePoint....etc.

    Once in my solution I can deploy my .wsp and the exported webpart will show up under the "Exported WebParts" category, then I can drop my preconfigured list form webpart wherever I want it.  The .webpart file contains all the exported properties of the webpart, and those settings get applied to the webpart when the webpart is dropped on a page.

     

    -Final Notes

    In my experience, in some cases where a webpart is inheritable, it's easier to wrap it anyways because the Inheritance might not offer you enough power to customize it the way you want due to non virtual methods/properties etc.   And in other cases, a webpart you want to wrap might have two constructors, a public one with no parameters that doesn't do what you want, and a private one that takes parameters that does do what you want.  In such a case I've had to resort to using reflection to call the private constructor.  A good example of that is the TPPanel class which handles the collapse support on a SharePoint ToolPane Editor Part (I ended up writing my own TPPanel in the end to support more scenarios.)

    In order to know if a webpart is inheritable, or if inheriting it will allow you to do what you want, get a copy of Reflector from RedGate, or ILSpy(Free) ('I prefer refector over ILSpy but it's not free anymore, but 30$ really isn't a bad deal for such a great tool and I'm happy to support their development team.").

     

    Addtionally, let me know what webpart your trying to customize and I'll tell you what your options are.

     


    My Blog: http://www.thesug.org/Blogs/ryan_mann1/default.aspx Website: Under Construction
    Thursday, June 16, 2011 2:36 PM
  • Thanks Ryan for this great reply.  What we need is simple. MostPopularWebPart displays URL, we need to change the URL to Title. I followed the following blog post:

    http://rolandoldengarm.wordpress.com/2011/04/08/whatspopularwebpart-render-titles-instead-of-urls/

    Created WebPart using following code:

      [ToolboxItemAttribute(false)]
      public class TestCustomWebPart : Microsoft.Office.Server.WebAnalytics.Reporting.WhatsPopularWebPart
      {
        protected override void CreateChildControls()
        {
        }
    
        private const string ItemRegEx = @"<span dir=""ltr"">(?<url>[^<]*)</span>";
    
        /// <summary>
        /// Replaces the urls with titles.
        /// </summary>
        /// <param name="html">The HTML.</param>
        /// <returns></returns>
        private static string ReplaceUrlsWithTitles(string html)
        {
          if (Regex.IsMatch(html, ItemRegEx))
          {
            html = Regex.Replace(html, ItemRegEx, delegate(Match match)
            {
              var url = match.Groups["url"].Value;
              var item = SPContext.Current.Site.RootWeb.GetListItem(url);
              string title = url;
              if (item != null)
              {
                title = item.Title;
              }
              return "<span>" + title + "</span>";
            });
          }
          else
          {
            html += "<!-- No match found using ReplaceUrlsWithTitles -->";
          }
          return html;
        }
    
    
    
        /// <summary>
        /// Gets the callback result. Result is loaded asynchronously using javascript
        /// </summary>
        /// <returns></returns>
        public new string GetCallbackResult()
        {
          return ReplaceUrlsWithTitles(base.GetCallbackResult());
        }
      }
    


    Its working fine but not as expected. Still displaying "URL" instead of "Title". I may not able to find any documentation related to Assembly "Microsoft.Office.Server.WebAnalytics.UI" or class "WhatsPopularWebPart". 

    Any help?

    Thursday, June 16, 2011 3:11 PM
  • I see, so your trying to do a string replace on the url in the list item and change it to title?

    The html generation is hard coded into the webpart, it relies on two methods

     

    CreateHTML

    and

    CreateHTMLListItems

     

    Render calls CreateHTML, and CreateHTML calls CreateHTMLListItems.

    CreateHTMLListItems is what's generating the <a href html with the Url's, heres what the code looks like,

              case WhatsPopularType.SearchCenterQueries:
              {
                sb.Append("<li value='");
                sb.Append(Convert.ToString(num2, 10));
                sb.Append("'>");
                sb.Append("<a href=\"");
                sb.Append(searchUrl + "k=");
                sb.Append(SPEncode.UrlEncode((string) row["QueryText"]));
                sb.Append("\">");
                sb.Append(row["QueryText"]);
                sb.Append("</a>");
                this.AddFrequency(sb, row, frequencyColName);
                this.AddTrend(sb, row, i + 1);
                sb.Append("</li>");
    
    


    It generates different html for each type of WhatsPopularType, ContentType's, SearchCenterQueries, and SiteSearchQueries.

     

    Theres no pretty way to do what your trying to do, the fact that it's still displaying URL's in your code means your regex expression isn't finding a match, this your string replace doesn't happen.

     

    What I would do, is get a copy of RegExBuilder from http://renschler.net/RegexBuilder/.  Then in the Text 1 box, enter in the html for one of the List Items.

    Then modify your reg ex till you get a match.

    1. Don't rely on an auto generated id, your reg ex should be able to match the base html tags ignoring any id attributes, otherwise it will only match that one ID and the rest will still be Url's.  It's possible to match part of an ID, e.g. "mypage_mywebpart_whatspopularwebpart"  if the end of the id is always the same, you could match just that part etc.

    you can use a reg ex cheat sheet to help you, in combination with RegExBuilder.  You can build your reg ex and make sure it works before you try it in sharepoint again (saves a ton of time on site spinups.)

    http://www.hci-matters.com/blog/wp-content/uploads/2009/08/RegEx_Chart_Barnes_v2.pdf

     

    Optionally, you can use reflection to analyze what CreateHtml and CreateHtmlListItems does exactly, including it's two boolean parameters, then override Render, and rewrite it from scratch, then you have complete control over what it renders.

     


    My Blog: http://www.thesug.org/Blogs/ryan_mann1/default.aspx Website: Under Construction
    • Marked as answer by Shimin Huang Monday, June 20, 2011 8:28 AM
    Thursday, June 16, 2011 3:45 PM
  • Thanks a lot for your quick reply but it seems that I am missing something here. I am not sure regarding two methods "CreateHTML and CreateHTMLListItems". Did you use reflection? How you find out "CreateHTMLListItems" functionality? 

    I will try to generate a Regx that matches and let you know.

    Thanks again.


    http://farhanfaiz.wordpress.com
    Thursday, June 16, 2011 3:56 PM
  • I used RedGates .Net Reflector,

    it  lets you see the source code of a .net Assembly, (akak Microsoft.Office.Server.WebAnalytics.UI.WhatsPopular)

    http://reflector.red-gate.com/download.aspx?TreatAsUpdate=1

    14 day free trial, best 35$ you'll ever spend imo.


    My Blog: http://www.thesug.org/Blogs/ryan_mann1/default.aspx Website: Under Construction
    Thursday, June 16, 2011 5:22 PM