Free cookie consent management tool by TermsFeed Policy Generator
wiki:Documentation/DevelopmentCenter/CreateNewViews

Version 6 (modified by ascheibe, 12 years ago) (diff)

--

How to ... implement a view

In HeuristicLab contents and views are strictly separated. A view must be derived from IContentView and tagged with a ViewAttribute and ContentAttribute. The reason behind this is, that the MainFormManager automatically discovers all classes of type IContentView to allow the automatic display of contents by the MainForm.

MainFormManager.MainForm.ShowContent(IContent content);                     //displays the content with its default view
MainFormManager.MainForm.ShowContent(IContent content, Type viewType);      //displays the content with the specified view type

In addition, there is an specialized control provided that is able to display arbitrary contents, the ViewHost. It can be used if the content type is not known during compile time, for example in collection views. In the following the implementation of the StringConvertibleValueView will be explaind in detail to describe the core functionality of the view concept in HeuristicLab.

The StringConvertibleValueView is located in HeuristicLab.Data.View and consists of a label and a textbox.

added image to howto views

Frame of HeuristicLab views

  [View("StringConvertibleValue View")]
  [Content(typeof(IStringConvertibleValue), true)]
  public partial class StringConvertibleValueView : AsynchronousContentView {
    public new IStringConvertibleValue Content {
      get { return (IStringConvertibleValue)base.Content; }
      set { base.Content = value; }
    }
  }

First of all, one will notice the two attributes on the StringConvertibleValueView. The ViewAttribute is responsible for providing an identifier that can be used in the GUI. The second attribute, the ContentAttribute, is more important as it states which type of contents can be displayed by the view. The first parameter of the ContentAttribute states the displayable content types and the second parameter wheter or not the view should be used per default for this content type. In this example, the StringConvertibleValueView can display all contents of type IStringConvertibleValue and furthermore is used as a default. It is important that it can only exists one default view per content type, because otherwise it is undecidable which view should be used to display the according content.

Registering content events and updating of controls

    protected override void DeregisterContentEvents() {
      Content.ValueChanged -= new EventHandler(Content_ValueChanged);
      base.DeregisterContentEvents();
    }

    protected override void OnContentChanged() {
      base.OnContentChanged();
      if (Content == null) {
        valueTextBox.Text = string.Empty;
      } else
        valueTextBox.Text = Content.GetValue();
    }

    protected override void RegisterContentEvents() {
      base.RegisterContentEvents();
      Content.ValueChanged += new EventHandler(Content_ValueChanged);
    }

   private void Content_ValueChanged(object sender, EventArgs e) {
      if (InvokeRequired)
        Invoke(new EventHandler(Content_ValueChanged), sender, e);
      else
        valueTextBox.Text = Content.GetValue();
    }

If a new content is set in a view, first the DeregisterContentEvents method is called, afterwards OnContentChanged and at last RegisterContentEvents. DeregisterContentEvents is responsible for deregistering events from the "old" content, and is only called if the old content is not null. OnContentChanged the controls in the view must be filled with the properties of the content, in this case the valueTextBox is either populated with the result of Content.GetValue() or displays nothing (String.Empty) if the content is null. RegisterContentEvents is the equivalent to DeregisterContentEvents for registering necessary events on the new content object. If the Content changes its value the previously registered Content_ValueChanged method is called and the value of the TextBox is updated. Please keep in mind, that these events are often called asynchronous and therefore, an InvokeRequired check with according Invoke call is necessary (more information on thread-safe calls to controls).

Enabling & Disabling of Controls

Every HeuristicLab view has the two states Locked and ReadOnly that are used to indicate if an operation is in progress and contents should not be altered, e.g. saving to a file or a running algorithm. Changes to these two properties, as well as content changes, trigger to following overriden method.

 protected override void SetEnabledStateOfControls() {
      base.SetEnabledStateOfControls();
      valueTextBox.Enabled = !Locked && Content != null;
      valueTextBox.ReadOnly = ReadOnly;
    }

In SetEnabledStateOfControls used controls must be adapted according to the current state of the view. If other HeuristicLab views are nested in the current view, no additional handling is necessary, as state changes are automatically propagated by the base class.

The Locked state of a view is set if a operation is in progress and ReadOnly is used if the content object itself indicates that it must not be changed. Most times the enabled property corresponds to the Locked state and additionally to ReadOnly if not separates handling is provided by the control.

Setting the AutoScaleMode of ContainerControls

To guarantee that HeuristicLab is rendered correctly with different font sizes and language settings (see #1688 for more information), the AutoScaleMode of ContainerControls has to be set to Inherit. This property can be configured in the Visual Studio Windows Forms designer in the properties window:

This covers the main parts that must be kept in mind when developing new views for HeuristicLab. You can find the source code of the StringConvertibleValueView used as an example attached to this page.

Attachments (3)

Download all attachments as: .zip