Expression Evaluation Time: ms / Round trip: ms
How to implement a detail view web part
22. Apr
2013
by Markus Lindenmann Category:
Technical
0

This sample demonstrates, how a basic custom Detail View Web Part can be implemented, using the 'MatchPoint Configuration' and the 'MatchPoint Connection Framework'. The web part is supposed to render specified detail information for a selected data grid row, even if this information is not displayed in the origin data grid.

Introduction

This sample demonstrates, how a basic custom Detail View Web Part can be implemented, using the 'MatchPoint Configuration' and the 'MatchPoint Connection Framework'. The web part is supposed to render specified detail information for a selected data grid row, even if this information is not displayed in the origin data grid.

This blog post describes the implementation of a consumer web part, previously described in the following blog post: How to implement a consumer / producer webpart.

Implementation

Overview

The Detail View Web Part implementation consists of multiple components:

  • A C# file, describing the HTML generation and server sided code
  • A JavaScript code behind file, as mediator between server and front end
  • A CSS file, describing the web part's style

Configuration

The Detail View Web Part configuration is specified in the class DetailViewWebPartConfiguration, which implements the interface Colygon.MatchPoint.Core.WebParts.IWebPartConfiguration and is member of the namespace Colygon.MatchPoint.Samples.WebParts. It specifies the web part properties shown in the MatchPoint configuration editor.

Each of the following public fields describes a setting in the web part's configuration, later shown in the MatchPoint configuration editor. The MemberDescriptor attribute (Colygon.MatchPoint.Core.Administration.ConfigurationEditor.MemberDescriptorAttribute) is used to describe these settings and to define the appearance in the configuration editor; the first constructor argument is a textual description, the (optional) Boolean flag describes, whether the setting is mandatory or not. For completeness it is to be mentioned that there are further optional constructor arguments, e.g. to specify a friendly name, etc.; However, they are not required in this example and hence not further described. If further information is required, you might want to take a look at the technical reference available in the download section.

[Serializable]
[ClassDescriptor(Category = "Web Parts")]
public class DetailViewWebPartConfiguration : IWebPartConfiguration
{
  [MemberDescriptor("Specifies the expression, describing "
                                       + "the details view.", true)]
  public ExpressionString Expression;

  [MemberDescriptor("Specifies how details are represented.", true)]
  public DisplayMode DisplayMode;

  [MemberDescriptor("Specifies whether column names should be "
                                       + "displayed or not.", true)]
  public bool ShowColumnNames;

  [MemberDescriptor("Specifies the column, shown as title in "
                                       + "the details view.", true)]
  public string TitleColumName;

  [MemberDescriptor("Specifies the column, shown as description "
                                          + "in the details view.")]
  public string DescriptionColumnName;

  [MemberDescriptor("Specifies the columns, shown as further "
                                  + "details in the details view.")]
    public string[] FurtherDetailColumns;

  public virtual WebPart CreateWebPart()
  {
    return new DetailViewWebPart();
  }
}

Where DisplayMode is an enum, rendered as a drop-down list in the 'MatchPoint Configuration Editor'.

public enum DisplayMode
{
  Rows,
  Columns,
  Fancy
};

After deploying, the configuration can be selected from 'Create' in the 'Manage MatchPoint Configurations' view (Ctrl-M). It is then rendered in the 'MatchPoint Configuration Editor', as depicted in Figure 1 below. The settings specified in the DetailViewWebPartConfiguration class are rendered in a form, according to the fields types, their names and the assigned MemberDescriptor attributes.

Figure 1: Detail View Web Part configuration, rendered in MatchPoint Configuration Editor

The web part

The web part's logic is implemented in an extension of Colygon.MatchPoint.Core.WebParts.BaseWebPart, where the previously implemented configuration is used as generic type argument.

public class DetailViewWebPart :
                            BaseWebPart<DetailViewWebPartConfiguration>
{
}

In a next step, we override OnInit(EventArgs e), to be able to register our new web part as consumer of the source, specified in Configuration.Expression and unrolled automatically in the DependencyCollection by AddFromExpression, which tries to find SelectedRow on the specified source expression.

protected override void OnInit(EventArgs e)
{
  base.OnInit(e);
  try
  {
    DependencyCollection dc = new DependencyCollection();
    // if and only if EndPoint == SelectedRow:
    //     => the following will add all columns implicitly
    dc.AddFromExpression(Configuration.Expression);

    if (dc.Count <= 0) return;
    if (dc.Count > 1) throw new InvalidOperationException(
             "Cannot depend on more than one connection data source.");

    // if endPoint is not a SelectedRow, we have to add the columns
    // we'll just do it in every case, to be on the safe side ...
    dc[0].Add(Configuration.TitleColumName);
    if (Configuration.DescriptionColumnName != null)
    {
      dc[0].Add(Configuration.DescriptionColumnName);
    }
    foreach (string column in Configuration.FurtherDetailColumns
                              ?? new string[0])
    {
      dc[0].Add(column);
    }

    // Register this control as consumer;
    // requiring all columns specified in config and collected in dc.
    ConnectionManager.RegisterConsumer(this, dc);
    JavaScriptBehaviorManager.RegisterBehavior(this,
                                          "Samples.DetailViewWebPart");
  }
  catch (Exception ex)
  {
    HandleError(ex);
  }
}

Finally we add a small method, which later on can be called from client-sided JavaScript. To achieve this, the method has to be public and decorated with the Colygon.MatchPoint.Core.Ajax.AjaxMethod.Attribute.

[AjaxMethod]
public string GetHtml()
{
  object value = Configuration.Expression.Evaluate(null);
  if (value == null) return null;

  IResultRecord record = value as IResultRecord;
  if (record == null)
  {
    throw new NotSupportedException("'Expression' is expected to "
                        + "return a result of type 'IResultRecord'.");
  }

  switch (Configuration.DisplayMode)
  {
    default:
      // Omitted for readability.
      // Should generate some meaningful HTML...
      return "";
  }
}

JavaScript code behind

The following small JavaScript code behind snippet overrides Refresh(), called to refresh the content / details for the current evaluation of the specified expression and calling GetHtml, previously defined in C# and decorated with the AjaxMethodAttribute.

$$.Namespace("Samples").DetailViewWebPart = function()
{
  /*
   * Called, when datasource notifies consumers about changes.
   * Requests new information from the server and delegates
   * answers to GetHtml_Callback.
   */
  this.Refresh = function()
  {
    if (this.Control)
    {
      $$.ProgressIndicator.Show(this.Control);
      this.Callback.GetHtml($$.Delegate.Create(this,
                                              this.GetHtml_Callback));
    }
  };

  /* 
   * Writes information retrieved from the server to the control.
   */
  this.GetHtml_Callback = function(res)
  {
    $$.ProgressIndicator.Hide(this.Control);
    $(this.Control).html(res.Value);
  };
}

Source code

All three files (C#, JavaScript, CSS) are available in this ZIP-archive.

Comments
ABOUT

This blog is about technical and non-technical aspects of the product MatchPoint and other SharePoint topics.

If you would like to post an article or if you have an idea for a post, please contact us.

ARCHIVE
COMMENTS
Matthias Weibel
09.04.2018 01:12
Link is updated and works now. | Goto Post
Dhanabalan
09.04.2018 12:21
Link doesn't work. Could anyone explain what does... | Goto Post
matthiaszbrun
14.03.2018 02:05
Hi Markus
We I use the config for SiteCollectionSe... | Goto Post
Reto Jeger
04.10.2017 09:15
Hello Reiner,
Thanks for pointing out the missing ... | Goto Post
rganser
29.09.2017 09:56
Hi, I downloaded the ZIP-file for MatchPoint Versi... | Goto Post