Back to Devexpress

Chart Designer for End Users

windowsforms-114127-controls-and-libraries-chart-control-end-user-features-chart-designer-for-end-users.md

latest29.1 KB
Original Source

Chart Designer for End Users

  • Jan 15, 2024
  • 13 minutes to read

The Chart Designer allows users to customize the chart’s appearance. This topic explains how to invoke and modify the Chart Designer.

This article consists of the following sections:

Invoke the Chart Designer

Create a ChartDesigner class instance and pass a ChartControl that should be customized to the ChartDesigner constructor parameters. Use the ChartDesigner.ShowDialog method to invoke the designer.

csharp
ChartDesigner designer = new ChartDesigner(chartControl);
designer.ShowDialog();
vb
Dim designer As New ChartDesigner(chartControl)
designer.ShowDialog()

Customize the Chart Designer

The following API members allow you to customize the Chart Designer:

ChartDesigner.IconGets or sets the Designer form icon.ChartDesigner.ShowIconGets or sets the value indicating whether the Designer form icon should be shown.ChartDesigner.ShowActualDataSpecifies whether to use sample data or data from the underlying data source to build a chart for the Chart Designer’s preview.ChartDesigner.AddElementMenuOptionsReturns options of the Add Element menu.ChartDesigner.CaptionGets or sets the Designer form caption.ChartDesigner.EnableLargeDataSetWarningGets or sets the value indicating whether the warning about possible freezes on large data sets should be shown.ChartDesigner.AvailableViewTypesGets or sets a list of groups of series views available to show on the chart.ChartDesigner.ChartElementHighlightingOccurs when chart element highlighting begins.ChartDesigner.ChartElementSelectingOccurs when chart element selection begins.ChartDesigner.ChartStructureUpdatingUsed to customize the Chart Designer Elements’ Tree.ChartDesigner.PropertyDescriptorsCustomizingOccurs when property descriptor customization required.

csharp
ChartDesigner designer = new ChartDesigner(chartControl1);
designer.Icon = new System.Drawing.Icon("../../../Icon.ico", new System.Drawing.Size(32,32));
designer.ShowIcon = true;
designer.AddElementMenuOptions.ShowAddSeriesMenuItem = false;
designer.AddElementMenuOptions.ShowAddSeriesTitleMenuItem = false;
designer.Caption = "Chart Designer";
designer.EnableLargeDataSetWarning = true;
designer.AvailableViewTypes.Clear();
designer.AvailableViewTypes.Add(new ViewTypeGroup("Available Series", new List<ViewType> { ViewType.Area, ViewType.Spline, ViewType.Bar }));

designer.ChartElementHighlighting += OnChartElementHighlighting;
designer.ChartElementSelecting += OnChartElementSelecting;
designer.ChartStructureUpdating += OnChartStructureUpdating;
designer.PropertyDescriptorsCustomizing += OnDesignerPropertyDescriptorsCustomizing;

designer.ShowDialog();

// Handlers for these events are shown below:

private void OnChartStructureUpdating(object sender, ChartStructureChangingEventArgs e) {
    e.ChartModel.Series.AllowAddChild = false;
    foreach(SeriesModel seriesModel in e.ChartModel.Series) { 
        seriesModel.AllowChangeVisibility = false;
        seriesModel.AllowRemove = false;
    }
    e.ChartModel.Legends.ShowInStructureControl = false;
}

private void OnChartElementSelecting(object sender, ChartElementSelectingEventArgs e) {
    if(e.ElementModel is SeriesBaseModel) {
        e.Cancel = false;
        return;
    }
    if (e.ElementModel is LegendModel) {
        e.ShowPropertiesTab = false;
        e.ShowDataTab = false;
        e.CustomOptionsControl = new CustomLegendOptionsControl(e.ElementModel); 
    }
}

private void OnChartElementHighlighting(object sender, ChartElementHighlightingEventArgs e) {
    SeriesBaseModel series = e.ElementModel as SeriesBaseModel;
    if(series == null) {
        e.Cancel = true;
        return;
    }

}

private void OnDesignerPropertyDescriptorsCustomizing(object sender, PropertyDescriptorsCustomizingEventArgs e) {
    if (e.ElementModel is ChartModel) {
        e.Properties.Remove(e.Properties["BackColor"]);
    }
}
vb
Dim designer As New ChartDesigner(chartControl1)
designer.Caption = "Chart Designer"
designer.Icon = New System.Drawing.Icon("../../../Icon.ico", New System.Drawing.Size(32, 32))
designer.ShowIcon = True
designer.AddElementMenuOptions.ShowAddSeriesMenuItem = False
designer.AddElementMenuOptions.ShowAddSeriesTitleMenuItem = False
designer.Caption = "Chart Designer"
designer.EnableLargeDataSetWarning = True
designer.AvailableViewTypes.Clear
designer.AvailableViewTypes.Add(New ViewTypeGroup("Available Series", New List(Of ViewType) From { ViewType.Area, ViewType.Spline, ViewType.Bar }))

AddHandler designer.ChartElementHighlighting, AddressOf OnChartElementHighlighting
AddHandler designer.ChartElementSelecting, AddressOf OnChartElementSelecting
AddHandler designer.ChartStructureUpdating, AddressOf OnChartStructureUpdating
AddHandler designer.PropertyDescriptorsCustomizing, AddressOf OnDesignerPropertyDescriptorsCustomizing

designer.ShowDialog()

' Handlers for these events are shown below:

Private Sub OnChartStructureUpdating(ByVal sender As Object, ByVal e As ChartStructureChangingEventArgs)
    e.ChartModel.Series.AllowAddChild = False

    For Each seriesModel As SeriesModel In e.ChartModel.Series
        seriesModel.AllowChangeVisibility = False
        seriesModel.AllowRemove = False
    Next

    e.ChartModel.Legends.ShowInStructureControl = False
End Sub

Private Sub OnChartElementSelecting(ByVal sender As Object, ByVal e As ChartElementSelectingEventArgs)
    If TypeOf e.ElementModel Is SeriesBaseModel Then
        e.Cancel = False
        Return
    End If

    If TypeOf e.ElementModel Is LegendModel Then
        e.ShowPropertiesTab = False
        e.ShowDataTab = False
        e.CustomOptionsControl = New CustomLegendOptionsControl(e.ElementModel)
    End If
End Sub

Private Sub OnChartElementHighlighting(ByVal sender As Object, ByVal e As ChartElementHighlightingEventArgs)
    Dim series As SeriesBaseModel = TryCast(e.ElementModel, SeriesBaseModel)

    If series Is Nothing Then
        e.Cancel = True
        Return
    End If
End Sub

Private Sub OnDesignerPropertyDescriptorsCustomizing(ByVal sender As Object, ByVal e As PropertyDescriptorsCustomizingEventArgs)
    If TypeOf e.ElementModel Is ChartModel Then
        e.Properties.Remove(e.Properties("BackColor"))
    End If
End Sub

You can use the ChartDesigner.ChartElementSelecting event to replace the control used in the Options tab. The custom control should inherit the DevExpress.XtraCharts.Designer.CustomOptionsControl class. The image below shows a custom Legend Options tab.

The following code demonstrates how to design the Legend Options tab as shown in the previous image:

cs
#region #CustomOptionsControl
using DevExpress.Utils;
using DevExpress.XtraCharts;
using DevExpress.XtraCharts.Designer;
using System;
using System.Windows.Forms;

namespace CrosshairOptions {
    partial class CustomLegendOptionsControl : CustomOptionsControl {
        bool updateStarted = false;

        LegendModel LegendModel { get { return (LegendModel)this.Model; } }

        public CustomLegendOptionsControl(ChartElementModel model) : base(model) {
            InitializeComponent();
            if(!(model is LegendModel)) throw new ArgumentException("The model must have the LegendModel type.");
        }

        protected override void OnLoad(EventArgs e) {
            base.OnLoad(e);

            var horizontalAlignments = Enum.GetValues(typeof(LegendAlignmentHorizontal));
            cbeHorizontalAlignment.Properties.Items.AddRange(horizontalAlignments);
            var verticvalAlignments = Enum.GetValues(typeof(LegendAlignmentVertical));
            cbeVerticalAlignment.Properties.Items.AddRange(verticvalAlignments);

            UpdateView();
        }

        public override void OnModelUpdated() {
            UpdateView();
        }

        protected void UpdateView() {
            updateStarted = true;
            cbeHorizontalAlignment.SelectedItem = LegendModel.AlignmentHorizontal;
            cbeVerticalAlignment.SelectedItem = LegendModel.AlignmentVertical;
            ceVisible.CheckState = DefaultBooleanToCheckState(LegendModel.Visibility);
            updateStarted = false;
        }

        protected void OnVerticalAlignmentChanged(object sender, EventArgs args) {
            if(!updateStarted)
                LegendModel.AlignmentVertical = (LegendAlignmentVertical)cbeVerticalAlignment.SelectedItem;
        }

        protected void OnHorizontalAlignmentChanged(object sender, EventArgs args) {
            if(!updateStarted)
                LegendModel.AlignmentHorizontal = (LegendAlignmentHorizontal)cbeHorizontalAlignment.SelectedItem;
        }

        protected void OnVisibilityChanged(object sender, EventArgs args) {
            if(!updateStarted)
                LegendModel.Visibility = CheckStateToDefaultBoolean(ceVisible.CheckState);
        }

        protected static CheckState DefaultBooleanToCheckState(DefaultBoolean b) {
            switch(b) {
                case DefaultBoolean.Default: return CheckState.Indeterminate;
                case DefaultBoolean.False: return CheckState.Unchecked;
                case DefaultBoolean.True: return CheckState.Checked;
                default: throw new Exception("The specified DefaultBoolean value is not supported.");
            }
        }

        protected static DefaultBoolean CheckStateToDefaultBoolean(CheckState b) {
            switch(b) {
                case CheckState.Indeterminate: return DefaultBoolean.Default;
                case CheckState.Unchecked: return DefaultBoolean.False;
                case CheckState.Checked: return DefaultBoolean.True;
                default: throw new Exception("The specified CheckState value is not supported.");
            }
        }

    }
}
#endregion #CustomOptionsControl
vb
#Region "#CustomOptionsControl"
Imports DevExpress.Utils
Imports DevExpress.XtraCharts
Imports DevExpress.XtraCharts.Designer
Imports System
Imports System.Windows.Forms

Namespace CrosshairOptions
    Partial Friend Class CustomLegendOptionsControl
        Inherits CustomOptionsControl

        Private updateStarted As Boolean = False

        Private ReadOnly Property LegendModel() As LegendModel
            Get
                Return CType(Me.Model, LegendModel)
            End Get
        End Property

        Public Sub New(ByVal model As ChartElementModel)
            MyBase.New(model)
            InitializeComponent()
            If Not(TypeOf model Is LegendModel) Then
                Throw New ArgumentException("The model must have the LegendModel type.")
            End If
        End Sub

        Protected Overrides Sub OnLoad(ByVal e As EventArgs)
            MyBase.OnLoad(e)

            Dim horizontalAlignments = System.Enum.GetValues(GetType(LegendAlignmentHorizontal))
            cbeHorizontalAlignment.Properties.Items.AddRange(horizontalAlignments)
            Dim verticvalAlignments = System.Enum.GetValues(GetType(LegendAlignmentVertical))
            cbeVerticalAlignment.Properties.Items.AddRange(verticvalAlignments)

            UpdateView()
        End Sub

        Public Overrides Sub OnModelUpdated()
            UpdateView()
        End Sub

        Protected Sub UpdateView()
            updateStarted = True
            cbeHorizontalAlignment.SelectedItem = LegendModel.AlignmentHorizontal
            cbeVerticalAlignment.SelectedItem = LegendModel.AlignmentVertical
            ceVisible.CheckState = DefaultBooleanToCheckState(LegendModel.Visibility)
            updateStarted = False
        End Sub

        Protected Sub OnVerticalAlignmentChanged(ByVal sender As Object, ByVal args As EventArgs)
            If Not updateStarted Then
                LegendModel.AlignmentVertical = CType(cbeVerticalAlignment.SelectedItem, LegendAlignmentVertical)
            End If
        End Sub

        Protected Sub OnHorizontalAlignmentChanged(ByVal sender As Object, ByVal args As EventArgs)
            If Not updateStarted Then
                LegendModel.AlignmentHorizontal = CType(cbeHorizontalAlignment.SelectedItem, LegendAlignmentHorizontal)
            End If
        End Sub

        Protected Sub OnVisibilityChanged(ByVal sender As Object, ByVal args As EventArgs)
            If Not updateStarted Then
                LegendModel.Visibility = CheckStateToDefaultBoolean(ceVisible.CheckState)
            End If
        End Sub

        Protected Shared Function DefaultBooleanToCheckState(ByVal b As DefaultBoolean) As CheckState
            Select Case b
                Case DefaultBoolean.Default
                    Return CheckState.Indeterminate
                Case DefaultBoolean.False
                    Return CheckState.Unchecked
                Case DefaultBoolean.True
                    Return CheckState.Checked
                Case Else
                    Throw New Exception("The specified DefaultBoolean value is not supported.")
            End Select
        End Function

        Protected Shared Function CheckStateToDefaultBoolean(ByVal b As CheckState) As DefaultBoolean
            Select Case b
                Case CheckState.Indeterminate
                    Return DefaultBoolean.Default
                Case CheckState.Unchecked
                    Return DefaultBoolean.False
                Case CheckState.Checked
                    Return DefaultBoolean.True
                Case Else
                    Throw New Exception("The specified CheckState value is not supported.")
            End Select
        End Function

    End Class
End Namespace
#End Region ' #CustomOptionsControl

Create a Model for a Custom Chart Element

Users configure chart element model properties when they modify chart element properties in the Chart Designer. Model changes apply to a corresponding chart element after the user clicks OK. Models are provided for existing chart elements. If you create a custom element (the colorizer in the example below), you should create and register a model for this element to allow users to edit its options in the Chart Designer.

Example

This example illustrates how to create and register a model (the CustomPointColorizerModel class in this example) for a custom colorizer (the CustomPointColorizer class in this example).

View Example: How to Create a Model for a Custom Chart Element

Step 1. Create a Model

For example, you have a custom colorizer CustomPointColorizer class that looks as follows:

csharp
[TypeConverter(typeof(ExpandableObjectConverter))]
public class CustomPointColorizer : ChartColorizerBase {
    double threshold = 60;
    Color lower = Color.Red;
    Color upper = Color.Green;

    public double Value {
        get { return threshold; }
        set { threshold = value; }
    }
    public Color LowerValuePointColor {
        get { return lower; }
        set { lower = value; }
    }
    public Color UpperValuePointColor {
        get { return upper; }
        set { upper = value; }
    }
    public override Color GetAggregatedPointColor(object argument, object[] values, SeriesPoint[] points, Palette palette) {
        if ((double)values[0] > Value)
            return UpperValuePointColor;
        else
            return LowerValuePointColor;
    }
    public override Color GetPointColor(object argument, object[] values, object colorKey, Palette palette) {
        return Color.Empty;
    }
    protected override ChartElement CreateObjectForClone() {
        return new CustomPointColorizer();
    }
    public override void Assign(ChartElement obj) {
        base.Assign(obj);
        CustomPointColorizer colorizer = obj as CustomPointColorizer;
        if (colorizer != null) {
            Value = colorizer.Value;
            LowerValuePointColor = colorizer.LowerValuePointColor;
            UpperValuePointColor = colorizer.UpperValuePointColor;
        }
    }
    public override string ToString() {
        return "(CustomPointColorizer)";
    }
}
vb
<TypeConverter(GetType(ExpandableObjectConverter))>
Public Class CustomPointColorizer
    Inherits ChartColorizerBase

    Private threshold As Double = 60
    Private lower As Color = Color.Red
    Private upper As Color = Color.Green

    Public Property Value As Double
        Get
            Return threshold
        End Get
        Set(ByVal value As Double)
            threshold = value
        End Set
    End Property

    Public Property LowerValuePointColor As Color
        Get
            Return lower
        End Get
        Set(ByVal value As Color)
            lower = value
        End Set
    End Property

    Public Property UpperValuePointColor As Color
        Get
            Return upper
        End Get
        Set(ByVal value As Color)
            upper = value
        End Set
    End Property

    Public Overrides Function GetAggregatedPointColor(ByVal argument As Object, ByVal values As Object(), ByVal points As SeriesPoint(), ByVal palette As Palette) As Color
        If CDbl(values(0)) > Value Then
            Return UpperValuePointColor
        Else
            Return LowerValuePointColor
        End If
    End Function

    Public Overrides Function GetPointColor(ByVal argument As Object, ByVal values As Object(), ByVal colorKey As Object, ByVal palette As Palette) As Color
        Return Color.Empty
    End Function

    Protected Overrides Function CreateObjectForClone() As ChartElement
        Return New CustomPointColorizer
    End Function

    Public Overrides Sub Assign(ByVal obj As ChartElement)
        MyBase.Assign(obj)
        Dim colorizer = TryCast(obj, CustomPointColorizer)

        If colorizer IsNot Nothing Then
            Value = colorizer.Value
            LowerValuePointColor = colorizer.LowerValuePointColor
            UpperValuePointColor = colorizer.UpperValuePointColor
        End If
    End Sub

    Public Overrides Function ToString() As String
        Return "(CustomPointColorizer)"
    End Function
End Class

Next, create a CustomPointColorizerModel model for your colorizer. This model is used to modify the colorizer options in the Chart Designer’s Properties tab.

csharp
public class CustomPointColorizerModel : ChartColorizerBaseModel {
    CustomPointColorizer MyColorizer { get { return (CustomPointColorizer)Colorizer; } } 

    public double Value {
        get { return MyColorizer.Value; }
        set { SetProperty("Value", value); }
    }
    public Color LowerValuePointColor {
        get { return MyColorizer.LowerValuePointColor; }
        set { SetProperty("LowerValuePointColor", value); }
    }
    public Color UpperValuePointColor {
        get { return MyColorizer.UpperValuePointColor; }
        set { SetProperty("UpperValuePointColor", value); }
    }
    public CustomPointColorizerModel(ChartColorizerBase element, CustomModelProvider customModelProvider) : base(element, customModelProvider) {
    }
}
vb
Public Class CustomPointColorizerModel
    Inherits ChartColorizerBaseModel

    Private ReadOnly Property MyColorizer As CustomPointColorizer
        Get
            Return CType(Colorizer, CustomPointColorizer)
        End Get
    End Property

    Public Property Value As Double
        Get
            Return MyColorizer.Value
        End Get
        Set(ByVal value As Double)
            SetProperty("Value", value)
        End Set
    End Property

    Public Property LowerValuePointColor As Color
        Get
            Return MyColorizer.LowerValuePointColor
        End Get
        Set(ByVal value As Color)
            SetProperty("LowerValuePointColor", value)
        End Set
    End Property

    Public Property UpperValuePointColor As Color
        Get
            Return MyColorizer.UpperValuePointColor
        End Get
        Set(ByVal value As Color)
            SetProperty("UpperValuePointColor", value)
        End Set
    End Property

    Public Sub New(ByVal element As ChartColorizerBase, ByVal customModelProvider As CustomModelProvider)
        MyBase.New(element, customModelProvider)
    End Sub
End Class

Step 2. Customize the Property Editor

Use the Editor attribute to configure an editor for a Chart Designer property. In this example, you add the CustomPointColorizer item to the list of colorizers for the bar series model’s Colorizer property.

csharp
public class SideBySideBarSeriesViewCustomModel : SideBySideBarSeriesViewModel {
    [Editor(typeof(CustomColorizerEditor), typeof(UITypeEditor))]
    public new ChartColorizerBaseModel Colorizer {
        get { return base.Colorizer; }
        set { base.Colorizer = value; }
    }

    public SideBySideBarSeriesViewCustomModel(SideBySideBarSeriesView element, CustomModelProvider customModelProvider)
        : base(element, customModelProvider) {
    }
}

public class CustomColorizerEditor : UITypeEditor {
    IWindowsFormsEditorService editorService;
    public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value) {
        editorService = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
        var seriesView = context.Instance as SeriesViewBaseModel;

        List<ChartColorizerBase> colorizers = GetColorizers();

        CustomModelProvider modelProvider = new CustomModelProvider();
        modelProvider.RegisterCustomModelType(typeof(CustomPointColorizer), typeof(CustomPointColorizerModel));

        var listBox = new ListBoxControl();
        listBox.Click += listBox_Click;
        listBox.Items.Add("(None)");
        foreach (ChartColorizerBase colorizer in colorizers) {
            var colorizerModel = ModelHelper.GetModel<ChartColorizerBaseModel>(colorizer, modelProvider);
            int index = listBox.Items.Add(colorizerModel);
            if (value != null && colorizerModel.GetType() == value.GetType()) {
                listBox.SelectedIndex = index;
            }
        }
        editorService.DropDownControl(listBox);
        if (listBox.SelectedIndex != 0)
            if (value == null || listBox.SelectedItem.GetType() != value.GetType())
                return listBox.SelectedItem;
            else
                return value;
        else
            return null;
    }
    void listBox_Click(object sender, EventArgs e) {
        this.editorService.CloseDropDown();
    }
    List<ChartColorizerBase> GetColorizers() {
        return new List<ChartColorizerBase>() { new CustomPointColorizer(), new KeyColorColorizer(), new RangeColorizer() };
    }
    public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) {
        return UITypeEditorEditStyle.DropDown;
    }
}
vb
Public Class SideBySideBarSeriesViewCustomModel
    Inherits SideBySideBarSeriesViewModel

    <Editor(GetType(CustomColorizerEditor), GetType(UITypeEditor))>
    Public Overloads Property Colorizer As ChartColorizerBaseModel
        Get
            Return MyBase.Colorizer
        End Get
        Set(ByVal value As ChartColorizerBaseModel)
            MyBase.Colorizer = value
        End Set
    End Property

    Public Sub New(ByVal element As SideBySideBarSeriesView, ByVal customModelProvider As CustomModelProvider)
        MyBase.New(element, customModelProvider)
    End Sub
End Class

Public Class CustomColorizerEditor
    Inherits UITypeEditor

    Private editorService As IWindowsFormsEditorService

    Public Overrides Function EditValue(ByVal context As ITypeDescriptorContext, ByVal provider As IServiceProvider, ByVal value As Object) As Object
        editorService = CType(provider.GetService(GetType(IWindowsFormsEditorService)), IWindowsFormsEditorService)
        Dim seriesView = TryCast(context.Instance, SeriesViewBaseModel)
        Dim colorizers = GetColorizers
        Dim modelProvider As CustomModelProvider = New CustomModelProvider
        modelProvider.RegisterCustomModelType(GetType(CustomPointColorizer), GetType(CustomPointColorizerModel))
        Dim listBox = New ListBoxControl
        listBox.Click += AddressOf listBox_Click
        listBox.Items.Add("(None)")

        For Each colorizer As ChartColorizerBase In colorizers
            Dim colorizerModel = ModelHelper.GetModel(Of ChartColorizerBaseModel)(colorizer, modelProvider)
            Dim index As Integer = listBox.Items.Add(colorizerModel)

            If value IsNot Nothing AndAlso colorizerModel.GetType Is value.GetType Then
                listBox.SelectedIndex = index
            End If
        Next

        editorService.DropDownControl(listBox)

        If listBox.SelectedIndex IsNot 0 Then

            If value Is Nothing OrElse listBox.SelectedItem.GetType IsNot value.GetType Then
                Return listBox.SelectedItem
            Else
                Return value
            End If
        Else
            Return Nothing
        End If
    End Function

    Private Sub listBox_Click(ByVal sender As Object, ByVal e As EventArgs)
        editorService.CloseDropDown
    End Sub

    Private Function GetColorizers() As List(Of ChartColorizerBase)
        Return New List(Of ChartColorizerBase) From {
            New CustomPointColorizer,
            New KeyColorColorizer,
            New RangeColorizer
        }
    End Function

    Public Overrides Function GetEditStyle(ByVal context As ITypeDescriptorContext) As UITypeEditorEditStyle
        Return UITypeEditorEditStyle.DropDown
    End Function
End Class

Step 3. Register Models

To associate the model with the chart element, use the ChartDesigner.RegisterCustomModelType(System.Type,System.Type) method.

csharp
void OnButtonClick(object sender, EventArgs e) {
    ChartDesigner chartDesigner = new ChartDesigner((ChartControl)this.Controls["MyChart"]);
    chartDesigner.RegisterCustomModelType(typeof(CustomPointColorizer), typeof(CustomPointColorizerModel));
    chartDesigner.RegisterCustomModelType(typeof(SideBySideBarSeriesView), typeof(SideBySideBarSeriesViewCustomModel));
    chartDesigner.ShowDialog(true);
}
vb
Private Sub OnButtonClick(ByVal sender As Object, ByVal e As EventArgs)
    Dim chartDesigner As ChartDesigner = New ChartDesigner(CType(Me.Controls("MyChart"), ChartControl))
    chartDesigner.RegisterCustomModelType(GetType(CustomPointColorizer), GetType(CustomPointColorizerModel))
    chartDesigner.RegisterCustomModelType(GetType(SideBySideBarSeriesView), GetType(SideBySideBarSeriesViewCustomModel))
    chartDesigner.ShowDialog(True)
End Sub

Localize the Chart Designer

Use one of the following approaches to localize text used in the Chart Designer:

  1. Use Satellite Resource Assemblies (standard localization mechanism).

  2. Use Localizer Objects.