Custom Detail View Web Part

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.

It is strongly recommended to read the Custom Connectable Web Part previously.

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 IWebPartConfiguration Interface 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 (MemberDescriptorAttribute Class) 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.

The web part

The web part's logic is implemented in an extension of BaseWebPart<T>, where the previously implemented configuration is used as generic type argument.

    public class DetailViewWebPart : BaseWebPart
    {
    }

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 AjaxMethodAttribute.

[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 data source 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);
  };
}

See Also

Custom Connectable Web Part

results matching ""

    No results matching ""