Clone our Wealth-Lab 8 Extension Demo project on GitHub to get a head start in developing your own Extensions!

Chart Drawing Object API

A Chart Drawing Object Extension allows you to create custom drawing tools that users can place interactively on WealthLab 9 charts. Drawing Objects appear in the drawing toolbar when a chart has focus. The user selects a Drawing Object and then clicks or drags on the chart to place it. Common Drawing Objects include:

  • Trendlines
  • Triangles and other shapes
  • Fibonacci Retracements

Build Environment

You can create a Drawing Object in a .NET development tool such as Visual Studio 2026. Create a class library project that targets .NET10, then reference the WealthLab.ChartWPF library DLL that you'll find in the WL9 installation folder.

Your Drawing Object will be a class in this library that descends from DrawingObjectBase, which is defined in the WealthLab.ChartWPF library, in the WealthLab.ChartWPF namespace. After you implement and build your library, simply copy the resulting assembly DLL into the WL9 installation folder. The next time WL9 starts up, it will discover your Drawing Object, making it available in appropriate locations of the WL9 user interface.

Visual Studio 2026 Build Environment

DrawingObjectBase derives from PlotBase. Consult the PlotBase class reference for additional properties and methods available to Drawing Objects.

Accessing the Host (WL9) Environment

The IHost interface provides access to the current WealthLab environment. Extensions can use it to retrieve application-level information and services, such as the location of the user's WealthLab data folder or the DataSets defined by the user.

You can access the current IHost instance from anywhere in your extension through the WLHost singleton and its Instance property. For example, the following code retrieves the path to the user's WealthLab data folder:

string folder = WLHost.Instance.DataFolder;

Use WLHost.Instance whenever your extension needs access to functionality exposed by the IHost interface.

Descriptive Properties

DrawingObjectBase ultimately derives from Configurable, which provides the descriptive properties used to identify your Drawing Object in WealthLab. Important properties to override include:

  • Name - The name displayed for the Drawing Object.
  • GlyphResource - The icon used to represent the Drawing Object in the drawing toolbar.

DrawingObjectBase also provides several properties specific to Drawing Objects.

public string GroupName

Determines the group under which the Drawing Object appears in the drawing toolbar. The default value is "Basic". Override this property to group related Drawing Objects together.

public virtual bool AutoEdit

Determines whether WealthLab automatically opens the Drawing Object's parameter editor immediately after the user places it on a chart.

The default value is false.

Return true when the Drawing Object normally requires additional user input after placement. For example, the Text Note Drawing Object uses this behavior so the user can enter the note text immediately after placing it.

Drawing Object Parameters

DrawingObjectBase uses the standard Configurable parameter framework. Override GenerateParameters to add Parameter instances to the Drawing Object's Parameters collection. The user can then edit these values to control the Drawing Object's appearance or behavior.

Default Parameters

The default implementation of GenerateParameters adds the following Parameters:

  • Color - WLColor
  • Line Width - Int32
  • Line Style - LineStyle

If you override GenerateParameters and want to retain these standard properties, call the base implementation first:

public override void GenerateParameters()
{
    base.GenerateParameters();

    // add custom parameters here
}

Filled Shape Parameters

protected void AddFilledShapeParameters()

Call this method from GenerateParameters when your Drawing Object represents a shape that can optionally be filled. It adds the following Parameters:

  • Fill? - Boolean
  • Opacity (0-100) - Int32

For example:

public override void GenerateParameters()
{
    base.GenerateParameters();
    AddFilledShapeParameters();
}

Accessing the CoreChart

public CoreChart Chart

This property is inherited from PlotBase and returns the CoreChart instance on which the Drawing Object is being rendered. Use this property when your Drawing Object needs information or functionality from the underlying chart.

Handles and Lines

A Drawing Object is typically composed of Handles and DrawingObjectLines. Handles are the small control points that appear when the user interacts with a Drawing Object. The user can drag a Handle to change the position or shape of the object.

Every Drawing Object must contain at least one Handle. Lines typically connect two Handles. Depending on their configuration, the user can also drag a line to move the entire Drawing Object.

public List<Handle> Handles

Contains the Handle instances that belong to the Drawing Object.

public List<DrawingObjectLine> Lines

Contains the DrawingObjectLine instances that belong to the Drawing Object.

Snap to Price

public bool SnapToPrice

Controls whether Handles snap to chart prices as the user moves them. This property is effective only if the Drawing Object contains a Boolean Parameter named:

Snap to Price

Responding to a Handle Move

public virtual void HandleMoved(Handle h)

WealthLab calls this method after the user moves one of the Drawing Object's Handles. Override it when moving one Handle requires additional calculations or changes to other Handles. For example, you might use it to maintain a geometric relationship between several points.

Creating the Drawing Object

public abstract Handle InitializeAt(double x, double y)

WealthLab calls InitializeAt when the user begins placing the Drawing Object on the chart. Override this method to create the Handles and Lines that make up your Drawing Object. The x and y parameters contain the chart coordinates where the user began drawing. Return the Handle that WealthLab should allow the user to drag while completing the initial placement of the Drawing Object.

Adding Handles

protected Handle AddHandle(double x, double y)
protected Handle AddHandle(DateTime dt, double val)

Use AddHandle to create a Handle. You can specify its location using either:

  • Chart pixel coordinates, using x and y.
  • Chart data coordinates, using a DateTime and y-axis value.

For example, the Triangle Drawing Object creates three Handles:

public override Handle InitializeAt(double x, double y)
{
    Handle h1 = AddHandle(x - 100, y - 50);
    Handle h2 = AddHandle(x, y);
    Handle h3 = AddHandle(x - 100, y + 50);

    AddLine(h1, h2);
    AddLine(h2, h3);
    AddLine(h3, h1);

    return h2;
}

In this example, h2 is returned so it becomes the Handle the user drags while initially placing the Triangle.

Adding Lines

protected DrawingObjectLine AddLine(
    double x1,
    double y1,
    double x2,
    double y2,
    bool canDrag = true)

protected DrawingObjectLine AddLine(
    Handle handle1,
    Handle handle2,
    bool canDrag = true)

protected DrawingObjectLine AddLine(
    DateTime dt1,
    double val1,
    DateTime dt2,
    double val2,
    bool canDrag = true)

Use AddLine to add a line to the Drawing Object. A line can be defined using:

  • Pixel coordinates.
  • Two previously created Handles.
  • Two DateTime/value coordinates.

The optional canDrag parameter controls whether the user can drag the line to move the Drawing Object. For example, the Trendline Drawing Object can create its line directly from the initial mouse position:

public override Handle InitializeAt(double x, double y)
{
    AddLine(x, y, x, y, true);
    return Lines[0].Handle2;
}

The second Handle of the new line is returned so that the user can drag it to establish the Trendline's endpoint.

Responding to User Interaction

DrawingObjectBase provides several methods you can override to respond as the user manipulates a Drawing Object.

public virtual void Moved(
    double startX,
    double startY,
    double x,
    double y)

Called while the user moves the Drawing Object. startX and startY contain the mouse coordinates where the move began. x and y contain the current mouse coordinates. Override this method when your Drawing Object needs custom processing as the entire object is moved.

public virtual void HandleMoved()

Called while the user moves one of the Drawing Object's Handles. Override this method when you need to perform processing continuously as a Handle is dragged.

public virtual void MoveComplete()

Called when the user finishes moving the Drawing Object and releases the mouse button. Override this method when processing should occur only after a move operation has completed.

Rendering Drawing Objects

DrawingObjectBase provides default rendering for standard lines and Handles. Override the rendering methods when your Drawing Object requires additional or custom graphics.

Render

public override void Render(DrawingContext dc)

The default implementation renders the Drawing Object's Lines using its configured:

  • Color
  • Line Width
  • Line Style

Override Render if you need to replace or augment the standard rendering. If you want to retain the standard lines while drawing additional content, call the base implementation before performing your custom rendering.

Highlight Rendering

public override void RenderHighlight(DrawingContext dc)

Called when the Drawing Object is highlighted, typically when the user moves the mouse over it. The default implementation renders the object's Handles and then calls RenderDrawingObjectHighlight. If you want to preserve the standard Handle rendering but customize how the Drawing Object itself is highlighted, override RenderDrawingObjectHighlight instead.

public virtual void RenderDrawingObjectHighlight(
    DrawingContext dc)

Called by RenderHighlight to render the highlighted representation of the Drawing Object. The default implementation renders a thick, translucent highlight over the first line in the Lines collection. Override this method to replace or augment the default highlighting behavior.

protected void RenderAllLinesHighlighted(
    DrawingContext dc)

Call this helper from RenderDrawingObjectHighlight to render the highlight effect over every line in the Drawing Object.

Rendering Helpers

DrawingObjectBase provides several helpers for rendering using the Drawing Object's configured Parameters.

protected Brush GetBrush()

Returns a Brush that can be used to fill a Drawing Object based on its configured color, fill, and opacity Parameters.

protected Pen GetPen(DrawingObjectLine line = null)

Returns a Pen configured from the Drawing Object's line Parameters. Optionally pass a DrawingObjectLine to obtain a Pen configured for that particular line.

protected Pen GetHighlightPen()

Returns the Pen used to render highlighted portions of the Drawing Object.

protected bool IsFilled

Returns true if the Drawing Object's Fill? Parameter is enabled.

protected Color FillColor

Returns the effective fill Color, taking the Drawing Object's configured color and fill opacity into account.

protected List<Point> GetPointsArray()

Returns a collection of Point instances representing the Drawing Object's Lines. This can be useful when rendering polygonal or filled Drawing Objects.

Example: Triangle Drawing Object

The following is a complete implementation of a simple Triangle Drawing Object:

namespace WealthLab.ChartWPF
{
    public class TriangleDrawingObject : DrawingObjectBase
    {
        public override void GenerateParameters()
        {
            base.GenerateParameters();
            AddFilledShapeParameters();
        }

        public override string Name => "Triangle";

        public override string GlyphResource =>
            "WealthLab.ChartWPF.Glyphs.TriangleDrawing.png";

        public override Handle InitializeAt(double x, double y)
        {
            Handle h1 = AddHandle(x - 100, y - 50);
            Handle h2 = AddHandle(x, y);
            Handle h3 = AddHandle(x - 100, y + 50);

            AddLine(h1, h2);
            AddLine(h2, h3);
            AddLine(h3, h1);

            return h2;
        }
    }
}