Displaying Multiple List Blocks using the .NET API

2 minute read time.

The .NET API allows complex screens to be created that contain multiple blocks and meta data objects that fetch,display and interact with the database in many different ways.

One of the tasks that is a little more difficult is the display of multiple list blocks within the same page.

The QuickLook project within the SDK samples does include multiple list blocks but these have had their navigation buttons disabled as can be seen from the image below.

There is a problem with using the navigation buttons. The list block in CRM returns a standard set of HTML to control the next, previous and other navigation within the records. So if more that one list block is rendered there will be a conflict of what the different elements in the page are called and what the different hyperlink buttons are trying to address.

But this can be circumvented within the .NET API too using an old trick. Please see the article, "Displaying Multiple List Blocks using the ASP COM API".

The image below shows how the screens can be displayed.

Note:

The example used in this article is based around the display of data in the company context. In Sage CRM v7.1 the Interactive Dashboard feature is availble to this code would be overkill as compound screens with multiple linked lists and gadgets become very easy to create without any code. Please see the blog articles that discuss Sage CRM v7.1 for more details.

The code

The code uses a trick of a wrapper page that creates the top list block and contains a iframe that displays a page that builds the inner, lower list.

The Wrapper Page

using Sage.CRM.Controls;
using Sage.CRM.UI;
using Sage.CRM.WebObject;
 
namespace SA_Basic_1
{
    class CompanyMultipleList : Web
    {
        public override void BuildContents()
        {
            GetTabs();
            AddContent(HTML.Form());
 
            List listCompanyOppos = new List("opportunitylist");
            listCompanyOppos.Filter = "oppo_primarycompanyid = " + GetContextInfo("company", "comp_companyid");
            
            HTMLString htmlFrame = new HTMLString();
            htmlFrame.Html += "<br/>";
            htmlFrame.Html += "<IFRAME FRAMEBORDER='0' MARGINHEIGHT='0' MARGINWIDTH='0' SCROLLING='NO' NORESIZE WIDTH=100% HEIGHT=400 src='";
            htmlFrame.Html += UrlDotNet(ThisDotNetDll,"RunCaseList");
            htmlFrame.Html+="'></IFrame>";
            
            VerticalPanel vpPageLayout = new VerticalPanel();
            vpPageLayout.Add(listCompanyOppos);
            vpPageLayout.Add(htmlFrame);
            vpPageLayout.AddAttribute("width", "100%");
 
            AddContent(vpPageLayout);
 
            AddUrlButton("newopportunity", "newopportunity.gif", Url("1190"));
            AddUrlButton("newcase", "newcase.gif", Url("1192"));
            AddHelpButton("help.htm");
 
        }
    }
}

The Inner Page

using Sage.CRM.Controls;
using Sage.CRM.UI;
using Sage.CRM.Utils;
using Sage.CRM.WebObject;
namespace SA_Basic_1
{
    class CaseList : Web
    {
        public override void BuildContents()
        {
            this.DontAddToHistory();
            this.OverrideContent("text/html; charset=utf-8");
 
            HTMLString htmlheaders = new HTMLString();
            htmlheaders.Html = "<html><head><link rel='stylesheet' HREF='/";
            htmlheaders.Html += Dispatch.InstallName + "//Themes//";
            htmlheaders.Html +=CurrentUser["PreferredCSSTheme"]+".css'></head><body>";
            HTMLString htmlend = new HTMLString();
            htmlend.Html = "</form></body></html>";
            
            AddContent(htmlheaders);
            
            string strScriptForHeader = "<script>window.attachEvent('onload',hideButton);function hideButton(){var strSpan='';var strLink='';for(i=0;i<document.all.length;i++){if(document.all[i].tagName=='A'){document.all[i].target='EWARE_MID';}}</script>";
            AddContent(strScriptForHeader);
            AddContent(HTML.Form());
             List listcases = new List("caselist");
            listcases.Filter = "case_primarycompanyid = " + GetContextInfo("company", "comp_companyid");
            AddContent(listcases);
            AddContent(htmlend);        
        }
    }
}

Note:

  • The inner page uses the OverrideContent() method. This is because without it the Notifications would display in the lower page. This means that the full HTML page has to be built.
  • The reference to the style guide is made within the Head tag.

  • Hi Jeff (I'm assuming it was you that originally posted this!),

    Is there some code missing from the Wrapper page above (been stripped out when moved here from the old community site)?

    There seems to be a lot of assigning empty strings to variables and adding them to the screen content in both the Wrapper code and inner frame code.

    I've noticed this on some of the other older code samples as well.

    Cheers,

    Mike