dashboard-401622-winforms-dashboard-winforms-designer-ui-elements-and-customization-create-custom-properties-grid-item-fixed-pinned-columns.md
This topic describes how to create a custom property for a data item container. In this example, the custom property pins a column to the Grid item in the WinForms Dashboard Designer.
View Example: WinForms Dashboard - Custom Properties
The code is organized into a separate module you can integrate in any dashboard application.
Create the GridFixedColumnModule 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 Fix Columns button is in the Custom Properties group on the Grid’s Design page.
public class GridFixedColumnModule {
public static readonly string PropertyName = "FixedColumns";
readonly DashboardDesigner designer;
public GridFixedColumnModule(DashboardDesigner designer, SvgImage barImage = null) {
this.designer = designer;
RibbonControl ribbon = (RibbonControl)designer.MenuManager;
RibbonPage page = ribbon.GetDashboardRibbonPage(DashboardBarItemCategory.GridTools, DashboardRibbonPage.Design);
RibbonPageGroup group = page.GetGroupByName("Custom Properties");
if(group == null) {
group = new RibbonPageGroup("Custom Properties") { Name = "Custom Properties" };
page.Groups.Add(group);
}
BarButtonItem barItem = CreateBarItem("Fix Columns", barImage);
group.ItemLinks.Add(barItem);
barItem.ItemClick += ChangeCustomPropertyValue;
designer.DashboardItemControlUpdated += Designer_DashboardItemControlUpdated;
}
Public Class GridFixedColumnModule
Public Shared ReadOnly PropertyName As String = "FixedColumns"
Private ReadOnly designer As DashboardDesigner
Public Sub New(ByVal designer As DashboardDesigner, Optional ByVal barImage As SvgImage = Nothing)
Me.designer = designer
Dim ribbon As RibbonControl = CType(designer.MenuManager, RibbonControl)
Dim page As RibbonPage = ribbon.GetDashboardRibbonPage(DashboardBarItemCategory.GridTools, 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 As BarButtonItem = CreateBarItem("Fix Columns", barImage)
group.ItemLinks.Add(barItem)
barItem.ItemClick += ChangeCustomPropertyValue
designer.DashboardItemControlUpdated += Designer_DashboardItemControlUpdated
End Sub
BarButtonItem CreateBarItem(string caption, SvgImage barImage) {
BarButtonItem barItem = new BarButtonItem();
barItem.Caption = caption;
barItem.ImageOptions.SvgImage = barImage;
return barItem;
}
Private Function CreateBarItem(ByVal caption As String, ByVal barImage As SvgImage) As BarButtonItem
Dim barItem As New BarButtonItem()
barItem.Caption = caption
barItem.ImageOptions.SvgImage = barImage
Return barItem
End Function
Create the CheckedComboBoxItem class that returns a list of grid columns and their checked state.
public class CheckedComboBoxItem {
public GridColumnBase Column { get; set; }
public bool Checked { get; set; }
public override string ToString() {
return Column.GetDisplayName();
}
}
Public Class CheckedComboBoxItem
Public Property Column() As GridColumnBase
Public Property Checked() As Boolean
Public Overrides Function ToString() As String
Return Column.GetDisplayName()
End Function
End Class
Create the XtraUserControl class instance and pass a list of CheckedComboBoxItem objects to its constructor. Subscribe to the BaseCheckedListBoxControl.ItemCheck event to check the columns checked status and specify whether they should be pinned.
public class ColumnSelectorControl: XtraUserControl {
CheckedListBoxControl checkedCombo = new CheckedListBoxControl();
public ColumnSelectorControl(List<CheckedComboBoxItem> gridColumns) {
foreach(CheckedComboBoxItem col in gridColumns) {
checkedCombo.Items.Add(col, col.Checked);
}
checkedCombo.ItemCheck += CheckedCombo_ItemCheck;
checkedCombo.Dock = DockStyle.Fill;
Controls.Add(checkedCombo);
Dock = DockStyle.Top;
}
Public Class ColumnSelectorControl
Inherits XtraUserControl
Private checkedCombo As New CheckedListBoxControl()
Public Sub New(ByVal gridColumns As List(Of CheckedComboBoxItem))
For Each col As CheckedComboBoxItem In gridColumns
checkedCombo.Items.Add(col, col.Checked)
Next col
checkedCombo.ItemCheck += CheckedCombo_ItemCheck
checkedCombo.Dock = DockStyle.Fill
Controls.Add(checkedCombo)
Dock = DockStyle.Top
End Sub
The ItemCheck event is raised each time your select the column in the ComboBox.
void CheckedCombo_ItemCheck(object sender, DevExpress.XtraEditors.Controls.ItemCheckEventArgs e) {
CheckedListBoxControl checkList = sender as CheckedListBoxControl;
CheckedComboBoxItem item = checkList.Items[e.Index].Value as CheckedComboBoxItem;
item.Checked = checkList.Items[e.Index].CheckState == CheckState.Checked;
}
Private Sub CheckedCombo_ItemCheck(ByVal sender As Object, ByVal e As DevExpress.XtraEditors.Controls.ItemCheckEventArgs)
Dim checkList As CheckedListBoxControl = TryCast(sender, CheckedListBoxControl)
Dim item As CheckedComboBoxItem = TryCast(checkList.Items(e.Index).Value, CheckedComboBoxItem)
item.Checked = checkList.Items(e.Index).CheckState = CheckState.Checked
End Sub
In this example, the custom property’s value is stored in the DataItemContainer.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 ChangeCustomPropertyValue(object sender, ItemClickEventArgs e) {
GridDashboardItem gridItem = designer.SelectedDashboardItem as GridDashboardItem;
List<CheckedComboBoxItem> checkedColumnsList = gridItem.Columns.Select(x => new CheckedComboBoxItem() {
Column = x,
Checked = Convert.ToBoolean(x.CustomProperties.GetValue(PropertyName))
}).ToList();
ColumnSelectorControl control = new ColumnSelectorControl(checkedColumnsList);
if(XtraDialog.Show(control, "Select columns to fix:") == DialogResult.OK) {
foreach(var item in checkedColumnsList)
if(Convert.ToBoolean(item.Column.CustomProperties.GetValue(PropertyName)) != item.Checked) {
string status = item.Checked == true ? "Pin" : "Unpin";
CustomPropertyHistoryItem historyItem = new CustomPropertyHistoryItem(item.Column, PropertyName, item.Checked.ToString(), $"{status} the {item} column");
designer.AddToHistory(historyItem);
}
}
}
}
Private Sub ChangeCustomPropertyValue(ByVal sender As Object, ByVal e As ItemClickEventArgs)
Dim gridItem As GridDashboardItem = TryCast(designer.SelectedDashboardItem, GridDashboardItem)
Dim checkedColumnsList As List(Of CheckedComboBoxItem) = gridItem.Columns.Select(Function(x) New CheckedComboBoxItem() With {
.Column = x,
.Checked = Convert.ToBoolean(x.CustomProperties.GetValue(PropertyName))
}).ToList()
Dim control As New ColumnSelectorControl(checkedColumnsList)
If XtraDialog.Show(control, "Select columns to fix:") = DialogResult.OK Then
For Each item In checkedColumnsList
If Convert.ToBoolean(item.Column.CustomProperties.GetValue(PropertyName)) <> item.Checked Then
Dim status As String = If(item.Checked = True, "Pin", "Unpin")
Dim historyItem As New CustomPropertyHistoryItem(item.Column, PropertyName, item.Checked.ToString(), $"{status} the {item} column")
designer.AddToHistory(historyItem)
End If
Next item
End If
End Sub
Handle the DashboardItemControlUpdated event to access the underlying Grid control and enable fixed columns. Use the CustomProperties.GetValue method to obtain the custom property’s value and update the selected column according to the value.
void Designer_DashboardItemControlUpdated(object sender, DashboardItemControlEventArgs e) {
if(e.GridControl != null) {
GridDashboardItem gridItem = designer.Dashboard.Items[e.DashboardItemName] as GridDashboardItem;
gridItem.GridOptions.ColumnWidthMode = GridColumnWidthMode.AutoFitToContents;
foreach(GridColumnBase itemColumn in gridItem.Columns) {
string customProperty = itemColumn.CustomProperties.GetValue(PropertyName);
if(!string.IsNullOrEmpty(customProperty)) {
GridColumn gridColumn = e.GridContext.GetControlColumn(itemColumn);
if(gridColumn != null) {
bool fixedWidthEnabled = Convert.ToBoolean(itemColumn.CustomProperties.GetValue(PropertyName));
gridColumn.Fixed = fixedWidthEnabled ? FixedStyle.Left : FixedStyle.None;
}
}
}
}
}
Private Sub Designer_DashboardItemControlUpdated(ByVal sender As Object, ByVal e As DashboardItemControlEventArgs)
If e.GridControl IsNot Nothing Then
Dim gridItem As GridDashboardItem = TryCast(designer.Dashboard.Items(e.DashboardItemName), GridDashboardItem)
gridItem.GridOptions.ColumnWidthMode = GridColumnWidthMode.AutoFitToContents
For Each itemColumn As GridColumnBase In gridItem.Columns
Dim customProperty As String = itemColumn.CustomProperties.GetValue(PropertyName)
If Not String.IsNullOrEmpty(customProperty) Then
Dim gridColumn As GridColumn = e.GridContext.GetControlColumn(itemColumn)
If gridColumn IsNot Nothing Then
Dim fixedWidthEnabled As Boolean = Convert.ToBoolean(itemColumn.CustomProperties.GetValue(PropertyName))
gridColumn.Fixed = If(fixedWidthEnabled, FixedStyle.Left, FixedStyle.None)
End If
End If
Next itemColumn
End If
End Sub
The code below is a complete module you need to add the Grid item’s Fix Columns option:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using DevExpress.DashboardCommon;
using DevExpress.DashboardWin;
using DevExpress.Utils.Svg;
using DevExpress.XtraBars;
using DevExpress.XtraBars.Ribbon;
using DevExpress.XtraEditors;
using DevExpress.XtraGrid.Columns;
namespace WindowsFormsAppCustomProperties {
public class GridFixedColumnModule {
public static readonly string PropertyName = "FixedColumns";
readonly DashboardDesigner designer;
public GridFixedColumnModule(DashboardDesigner designer, SvgImage barImage = null) {
this.designer = designer;
RibbonControl ribbon = (RibbonControl)designer.MenuManager;
RibbonPage page = ribbon.GetDashboardRibbonPage(DashboardBarItemCategory.GridTools, DashboardRibbonPage.Design);
RibbonPageGroup group = page.GetGroupByName("Custom Properties");
if(group == null) {
group = new RibbonPageGroup("Custom Properties") { Name = "Custom Properties" };
page.Groups.Add(group);
}
BarButtonItem barItem = CreateBarItem("Fix Columns", barImage);
group.ItemLinks.Add(barItem);
barItem.ItemClick += ChangeCustomPropertyValue;
designer.DashboardItemControlUpdated += Designer_DashboardItemControlUpdated;
}
BarButtonItem CreateBarItem(string caption, SvgImage barImage) {
BarButtonItem barItem = new BarButtonItem();
barItem.Caption = caption;
barItem.ImageOptions.SvgImage = barImage;
return barItem;
}
void Designer_DashboardItemControlUpdated(object sender, DashboardItemControlEventArgs e) {
if(e.GridControl != null) {
GridDashboardItem gridItem = designer.Dashboard.Items[e.DashboardItemName] as GridDashboardItem;
gridItem.GridOptions.ColumnWidthMode = GridColumnWidthMode.AutoFitToContents;
foreach(GridColumnBase itemColumn in gridItem.Columns) {
string customProperty = itemColumn.CustomProperties.GetValue(PropertyName);
if(!string.IsNullOrEmpty(customProperty)) {
GridColumn gridColumn = e.GridContext.GetControlColumn(itemColumn);
if(gridColumn != null) {
bool fixedWidthEnabled = Convert.ToBoolean(itemColumn.CustomProperties.GetValue(PropertyName));
gridColumn.Fixed = fixedWidthEnabled ? FixedStyle.Left : FixedStyle.None;
}
}
}
}
}
void ChangeCustomPropertyValue(object sender, ItemClickEventArgs e) {
GridDashboardItem gridItem = designer.SelectedDashboardItem as GridDashboardItem;
List<CheckedComboBoxItem> checkedColumnsList = gridItem.Columns.Select(x => new CheckedComboBoxItem() {
Column = x,
Checked = Convert.ToBoolean(x.CustomProperties.GetValue(PropertyName))
}).ToList();
ColumnSelectorControl control = new ColumnSelectorControl(checkedColumnsList);
if(XtraDialog.Show(control, "Select columns to fix:") == DialogResult.OK) {
foreach(var item in checkedColumnsList)
if(Convert.ToBoolean(item.Column.CustomProperties.GetValue(PropertyName)) != item.Checked) {
string status = item.Checked == true ? "Pin" : "Unpin";
CustomPropertyHistoryItem historyItem = new CustomPropertyHistoryItem(item.Column, PropertyName, item.Checked.ToString(), $"{status} the {item} column");
designer.AddToHistory(historyItem);
}
}
}
}
public class CheckedComboBoxItem {
public GridColumnBase Column { get; set; }
public bool Checked { get; set; }
public override string ToString() {
return Column.GetDisplayName();
}
}
public class ColumnSelectorControl: XtraUserControl {
CheckedListBoxControl checkedCombo = new CheckedListBoxControl();
public ColumnSelectorControl(List<CheckedComboBoxItem> gridColumns) {
foreach(CheckedComboBoxItem col in gridColumns) {
checkedCombo.Items.Add(col, col.Checked);
}
checkedCombo.ItemCheck += CheckedCombo_ItemCheck;
checkedCombo.Dock = DockStyle.Fill;
Controls.Add(checkedCombo);
Dock = DockStyle.Top;
}
void CheckedCombo_ItemCheck(object sender, DevExpress.XtraEditors.Controls.ItemCheckEventArgs e) {
CheckedListBoxControl checkList = sender as CheckedListBoxControl;
CheckedComboBoxItem item = checkList.Items[e.Index].Value as CheckedComboBoxItem;
item.Checked = checkList.Items[e.Index].CheckState == CheckState.Checked;
}
}
}
Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Windows.Forms
Imports DevExpress.DashboardCommon
Imports DevExpress.DashboardWin
Imports DevExpress.Utils.Svg
Imports DevExpress.XtraBars
Imports DevExpress.XtraBars.Ribbon
Imports DevExpress.XtraEditors
Imports DevExpress.XtraGrid.Columns
Namespace WindowsFormsAppCustomProperties
Public Class GridFixedColumnModule
Public Shared ReadOnly PropertyName As String = "FixedColumns"
Private ReadOnly designer As DashboardDesigner
Public Sub New(ByVal designer As DashboardDesigner, Optional ByVal barImage As SvgImage = Nothing)
Me.designer = designer
Dim ribbon As RibbonControl = CType(designer.MenuManager, RibbonControl)
Dim page As RibbonPage = ribbon.GetDashboardRibbonPage(DashboardBarItemCategory.GridTools, 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 As BarButtonItem = CreateBarItem("Fix Columns", barImage)
group.ItemLinks.Add(barItem)
AddHandler barItem.ItemClick, AddressOf ChangeCustomPropertyValue
AddHandler designer.DashboardItemControlUpdated, AddressOf Designer_DashboardItemControlUpdated
End Sub
Private Function CreateBarItem(ByVal caption As String, ByVal barImage As SvgImage) As BarButtonItem
Dim barItem As New BarButtonItem()
barItem.Caption = caption
barItem.ImageOptions.SvgImage = barImage
Return barItem
End Function
Private Sub Designer_DashboardItemControlUpdated(ByVal sender As Object, ByVal e As DashboardItemControlEventArgs)
If e.GridControl IsNot Nothing Then
Dim gridItem As GridDashboardItem = TryCast(designer.Dashboard.Items(e.DashboardItemName), GridDashboardItem)
gridItem.GridOptions.ColumnWidthMode = GridColumnWidthMode.AutoFitToContents
For Each itemColumn As GridColumnBase In gridItem.Columns
Dim customProperty As String = itemColumn.CustomProperties.GetValue(PropertyName)
If Not String.IsNullOrEmpty(customProperty) Then
Dim gridColumn As GridColumn = e.GridContext.GetControlColumn(itemColumn)
If gridColumn IsNot Nothing Then
Dim fixedWidthEnabled As Boolean = Convert.ToBoolean(itemColumn.CustomProperties.GetValue(PropertyName))
gridColumn.Fixed = If(fixedWidthEnabled, FixedStyle.Left, FixedStyle.None)
End If
End If
Next itemColumn
End If
End Sub
Private Sub ChangeCustomPropertyValue(ByVal sender As Object, ByVal e As ItemClickEventArgs)
Dim gridItem As GridDashboardItem = TryCast(designer.SelectedDashboardItem, GridDashboardItem)
Dim checkedColumnsList As List(Of CheckedComboBoxItem) = gridItem.Columns.Select(Function(x) New CheckedComboBoxItem() With {
.Column = x,
.Checked = Convert.ToBoolean(x.CustomProperties.GetValue(PropertyName))
}).ToList()
Dim control As New ColumnSelectorControl(checkedColumnsList)
If XtraDialog.Show(control, "Select columns to fix:") = DialogResult.OK Then
For Each item In checkedColumnsList
If Convert.ToBoolean(item.Column.CustomProperties.GetValue(PropertyName)) <> item.Checked Then
Dim status As String = If(item.Checked = True, "Pin", "Unpin")
Dim historyItem As New CustomPropertyHistoryItem(item.Column, PropertyName, item.Checked.ToString(), $"{status} the {item} column")
designer.AddToHistory(historyItem)
End If
Next item
End If
End Sub
End Class
Public Class CheckedComboBoxItem
Public Property Column() As GridColumnBase
Public Property Checked() As Boolean
Public Overrides Function ToString() As String
Return Column.GetDisplayName()
End Function
End Class
Public Class ColumnSelectorControl
Inherits XtraUserControl
Private checkedCombo As New CheckedListBoxControl()
Public Sub New(ByVal gridColumns As List(Of CheckedComboBoxItem))
For Each col As CheckedComboBoxItem In gridColumns
checkedCombo.Items.Add(col, col.Checked)
Next col
AddHandler checkedCombo.ItemCheck, AddressOf CheckedCombo_ItemCheck
checkedCombo.Dock = DockStyle.Fill
Controls.Add(checkedCombo)
Dock = DockStyle.Top
End Sub
Private Sub CheckedCombo_ItemCheck(ByVal sender As Object, ByVal e As DevExpress.XtraEditors.Controls.ItemCheckEventArgs)
Dim checkList As CheckedListBoxControl = TryCast(sender, CheckedListBoxControl)
Dim item As CheckedComboBoxItem = TryCast(checkList.Items(e.Index).Value, CheckedComboBoxItem)
item.Checked = checkList.Items(e.Index).CheckState = CheckState.Checked
End Sub
End Class
End Namespace
Register the created module before you load a dashboard to apply custom settings to this dashboard. For this, create a new GridFixedColumnModule 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 an icon for the bar item.
using WindowsFormsAppCustomProperties;
//...
public Form1() {
InitializeComponent();
new GridFixedColumnModule(dashboardDesigner1, svgImageCollection1["alignverticalleft"]);
dashboardDesigner1.LoadDashboard("../../Dashboard/newDashboard.xml");
//...
}
Imports WindowsFormsAppCustomProperties
'...
Public Sub New()
InitializeComponent()
Dim TempGridFixedColumnModule As GridFixedColumnModule = New GridFixedColumnModule(dashboardDesigner1, svgImageCollection1("alignverticalleft"))
dashboardDesigner1.LoadDashboard("../../Dashboard/newDashboard.xml")
'...
End Sub
After you registered the GridFixedColumnModule module, the FixedColumn button is added that invokes the pop-up comboBox menu that contains the selected grid item’s data fields. Select the fields you want to pin and click OK.
you can undo/redo actions because information about the scale break property’s state is saved in history.
See Also