dashboard-401621-winforms-dashboard-winforms-designer-ui-elements-and-customization-create-custom-properties-chart-item-constant-line.md
This topic describes how to create a custom property for a dashboard item. In this example, the property provides editors that allow you to draw a constant line for the selected Chart item in the WinForms Dashboard Designer. The ChartContext.GetDashboardItemSeries method is used to provide a connection between data item containers from the Values section and the series from an underlying Chart control.
View Example: WinForms Dashboard - Custom Properties
The code is organized into a separate module you can integrate into any dashboard application.
Create the ConstantLineUserValueModule class that serves as a custom functionality module and contains:
Note
You can use the IDashboardControl interface that provides common API for WinForms Designer and Viewer to write code that can be used in both controls simultaneously.
You can add control elements to the Ribbon / Toolbar to change the custom property’s value in the UI.
In this example, the AddBarItem method places the Constant Line button in the Custom Properties ribbon group on the Chart’s Design page.
public class ConstantLineUserValueModule {
public static readonly string PropertyName = "ConstantLine";
readonly DashboardDesigner designer;
public ConstantLineUserValueModule(DashboardDesigner designer, SvgImage barImage = null) {
this.designer = designer;
BarButtonItem barItem = AddBarItem("Constant Line", barImage, designer.Ribbon);
barItem.ItemClick += BarItem_Click;
designer.DashboardItemControlUpdated += Designer_DashboardItemControlUpdated;
}
BarButtonItem AddBarItem(string caption, SvgImage barImage, RibbonControl ribbon) {
var page = ribbon.GetDashboardRibbonPage(DashboardBarItemCategory.ChartTools, DashboardRibbonPage.Design);
RibbonPageGroup group = page.GetGroupByName("Custom Properties");
if(group == null) {
group = new RibbonPageGroup("Custom Properties") { Name = "Custom Properties" };
page.Groups.Add(group);
}
var barItem = new BarButtonItem(ribbon.Manager, caption);
barItem.ImageOptions.SvgImage = barImage;
group.ItemLinks.Add(barItem);
return barItem;
}
Public Class ConstantLineUserValueModule
Public Shared ReadOnly PropertyName As String = "ConstantLine"
Private ReadOnly designer As DashboardDesigner
Public Sub New(ByVal designer As DashboardDesigner, Optional ByVal barImage As SvgImage = Nothing)
Me.designer = designer
Dim barItem As BarButtonItem = AddBarItem("Constant line", barImage, designer.Ribbon)
AddHandler barItem.ItemClick, AddressOf BarItem_Click
AddHandler designer.DashboardItemControlUpdated, AddressOf Designer_DashboardItemControlUpdated
End Sub
Private Function AddBarItem(ByVal caption As String, ByVal barImage As SvgImage, ByVal ribbon As RibbonControl) As BarButtonItem
Dim page = ribbon.GetDashboardRibbonPage(DashboardBarItemCategory.ChartTools, DashboardRibbonPage.Design)
Dim group As RibbonPageGroup = page.GetGroupByName("Custom Properties")
If group Is Nothing Then
group = New RibbonPageGroup("Custom Properties") With {.Name = "Custom Properties"}
page.Groups.Add(group)
End If
Dim barItem = New BarButtonItem(ribbon.Manager, caption)
barItem.ImageOptions.SvgImage = barImage
group.ItemLinks.Add(barItem)
Return barItem
End Function
Create the ConstantLineUserValueModuleData class that parses the selected chart item’s data.
The GetDataFromString method returns the ConstantLineUserValueModuleData class instance that contains parsed values.
The GetStringFromData method returns an instance’s values as a string: {Pane 1_False_100000}.
“Pane 1” is the PaneName string value.
“False” is the IsSecondaryAxis Boolean value that defines whether to create a constant line on the secondary Y axis.
“100000” is the Value numeric value that is the position of the constant line on the Y (or secondary Y) axis.
public class ConstantLineUserValueModuleData {
public string PaneName { get; set; }
public bool IsSecondaryAxis { get; set; }
public double Value { get; set; }
public string GetStringFromData() {
return PaneName + "_" + IsSecondaryAxis.ToString() + "_" + Value;
}
}
ConstantLineUserValueModuleData GetDataFromString(string customPropertyValue) {
if(!string.IsNullOrEmpty(customPropertyValue)) {
var array = customPropertyValue.Split('_');
return new ConstantLineUserValueModuleData() {
PaneName = array[0],
IsSecondaryAxis = bool.Parse(array[1]),
Value = Convert.ToDouble(array[2])
};
}
return new ConstantLineUserValueModuleData();
}
Public Class ConstantLineUserValueModuleData
Public Property PaneName() As String
Public Property IsSecondaryAxis() As Boolean
Public Property Value() As Double
Public Function GetStringFromData() As String
Return PaneName & "_" & IsSecondaryAxis.ToString() & "_" & Value
End Function
Private Function GetDataFromString(ByVal customPropertyValue As String) As ConstantLineUserValueModuleData
If Not String.IsNullOrEmpty(customPropertyValue) Then
Dim array = customPropertyValue.Split("_"c)
Return New ConstantLineUserValueModuleData() With {
.PaneName = array(0),
.IsSecondaryAxis = Boolean.Parse(array(1)),
.Value = Convert.ToDouble(array(2))
}
End If
Return New ConstantLineUserValueModuleData()
End Function
End Class
Create a new form that allows users to edit the constant line’s options.
Inherit the XtraUserControl. In this example, it is the ValueSelectorControl class. Add the DataLayoutControl. Next, add editors to the control that allows you to edit options.
public class ValueSelectorControl : XtraUserControl {
public ConstantLineUserValueModuleData ConstantLineModuleData { get; }
public ValueSelectorControl(List<string> paneNames) {
DataLayoutControl dataLayoutControl = new DataLayoutControl();
BindingSource source = new BindingSource();
ConstantLineModuleData = new ConstantLineUserValueModuleData();
source.DataSource = ConstantLineModuleData;
dataLayoutControl.DataSource = source;
dataLayoutControl.FieldRetrieving += (s, e) => {
if(e.FieldName == nameof(ConstantLineModuleData.PaneName)) {
e.EditorType = typeof(LookUpEdit);
e.Handled = true;
}
};
dataLayoutControl.FieldRetrieved += (s, e) => {
if(e.FieldName == nameof(ConstantLineModuleData.PaneName))
InitRepositoryItem(e.RepositoryItem, paneNames);
};
dataLayoutControl.RetrieveFields();
dataLayoutControl.Dock = DockStyle.Fill;
Controls.Add(dataLayoutControl);
Dock = DockStyle.Top;
}
void InitRepositoryItem<T>(RepositoryItem ri, List<T> list) {
var lookUpEdit = ri as RepositoryItemLookUpEdit;
lookUpEdit.TextEditStyle = TextEditStyles.DisableTextEditor;
lookUpEdit.AllowNullInput = DefaultBoolean.False;
lookUpEdit.DataSource = list;
}
}
}
Public Class ValueSelectorControl
Inherits XtraUserControl
Public ReadOnly Property ConstantLineModuleData() As ConstantLineUserValueModuleData
Public Sub New(ByVal paneNames As List(Of String))
Dim dataLayoutControl As New DataLayoutControl()
Dim source As New BindingSource()
ConstantLineModuleData = New ConstantLineUserValueModuleData()
source.DataSource = ConstantLineModuleData
dataLayoutControl.DataSource = source
AddHandler dataLayoutControl.FieldRetrieving, Sub(s, e)
If e.FieldName = NameOf(ConstantLineModuleData.PaneName) Then
e.EditorType = GetType(LookUpEdit)
e.Handled = True
End If
End Sub
AddHandler dataLayoutControl.FieldRetrieved, Sub(s, e)
If e.FieldName = NameOf(ConstantLineModuleData.PaneName) Then
InitRepositoryItem(e.RepositoryItem, paneNames)
End If
End Sub
dataLayoutControl.RetrieveFields()
dataLayoutControl.Dock = DockStyle.Fill
Controls.Add(dataLayoutControl)
Dock = DockStyle.Top
End Sub
Private Sub InitRepositoryItem(Of T)(ByVal ri As RepositoryItem, ByVal list As List(Of T))
Dim lookUpEdit = TryCast(ri, RepositoryItemLookUpEdit)
lookUpEdit.TextEditStyle = TextEditStyles.DisableTextEditor
lookUpEdit.AllowNullInput = DefaultBoolean.False
lookUpEdit.DataSource = list
End Sub
End Class
Use the GetConstantLineModuleData method to get the specified options.
ConstantLineUserValueModuleData GetConstantLineModuleData(ChartDashboardItem dashboardItem) {
using(ValueSelectorControl selector = new ValueSelectorControl(dashboardItem.Panes.Select(p => p.Name).ToList())) {
if(XtraDialog.Show(selector, "Select the required series:") == DialogResult.OK) {
return selector.ConstantLineModuleData;
}
}
return null;
}
Private Function GetConstantLineModuleData(ByVal dashboardItem As ChartDashboardItem) As ConstantLineUserValueModuleData
Using selector As New ValueSelectorControl(dashboardItem.Panes.Select(Function(p) p.Name).ToList())
If XtraDialog.Show(selector, "Select the required series:") = DialogResult.OK Then
Return selector.ConstantLineModuleData
End If
End Using
Return Nothing
End Function
The following image shows the ValueSelectorControl :
In this example, the custom property’s value is stored in the DashboardItem.CustomProperties collection.
Use the DashboardDesigner.AddToHistory method to record a new custom property’s value and save the action to the Dashboard Designer’s history when a user changes the value. This method calls the CustomProperties.SetValue method and adds the information to the history item. You can undo/redo this action like other user actions.
void BarItem_Click(object sender, ItemClickEventArgs e) {
var chartItem = designer.SelectedDashboardItem as ChartDashboardItem;
if(chartItem != null) {
var data = GetConstantLineModuleData(chartItem);
if(data != null)
designer.AddToHistory(new CustomPropertyHistoryItem(chartItem, PropertyName, data.GetStringFromData(), $"{data.PaneName} constant line is set"));
}
}
Private Sub BarItem_Click(ByVal sender As Object, ByVal e As ItemClickEventArgs)
Dim chartItem = TryCast(designer.SelectedDashboardItem, ChartDashboardItem)
If chartItem IsNot Nothing Then
Dim data = GetConstantLineModuleData(chartItem)
If data IsNot Nothing Then
designer.AddToHistory(New CustomPropertyHistoryItem(chartItem, PropertyName, data.GetStringFromData(), $"{data.PaneName} constant line is set"))
End If
End If
End Sub
Create the UpdateChart method to draw a constant line. Create a new ConstantLine class instance and assign AxisValue as the constant line value to define the constant line’s position.
Handle the DashboardDesigner.DashboardItemControlUpdated event to update the underlying Chart. Use the CustomProperties.GetValue method to get the custom property’s value and update the control’s options according to this value.
void UpdateChart(ChartDashboardItem chartDashboardItem, ChartContext chartContext) {
var moduleData = GetDataFromString(chartDashboardItem.CustomProperties.GetValue(PropertyName));
var pane = chartDashboardItem.Panes.FirstOrDefault(x => x.Name == moduleData.PaneName);
if(pane != null) {
ChartSeries dashboardSeries = pane.Series.FirstOrDefault(s => s.PlotOnSecondaryAxis == moduleData.IsSecondaryAxis);
if(dashboardSeries != null) {
Series chartSeries = chartContext.GetControlSeries(dashboardSeries).FirstOrDefault();
var chartAxis = (chartSeries.View as XYDiagramSeriesViewBase)?.AxisY;
if(chartAxis != null) {
ConstantLine line = new ConstantLine() { AxisValue = moduleData.Value };
chartAxis.ConstantLines.Clear();
chartAxis.ConstantLines.Add(line);
line.ShowInLegend = false;
line.Color = Color.Green;
line.LineStyle.Thickness = 2;
line.LineStyle.DashStyle = DashStyle.Dash;
line.Title.Text = "Value: " + moduleData.Value.ToString();
line.Title.TextColor = line.Color;
}
}
}
}
void Designer_DashboardItemControlUpdated(object sender, DashboardItemControlEventArgs e) {
if(e.ChartControl != null && designer.Dashboard.Items[e.DashboardItemName] is ChartDashboardItem chartDashboardItem)
UpdateChart(chartDashboardItem, e.ChartContext);
}
Private Sub UpdateChart(ByVal chartDashboardItem As ChartDashboardItem, ByVal chartContext As ChartContext)
Dim moduleData = GetDataFromString(chartDashboardItem.CustomProperties.GetValue(PropertyName))
Dim pane = chartDashboardItem.Panes.FirstOrDefault(Function(x) x.Name = moduleData.PaneName)
If pane IsNot Nothing Then
Dim dashboardSeries As ChartSeries = pane.Series.FirstOrDefault(Function(s) s.PlotOnSecondaryAxis = moduleData.IsSecondaryAxis)
If dashboardSeries IsNot Nothing Then
Dim chartSeries As Series = chartContext.GetControlSeries(dashboardSeries).FirstOrDefault()
Dim chartAxis = (TryCast(chartSeries.View, XYDiagramSeriesViewBase))?.AxisY
If chartAxis IsNot Nothing Then
Dim line As New ConstantLine() With {.AxisValue = moduleData.Value}
chartAxis.ConstantLines.Clear()
chartAxis.ConstantLines.Add(line)
line.ShowInLegend = False
line.Color = Color.Green
line.LineStyle.Thickness = 2
line.LineStyle.DashStyle = DashStyle.Dash
line.Title.Text = "Value: " & moduleData.Value.ToString()
line.Title.TextColor = line.Color
End If
End If
End If
End Sub
Private Sub Designer_DashboardItemControlUpdated(ByVal sender As Object, ByVal e As DashboardItemControlEventArgs)
Dim tempVar As Boolean = TypeOf designer.Dashboard.Items(e.DashboardItemName) Is ChartDashboardItem
Dim chartDashboardItem As ChartDashboardItem = If(tempVar, CType(designer.Dashboard.Items(e.DashboardItemName), ChartDashboardItem), Nothing)
If e.ChartControl IsNot Nothing AndAlso tempVar Then
UpdateChart(chartDashboardItem, e.ChartContext)
End If
End Sub
The code below is a complete module you need to add the Chart item’s Constant Line option:
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using DevExpress.DashboardCommon;
using DevExpress.DashboardWin;
using DevExpress.Utils;
using DevExpress.Utils.Svg;
using DevExpress.XtraBars;
using DevExpress.XtraBars.Ribbon;
using DevExpress.XtraCharts;
using DevExpress.XtraDataLayout;
using DevExpress.XtraEditors;
using DevExpress.XtraEditors.Controls;
using DevExpress.XtraEditors.Repository;
namespace WindowsFormsAppCustomProperties {
public class ConstantLineUserValueModuleData {
public string PaneName { get; set; }
public bool IsSecondaryAxis { get; set; }
public double Value { get; set; }
public string GetStringFromData() {
return PaneName + "_" + IsSecondaryAxis.ToString() + "_" + Value;
}
}
public class ConstantLineUserValueModule {
public static readonly string PropertyName = "ConstantLine";
readonly DashboardDesigner designer;
public ConstantLineUserValueModule(DashboardDesigner designer, SvgImage barImage = null) {
this.designer = designer;
BarButtonItem barItem = AddBarItem("Constant line", barImage, designer.Ribbon);
barItem.ItemClick += BarItem_Click;
designer.DashboardItemControlUpdated += Designer_DashboardItemControlUpdated;
}
BarButtonItem AddBarItem(string caption, SvgImage barImage, RibbonControl ribbon) {
var page = ribbon.GetDashboardRibbonPage(DashboardBarItemCategory.ChartTools, DashboardRibbonPage.Design);
RibbonPageGroup group = page.GetGroupByName("Custom Properties");
if(group == null) {
group = new RibbonPageGroup("Custom Properties") { Name = "Custom Properties" };
page.Groups.Add(group);
}
var barItem = new BarButtonItem(ribbon.Manager, caption);
barItem.ImageOptions.SvgImage = barImage;
group.ItemLinks.Add(barItem);
return barItem;
}
void BarItem_Click(object sender, ItemClickEventArgs e) {
var chartItem = designer.SelectedDashboardItem as ChartDashboardItem;
if(chartItem != null) {
var data = GetConstantLineModuleData(chartItem);
if(data != null)
designer.AddToHistory(new CustomPropertyHistoryItem(chartItem, PropertyName, data.GetStringFromData(), $"{data.PaneName} constant line is set"));
}
}
ConstantLineUserValueModuleData GetConstantLineModuleData(ChartDashboardItem dashboardItem) {
using(ValueSelectorControl selector = new ValueSelectorControl(dashboardItem.Panes.Select(p => p.Name).ToList())) {
if(XtraDialog.Show(selector, "Select the required series") == DialogResult.OK) {
return selector.ConstantLineModuleData;
}
}
return null;
}
void Designer_DashboardItemControlUpdated(object sender, DashboardItemControlEventArgs e) {
if(e.ChartControl != null && designer.Dashboard.Items[e.DashboardItemName] is ChartDashboardItem chartDashboardItem)
UpdateChart(chartDashboardItem, e.ChartContext);
}
void UpdateChart(ChartDashboardItem chartDashboardItem, ChartContext chartContext) {
var moduleData = GetDataFromString(chartDashboardItem.CustomProperties.GetValue(PropertyName));
var pane = chartDashboardItem.Panes.FirstOrDefault(x => x.Name == moduleData.PaneName);
if(pane != null) {
ChartSeries dashboardSeries = pane.Series.FirstOrDefault(s => s.PlotOnSecondaryAxis == moduleData.IsSecondaryAxis);
if(dashboardSeries != null) {
Series chartSeries = chartContext.GetControlSeries(dashboardSeries).FirstOrDefault();
var chartAxis = (chartSeries.View as XYDiagramSeriesViewBase)?.AxisY;
if(chartAxis != null) {
ConstantLine line = new ConstantLine() { AxisValue = moduleData.Value };
chartAxis.ConstantLines.Clear();
chartAxis.ConstantLines.Add(line);
line.ShowInLegend = false;
line.Color = Color.Green;
line.LineStyle.Thickness = 2;
line.LineStyle.DashStyle = DashStyle.Dash;
line.Title.Text = "Value: " + moduleData.Value.ToString();
line.Title.TextColor = line.Color;
}
}
}
}
ConstantLineUserValueModuleData GetDataFromString(string customPropertyValue) {
if(!string.IsNullOrEmpty(customPropertyValue)) {
var array = customPropertyValue.Split('_');
return new ConstantLineUserValueModuleData() {
PaneName = array[0],
IsSecondaryAxis = bool.Parse(array[1]),
Value = Convert.ToDouble(array[2])
};
}
return new ConstantLineUserValueModuleData();
}
}
public class ValueSelectorControl: XtraUserControl {
public ConstantLineUserValueModuleData ConstantLineModuleData { get; }
public ValueSelectorControl(List<string> paneNames) {
DataLayoutControl dataLayoutControl = new DataLayoutControl();
BindingSource source = new BindingSource();
ConstantLineModuleData = new ConstantLineUserValueModuleData();
source.DataSource = ConstantLineModuleData;
dataLayoutControl.DataSource = source;
dataLayoutControl.FieldRetrieving += (s, e) => {
if(e.FieldName == nameof(ConstantLineModuleData.PaneName)) {
e.EditorType = typeof(LookUpEdit);
e.Handled = true;
}
};
dataLayoutControl.FieldRetrieved += (s, e) => {
if(e.FieldName == nameof(ConstantLineModuleData.PaneName))
InitRepositoryItem(e.RepositoryItem, paneNames);
};
dataLayoutControl.RetrieveFields();
dataLayoutControl.Dock = DockStyle.Fill;
Controls.Add(dataLayoutControl);
Dock = DockStyle.Top;
}
void InitRepositoryItem<T>(RepositoryItem ri, List<T> list) {
var lookUpEdit = ri as RepositoryItemLookUpEdit;
lookUpEdit.TextEditStyle = TextEditStyles.DisableTextEditor;
lookUpEdit.AllowNullInput = DefaultBoolean.False;
lookUpEdit.DataSource = list;
}
}
}
Imports System
Imports System.Collections.Generic
Imports System.Drawing
Imports System.Linq
Imports System.Windows.Forms
Imports DevExpress.DashboardCommon
Imports DevExpress.DashboardWin
Imports DevExpress.Utils
Imports DevExpress.Utils.Svg
Imports DevExpress.XtraBars
Imports DevExpress.XtraBars.Ribbon
Imports DevExpress.XtraCharts
Imports DevExpress.XtraDataLayout
Imports DevExpress.XtraEditors
Imports DevExpress.XtraEditors.Controls
Imports DevExpress.XtraEditors.Repository
Namespace WindowsFormsAppCustomProperties
Public Class ConstantLineUserValueModuleData
Public Property PaneName() As String
Public Property IsSecondaryAxis() As Boolean
Public Property Value() As Double
Public Function GetStringFromData() As String
Return PaneName & "_" & IsSecondaryAxis.ToString() & "_" & Value
End Function
End Class
Public Class ConstantLineUserValueModule
Public Shared ReadOnly PropertyName As String = "ConstantLine"
Private ReadOnly designer As DashboardDesigner
Public Sub New(ByVal designer As DashboardDesigner, Optional ByVal barImage As SvgImage = Nothing)
Me.designer = designer
Dim barItem As BarButtonItem = AddBarItem("Constant line", barImage, designer.Ribbon)
AddHandler barItem.ItemClick, AddressOf BarItem_Click
AddHandler designer.DashboardItemControlUpdated, AddressOf Designer_DashboardItemControlUpdated
End Sub
Private Function AddBarItem(ByVal caption As String, ByVal barImage As SvgImage, ByVal ribbon As RibbonControl) As BarButtonItem
Dim page = ribbon.GetDashboardRibbonPage(DashboardBarItemCategory.ChartTools, DashboardRibbonPage.Design)
Dim group As RibbonPageGroup = page.GetGroupByName("Custom Properties")
If group Is Nothing Then
group = New RibbonPageGroup("Custom Properties") With {.Name = "Custom Properties"}
page.Groups.Add(group)
End If
Dim barItem = New BarButtonItem(ribbon.Manager, caption)
barItem.ImageOptions.SvgImage = barImage
group.ItemLinks.Add(barItem)
Return barItem
End Function
Private Sub BarItem_Click(ByVal sender As Object, ByVal e As ItemClickEventArgs)
Dim chartItem = TryCast(designer.SelectedDashboardItem, ChartDashboardItem)
If chartItem IsNot Nothing Then
Dim data = GetConstantLineModuleData(chartItem)
If data IsNot Nothing Then
designer.AddToHistory(New CustomPropertyHistoryItem(chartItem, PropertyName, data.GetStringFromData(), $"{data.PaneName} constant line is set"))
End If
End If
End Sub
Private Function GetConstantLineModuleData(ByVal dashboardItem As ChartDashboardItem) As ConstantLineUserValueModuleData
Using selector As New ValueSelectorControl(dashboardItem.Panes.Select(Function(p) p.Name).ToList())
If XtraDialog.Show(selector, "Select the required series") = DialogResult.OK Then
Return selector.ConstantLineModuleData
End If
End Using
Return Nothing
End Function
Private Sub Designer_DashboardItemControlUpdated(ByVal sender As Object, ByVal e As DashboardItemControlEventArgs)
Dim tempVar As Boolean = TypeOf designer.Dashboard.Items(e.DashboardItemName) Is ChartDashboardItem
Dim chartDashboardItem As ChartDashboardItem = If(tempVar, CType(designer.Dashboard.Items(e.DashboardItemName), ChartDashboardItem), Nothing)
If e.ChartControl IsNot Nothing AndAlso tempVar Then
UpdateChart(chartDashboardItem, e.ChartContext)
End If
End Sub
Private Sub UpdateChart(ByVal chartDashboardItem As ChartDashboardItem, ByVal chartContext As ChartContext)
Dim moduleData = GetDataFromString(chartDashboardItem.CustomProperties.GetValue(PropertyName))
Dim pane = chartDashboardItem.Panes.FirstOrDefault(Function(x) x.Name = moduleData.PaneName)
If pane IsNot Nothing Then
Dim dashboardSeries As ChartSeries = pane.Series.FirstOrDefault(Function(s) s.PlotOnSecondaryAxis = moduleData.IsSecondaryAxis)
If dashboardSeries IsNot Nothing Then
Dim chartSeries As Series = chartContext.GetControlSeries(dashboardSeries).FirstOrDefault()
Dim chartAxis = TryCast(chartSeries.View, XYDiagramSeriesViewBase)?.AxisY
If chartAxis IsNot Nothing Then
Dim line As New ConstantLine() With {.AxisValue = moduleData.Value}
chartAxis.ConstantLines.Clear()
chartAxis.ConstantLines.Add(line)
line.ShowInLegend = False
line.Color = Color.Green
line.LineStyle.Thickness = 2
line.LineStyle.DashStyle = DashStyle.Dash
line.Title.Text = "Value: " & moduleData.Value.ToString()
line.Title.TextColor = line.Color
End If
End If
End If
End Sub
Private Function GetDataFromString(ByVal customPropertyValue As String) As ConstantLineUserValueModuleData
If Not String.IsNullOrEmpty(customPropertyValue) Then
Dim array = customPropertyValue.Split("_"c)
Return New ConstantLineUserValueModuleData() With {
.PaneName = array(0),
.IsSecondaryAxis = Boolean.Parse(array(1)),
.Value = Convert.ToDouble(array(2))
}
End If
Return New ConstantLineUserValueModuleData()
End Function
End Class
Public Class ValueSelectorControl
Inherits XtraUserControl
Public ReadOnly Property ConstantLineModuleData() As ConstantLineUserValueModuleData
Public Sub New(ByVal paneNames As List(Of String))
Dim dataLayoutControl As New DataLayoutControl()
Dim source As New BindingSource()
ConstantLineModuleData = New ConstantLineUserValueModuleData()
source.DataSource = ConstantLineModuleData
dataLayoutControl.DataSource = source
AddHandler dataLayoutControl.FieldRetrieving, Sub(s, e)
If e.FieldName = NameOf(ConstantLineModuleData.PaneName) Then
e.EditorType = GetType(LookUpEdit)
e.Handled = True
End If
End Sub
AddHandler dataLayoutControl.FieldRetrieved, Sub(s, e)
If e.FieldName = NameOf(ConstantLineModuleData.PaneName) Then
InitRepositoryItem(e.RepositoryItem, paneNames)
End If
End Sub
dataLayoutControl.RetrieveFields()
dataLayoutControl.Dock = DockStyle.Fill
Controls.Add(dataLayoutControl)
Dock = DockStyle.Top
End Sub
Private Sub InitRepositoryItem(Of T)(ByVal ri As RepositoryItem, ByVal list As List(Of T))
Dim lookUpEdit = TryCast(ri, RepositoryItemLookUpEdit)
lookUpEdit.TextEditStyle = TextEditStyles.DisableTextEditor
lookUpEdit.AllowNullInput = DefaultBoolean.False
lookUpEdit.DataSource = list
End Sub
End Class
End Namespace
Register it before you load a dashboard to apply settings to this dashboard. For this, create a new ConstantLineUserValueModule instance and pass the Dashboard Designer for which you register a custom property. You can create the SvgImageCollection instance to store vector images and use one of them as the bar item’s icon.
using WindowsFormsAppCustomProperties;
//...
public Form1() {
InitializeComponent();
new ConstantLineUserValueModule(dashboardDesigner1, svgImageCollection1["chartrangearea"]);
dashboardDesigner1.LoadDashboard("../../Dashboard/newDashboard.xml");
//...
}
Imports WindowsFormsAppCustomProperties
'...
Public Sub New()
InitializeComponent()
Dim TempConstantLineUserValueModule As ConstantLineUserValueModule = New ConstantLineUserValueModule(dashboardDesigner1, svgImageCollection1("chartrangearea"))
dashboardDesigner1.LoadDashboard("../../Dashboard/newDashboard.xml")
'...
End Sub
After you register the ChartScaleBreakModule module, the ConstantLine button is added that draws the constant line for the selected Chart item in a dashboard. Clicking the button invokes the ValueSelectorControl editor that allows users to specify the pane, axis, and constant line’s position.
You can undo/redo actions, because information about the scale break property’s state is saved in the history.
Tip
You can also download the multiplatform example on GitHub: Constant Lines
See Also