Для изменения размера нажмите или перетащите

Графический рендерер индикаторов

Некоторые индикаторы требуют особого стиля прорисовки как, например, для индикатора BollingerBands это две линии. Или для индикатора Fractals это точки. В этом случае необходимо явно указывать в ChartIndicatorElement графический рендерер индикаторов.

C#
var chartIndicatorElement = new ChartIndicatorElement()
{
    IndicatorPainter = new BollingerBandsPainter(),
};

Рассмотрим на примере индикатора Fractals как создать собственный IndicatorPainter.

Все IndicatorPainter должны быть унаследованны от базового класса BaseChartIndicatorPainter или интерфейса IChartIndicatorPainter:

C#
/// <summary>
/// The chart element for <see cref="Fractals"/>.
/// </summary>
[Indicator(typeof(Fractals))]
public class FractalsPainter : BaseChartIndicatorPainter
{
...
}

Зададим элементы графика ChartLineElement которые будут представлять верхний и нижний фракталы:

C#
/// <summary>
/// The chart element for <see cref="Fractals"/>.
/// </summary>
[Indicator(typeof(Fractals))]
public class FractalsPainter : BaseChartIndicatorPainter
{
    /// <summary>
    /// <see cref="Fractals.Up"/> dots color.
    /// </summary>
    [Display(
        ResourceType = typeof(LocalizedStrings),
        Name = LocalizedStrings.Str2035Key,
        Description = LocalizedStrings.Str2036Key)]
    public ChartLineElement Up { get; }

    /// <summary>
    /// <see cref="Fractals.Down"/> dots color.
    /// </summary>
    [Display(
        ResourceType = typeof(LocalizedStrings),
        Name = LocalizedStrings.Str2037Key,
        Description = LocalizedStrings.Str2038Key)]
    public ChartLineElement Down { get; }
...
}

В конструкторе FractalsPainter зададим им значения и основные свойства цвет, толщину и стиль прорисовки. После чего добавляем их как дочерний элемент графика:

C#
...
    /// <summary>
    /// Create instance.
    /// </summary>
    public FractalsPainter()
    {
        Up = new ChartLineElement { Color = Colors.Green };
        Down = new ChartLineElement { Color = Colors.Red };

        Up.Style = Down.Style = ChartIndicatorDrawStyles.Dot;
        Up.StrokeThickness = Down.StrokeThickness = 4;

        AddChildElement(Up);
        AddChildElement(Down);
    }
...

Переопределяем метод OnDraw в котором с помощью метода DrawValues(IIndicator, IChartElement) прорисовываем индикатор:

C#
...
    /// <inheritdoc />
    protected override bool OnDraw()
    {
        var ind = (Fractals)Indicator;
        var result = false;

        result |= DrawValues(ind.Down, Down);
        result |= DrawValues(ind.Up, Up);

        return result;
    }
...

Полный код FractalsPainter:

C#
/// <summary>
/// The chart element for <see cref="Fractals"/>.
/// </summary>
[Indicator(typeof(Fractals))]
public class FractalsPainter : BaseChartIndicatorPainter
{
    /// <summary>
    /// <see cref="Fractals.Up"/> dots color.
    /// </summary>
    [Display(
        ResourceType = typeof(LocalizedStrings),
        Name = LocalizedStrings.Str2035Key,
        Description = LocalizedStrings.Str2036Key)]
    public ChartLineElement Up { get; }

    /// <summary>
    /// <see cref="Fractals.Down"/> dots color.
    /// </summary>
    [Display(
        ResourceType = typeof(LocalizedStrings),
        Name = LocalizedStrings.Str2037Key,
        Description = LocalizedStrings.Str2038Key)]
    public ChartLineElement Down { get; }

    /// <summary>
    /// Create instance.
    /// </summary>
    public FractalsPainter()
    {
        Up = new ChartLineElement { Color = Colors.Green };
        Down = new ChartLineElement { Color = Colors.Red };

        Up.Style = Down.Style = ChartIndicatorDrawStyles.Dot;
        Up.StrokeThickness = Down.StrokeThickness = 4;

        AddChildElement(Up);
        AddChildElement(Down);
    }

    /// <inheritdoc />
    protected override bool OnDraw()
    {
        var ind = (Fractals)Indicator;
        var result = false;

        result |= DrawValues(ind.Down, Down);
        result |= DrawValues(ind.Up, Up);

        return result;
    }

    #region IPersistable

    /// <inheritdoc />
    public override void Load(SettingsStorage storage)
    {
        base.Load(storage);

        Up.Load(storage.GetValue<SettingsStorage>(nameof(Up)));
        Down.Load(storage.GetValue<SettingsStorage>(nameof(Down)));
    }

    /// <inheritdoc />
    public override void Save(SettingsStorage storage)
    {
        base.Save(storage);

        storage.SetValue(nameof(Up), Up.Save());
        storage.SetValue(nameof(Down), Down.Save());
    }

    #endregion
}