From 137924992033f83abc3ddd5f2e10fc97af331097 Mon Sep 17 00:00:00 2001 From: DevExpressExampleBot Date: Mon, 17 Nov 2025 15:12:34 +0400 Subject: [PATCH 1/6] README auto update [skip ci] --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 4438aca..b49a346 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,4 @@ -![](https://img.shields.io/endpoint?url=https://codecentral.devexpress.com/api/v1/VersionRange/1098175829/25.1.3%2B) [![](https://img.shields.io/badge/Open_in_DevExpress_Support_Center-FF7200?style=flat-square&logo=DevExpress&logoColor=white)](https://supportcenter.devexpress.com/ticket/details/T1313893) [![](https://img.shields.io/badge/📖_How_to_use_DevExpress_Examples-e9f6fc?style=flat-square)](https://docs.devexpress.com/GeneralInformation/403183) [![](https://img.shields.io/badge/💬_Leave_Feedback-feecdd?style=flat-square)](#does-this-example-address-your-development-requirementsobjectives) From da977cdf3bb7cf6f296be30bcff4acb1ce6c5c8c Mon Sep 17 00:00:00 2001 From: Schulllz Date: Mon, 17 Nov 2025 15:14:34 +0400 Subject: [PATCH 2/6] Custom column chooser implemented. Moved data classes to separate files --- CS/Components/Pages/Index.razor | 126 ++++++++++++++++++++++---- CS/CustomColumnChooser.sln | 2 +- CS/Program.cs | 3 +- CS/Services/WeatherForecast.cs | 12 +++ CS/Services/WeatherForecastService.cs | 28 ++++++ 5 files changed, 152 insertions(+), 19 deletions(-) create mode 100644 CS/Services/WeatherForecast.cs create mode 100644 CS/Services/WeatherForecastService.cs diff --git a/CS/Components/Pages/Index.razor b/CS/Components/Pages/Index.razor index 3251a4d..baf6fd4 100644 --- a/CS/Components/Pages/Index.razor +++ b/CS/Components/Pages/Index.razor @@ -1,13 +1,22 @@ @page "/" +@using CustomColumnChooser.Services +@inject WeatherForecastService ForecastService + Welcome + + + + @if (forecasts == null) {

Loading...

} else { - + - + + @@ -15,23 +24,106 @@ else { } + + +
+
+ + + Reverse Order +
+ + +
+
+
+ +

The Date column ShowInColumnChooser parameter is false - thus, it doesn't appear in the Column Chooser

@code { + DxGrid MyGrid { get; set; } = default!; + DxListBox columnListBox { get; set; } = default!; private WeatherForecast[]? forecasts; - + private bool isCustomColumnChooserVisible = false; + public IEnumerable AllColumns { get; set; } + public IEnumerable VisibleColumns { get; set; } + bool ReverseOrder { get; set; } = false; + + #region Initialization protected override async Task OnInitializedAsync() { - var startDate = DateOnly.FromDateTime(DateTime.Now); - var summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" }; - forecasts = Enumerable.Range(1, 5).Select(index => new WeatherForecast { - Date = startDate.AddDays(index), - TemperatureC = Random.Shared.Next(-20, 55), - Summary = summaries[Random.Shared.Next(summaries.Length)] - }).ToArray(); - } - - private class WeatherForecast { - public DateOnly Date { get; set; } - public int TemperatureC { get; set; } - public string? Summary { get; set; } - public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); + forecasts = await ForecastService.GetForecastsAsync(); + } + protected override void OnAfterRender(bool firstRender) { + if (firstRender) { + InitializeColumnList(); + } + } + private void ShowCustomColumnChooser() { + isCustomColumnChooserVisible = true; + } + private void InitializeColumnList() { + AllColumns = MyGrid.GetColumns().Where(i => i.ShowInColumnChooser).OrderBy(i => i, ColumnsComparerImpl.Default).ToList(); + if (ReverseOrder) + AllColumns = AllColumns.Reverse(); + VisibleColumns = MyGrid.GetVisibleColumns(); + } + #endregion + + #region Event Handling + void SelectedDataItemsChanged(SelectedDataItemsChangedEventArgs args) { + if (args.ChangeSource == SelectionChangeSource.ParameterChange) + return; + var values = args.DataItems; + VisibleColumns = values; + UpdateColumnsVisibility(); + } + void UpdateColumnsVisibility() { + MyGrid.BeginUpdate(); + var columnCollection = MyGrid.GetColumns(); + foreach (var column in columnCollection) + if (column.ShowInColumnChooser) + column.Visible = VisibleColumns.Contains(column); + MyGrid.EndUpdate(); + } + private async Task SelectAllColumns() { + await columnListBox.SelectAllAsync(); + UpdateColumnsVisibility(); + } + private async Task DeselectAllColumns() { + await columnListBox.DeselectAllAsync(); + UpdateColumnsVisibility(); + } + private void OnReverseOrder(bool newValue) { + ReverseOrder = newValue; + AllColumns = AllColumns.Reverse(); + } + #endregion + + class ColumnsComparerImpl : IComparer { + public static IComparer Default { get; } = new ColumnsComparerImpl(); + ColumnsComparerImpl() { } + int IComparer.Compare(IGridColumn x, IGridColumn y) { + if (x is IGridSelectionColumn) + return -1; + if (x is IGridCommandColumn && y is IGridDataColumn) + return -1; + if (x is IGridDataColumn xData && y is IGridDataColumn yData) { + var xName = !string.IsNullOrEmpty(xData.Caption) ? xData.Caption : xData.FieldName; + var yName = !string.IsNullOrEmpty(yData.Caption) ? yData.Caption : yData.FieldName; + return string.Compare(xName, yName); + } + return 0; + } } } diff --git a/CS/CustomColumnChooser.sln b/CS/CustomColumnChooser.sln index fd52aed..71e9221 100644 --- a/CS/CustomColumnChooser.sln +++ b/CS/CustomColumnChooser.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 -VisualStudioVersion = 17.14.36518.9 d17.14 +VisualStudioVersion = 17.14.36518.9 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CustomColumnChooser", "CustomColumnChooser.csproj", "{B3679CF4-DD44-4DAD-A419-5D98E4383F48}" EndProject diff --git a/CS/Program.cs b/CS/Program.cs index e88b222..6d51938 100644 --- a/CS/Program.cs +++ b/CS/Program.cs @@ -11,6 +11,7 @@ options.SizeMode = DevExpress.Blazor.SizeMode.Medium; }); builder.Services.AddMvc(); +builder.Services.AddSingleton(); var app = builder.Build(); if (!app.Environment.IsDevelopment()) @@ -29,4 +30,4 @@ .AddInteractiveServerRenderMode() .AllowAnonymous(); -app.Run(); \ No newline at end of file +app.Run(); diff --git a/CS/Services/WeatherForecast.cs b/CS/Services/WeatherForecast.cs new file mode 100644 index 0000000..dfbba21 --- /dev/null +++ b/CS/Services/WeatherForecast.cs @@ -0,0 +1,12 @@ +using System; + +namespace CustomColumnChooser.Services +{ + public class WeatherForecast + { + public DateOnly Date { get; set; } + public int TemperatureC { get; set; } + public string? Summary { get; set; } + public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); + } +} \ No newline at end of file diff --git a/CS/Services/WeatherForecastService.cs b/CS/Services/WeatherForecastService.cs new file mode 100644 index 0000000..352b065 --- /dev/null +++ b/CS/Services/WeatherForecastService.cs @@ -0,0 +1,28 @@ +using System; +using System.Linq; +using System.Threading.Tasks; + +namespace CustomColumnChooser.Services +{ + public class WeatherForecastService + { + private static readonly string[] Summaries = new[] + { + "Freezing", "Bracing", "Chilly", "Cool", "Mild", + "Warm", "Balmy", "Hot", "Sweltering", "Scorching" + }; + + public Task GetForecastsAsync(int days = 5) + { + var startDate = DateOnly.FromDateTime(DateTime.Now); + var forecasts = Enumerable.Range(1, days).Select(index => new WeatherForecast + { + Date = startDate.AddDays(index), + TemperatureC = Random.Shared.Next(-20, 55), + Summary = Summaries[Random.Shared.Next(Summaries.Length)] + }).ToArray(); + + return Task.FromResult(forecasts); + } + } +} \ No newline at end of file From d572e280456dab93f6db462746349205338163e7 Mon Sep 17 00:00:00 2001 From: Schulllz Date: Tue, 18 Nov 2025 12:13:03 +0400 Subject: [PATCH 3/6] Replaced inline styles with CSS classes for csp compliance --- CS/Components/Pages/Index.razor | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/CS/Components/Pages/Index.razor b/CS/Components/Pages/Index.razor index baf6fd4..afa1deb 100644 --- a/CS/Components/Pages/Index.razor +++ b/CS/Components/Pages/Index.razor @@ -4,6 +4,19 @@ Welcome + @@ -30,9 +43,9 @@ else { Height="auto" ShowCloseButton="true"> -
-
- +
+
+ Reverse Order
@@ -59,7 +72,7 @@ else { public IEnumerable AllColumns { get; set; } public IEnumerable VisibleColumns { get; set; } bool ReverseOrder { get; set; } = false; - + #region Initialization protected override async Task OnInitializedAsync() { forecasts = await ForecastService.GetForecastsAsync(); From 8f2c66d79ca74d7d0a83a23c1991d7a2b068623e Mon Sep 17 00:00:00 2001 From: Schulllz Date: Tue, 18 Nov 2025 12:16:48 +0400 Subject: [PATCH 4/6] removed unnecessary variable in SelectedDataItemsChanged --- CS/Components/Pages/Index.razor | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CS/Components/Pages/Index.razor b/CS/Components/Pages/Index.razor index afa1deb..f5af9aa 100644 --- a/CS/Components/Pages/Index.razor +++ b/CS/Components/Pages/Index.razor @@ -97,8 +97,7 @@ else { void SelectedDataItemsChanged(SelectedDataItemsChangedEventArgs args) { if (args.ChangeSource == SelectionChangeSource.ParameterChange) return; - var values = args.DataItems; - VisibleColumns = values; + VisibleColumns = args.DataItems; UpdateColumnsVisibility(); } void UpdateColumnsVisibility() { From 9109560141d28ecc82e3b0c2a07350b88a954fbb Mon Sep 17 00:00:00 2001 From: Schulllz Date: Tue, 18 Nov 2025 16:25:52 +0400 Subject: [PATCH 5/6] Moved styles to site.css for CSP complience --- CS/Components/Pages/Index.razor | 14 -------------- CS/wwwroot/css/site.css | 11 +++++++++++ 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/CS/Components/Pages/Index.razor b/CS/Components/Pages/Index.razor index f5af9aa..93a0a92 100644 --- a/CS/Components/Pages/Index.razor +++ b/CS/Components/Pages/Index.razor @@ -4,20 +4,6 @@ Welcome - - diff --git a/CS/wwwroot/css/site.css b/CS/wwwroot/css/site.css index c3fbbbf..5e90fb7 100644 --- a/CS/wwwroot/css/site.css +++ b/CS/wwwroot/css/site.css @@ -102,3 +102,14 @@ html, body { mask-image: var(--icon-mask-image); } +.column-chooser-body { + padding: 10px; +} + +.column-chooser-buttons { + margin-bottom: 10px; +} + +.column-chooser-button-spacing { + margin-right: 5px; +} From 55040f3ada1a4c717675cde5159f36c1bc8e4770 Mon Sep 17 00:00:00 2001 From: Schulllz Date: Thu, 27 Nov 2025 17:00:55 +0400 Subject: [PATCH 6/6] Applied Svetlana's recommendations after Demo Use built-in listbox select/deselect all option. Moved "reversed" checkbox below the columns list. Changed SelectedDataItemsChanged to ValuesChanged --- CS/Components/Pages/Index.razor | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/CS/Components/Pages/Index.razor b/CS/Components/Pages/Index.razor index 93a0a92..d6bb6f8 100644 --- a/CS/Components/Pages/Index.razor +++ b/CS/Components/Pages/Index.razor @@ -18,7 +18,7 @@ else { - + } @@ -30,21 +30,22 @@ else { ShowCloseButton="true">
-
- - - Reverse Order -
+
+ + Reverse Order + +
@@ -80,10 +81,9 @@ else { #endregion #region Event Handling - void SelectedDataItemsChanged(SelectedDataItemsChangedEventArgs args) { - if (args.ChangeSource == SelectionChangeSource.ParameterChange) - return; - VisibleColumns = args.DataItems; + void SelectedDataItemsChanged(IEnumerable values) + { + VisibleColumns = values; UpdateColumnsVisibility(); } void UpdateColumnsVisibility() { @@ -94,14 +94,6 @@ else { column.Visible = VisibleColumns.Contains(column); MyGrid.EndUpdate(); } - private async Task SelectAllColumns() { - await columnListBox.SelectAllAsync(); - UpdateColumnsVisibility(); - } - private async Task DeselectAllColumns() { - await columnListBox.DeselectAllAsync(); - UpdateColumnsVisibility(); - } private void OnReverseOrder(bool newValue) { ReverseOrder = newValue; AllColumns = AllColumns.Reverse();