@* Header *@
+ @* Toolbar *@
+ @if (_currentGrid != null)
+ {
+
+
+
+ }
+
@* Content *@
@if (GetActiveDataItem() != null && _currentGrid != null)
@@ -446,87 +454,37 @@
{
var seq = 0;
- switch (settingsType)
+ // View mode: simple text display with DevExpress-like styling (no editors)
+ builder.OpenElement(seq++, "div");
+ builder.AddAttribute(seq++, "class", GetViewModeCssClass(value, settingsType));
+ builder.AddAttribute(seq++, "title", displayText);
+
+ // Special handling for boolean - show checkbox icon
+ if (value is bool boolValue)
{
- case EditSettingsType.ComboBox:
- builder.OpenElement(seq++, "div");
- builder.AddAttribute(seq++, "title", displayText);
- builder.AddAttribute(seq++, "class", "info-panel-text-wrapper");
- builder.OpenComponent(seq++);
- builder.AddAttribute(seq++, "Text", displayText);
- builder.AddAttribute(seq++, "ReadOnly", true);
- builder.CloseComponent();
- builder.CloseElement();
- return;
-
- case EditSettingsType.CheckBox when value is bool boolVal:
- builder.OpenComponent>(seq++);
- builder.AddAttribute(seq++, "Checked", boolVal);
- builder.AddAttribute(seq++, "ReadOnly", true);
- builder.CloseComponent();
- return;
-
- case EditSettingsType.Memo:
- builder.OpenElement(seq++, "div");
- builder.AddAttribute(seq++, "title", displayText);
- builder.OpenComponent(seq++);
- builder.AddAttribute(seq++, "Text", displayText);
- builder.AddAttribute(seq++, "ReadOnly", true);
- builder.AddAttribute(seq++, "Rows", 3);
- builder.CloseComponent();
- builder.CloseElement();
- return;
+ builder.OpenElement(seq++, "span");
+ builder.AddAttribute(seq++, "class", boolValue ? "dx-icon dx-icon-check text-success" : "dx-icon dx-icon-close text-muted");
+ builder.CloseElement();
}
-
- // Default by value type
- switch (value)
+ else
{
- case bool boolValue:
- builder.OpenComponent>(seq++);
- builder.AddAttribute(seq++, "Checked", boolValue);
- builder.AddAttribute(seq++, "ReadOnly", true);
- builder.CloseComponent();
- break;
-
- case DateTime dateValue:
- builder.OpenComponent>(seq++);
- builder.AddAttribute(seq++, "Date", dateValue);
- builder.AddAttribute(seq++, "ReadOnly", true);
- builder.AddAttribute(seq++, "DisplayFormat", column.DisplayFormat ?? "yyyy-MM-dd HH:mm");
- builder.CloseComponent();
- break;
-
- case DateOnly dateOnlyValue:
- builder.OpenComponent>(seq++);
- builder.AddAttribute(seq++, "Date", dateOnlyValue);
- builder.AddAttribute(seq++, "ReadOnly", true);
- builder.AddAttribute(seq++, "DisplayFormat", column.DisplayFormat ?? "yyyy-MM-dd");
- builder.CloseComponent();
- break;
-
- case decimal or double or float or int or long or short:
- builder.OpenElement(seq++, "div");
- builder.AddAttribute(seq++, "title", displayText);
- builder.AddAttribute(seq++, "class", "info-panel-text-wrapper");
- builder.OpenComponent(seq++);
- builder.AddAttribute(seq++, "Text", displayText);
- builder.AddAttribute(seq++, "ReadOnly", true);
- builder.AddAttribute(seq++, "CssClass", "text-end");
- builder.CloseComponent();
- builder.CloseElement();
- break;
-
- default:
- builder.OpenElement(seq++, "div");
- builder.AddAttribute(seq++, "title", displayText);
- builder.AddAttribute(seq++, "class", "info-panel-text-wrapper");
- builder.OpenComponent(seq++);
- builder.AddAttribute(seq++, "Text", displayText);
- builder.AddAttribute(seq++, "ReadOnly", true);
- builder.CloseComponent();
- builder.CloseElement();
- break;
+ builder.AddContent(seq++, displayText);
}
+
+ builder.CloseElement();
+ };
+ }
+
+ private static string GetViewModeCssClass(object? value, EditSettingsType settingsType)
+ {
+ var baseCss = "mg-info-panel-value";
+
+ return value switch
+ {
+ bool => $"{baseCss} mg-info-panel-value-bool",
+ decimal or double or float or int or long or short => $"{baseCss} mg-info-panel-value-numeric",
+ DateTime or DateOnly or TimeOnly => $"{baseCss} mg-info-panel-value-date",
+ _ => baseCss
};
}
}
diff --git a/AyCode.Blazor.Components/Components/Grids/MgGridInfoPanel.razor.cs b/AyCode.Blazor.Components/Components/Grids/MgGridInfoPanel.razor.cs
index 20cb506..400666b 100644
--- a/AyCode.Blazor.Components/Components/Grids/MgGridInfoPanel.razor.cs
+++ b/AyCode.Blazor.Components/Components/Grids/MgGridInfoPanel.razor.cs
@@ -11,7 +11,7 @@ public interface IInfoPanelBase
{
void ClearEditMode();
void SetEditMode(object editModel);
- void RefreshData(DxGrid grid, object? dataItem, int visibleIndex = -1);
+ void RefreshData(IMgGridBase grid, object? dataItem, int visibleIndex = -1);
}
///
@@ -30,7 +30,7 @@ public partial class MgGridInfoPanel : ComponentBase, IAsyncDisposable, IInfoPan
private bool _isJsInitialized;
private const int DefaultTopOffset = 300; // Increased from 180 to account for header + tabs + toolbar
- private DxGrid? _currentGrid;
+ private IMgGridBase? _currentGrid;
private object? _currentDataItem;
private int _focusedRowVisibleIndex = -1;
private List _allDataColumns = [];
@@ -69,7 +69,7 @@ public partial class MgGridInfoPanel : ComponentBase, IAsyncDisposable, IInfoPan
///
/// Refreshes the InfoPanel with data from the specified grid row (view mode)
///
- public void RefreshData(DxGrid grid, object? dataItem, int visibleIndex = -1)
+ public void RefreshData(IMgGridBase grid, object? dataItem, int visibleIndex = -1)
{
ArgumentNullException.ThrowIfNull(grid);
@@ -290,12 +290,12 @@ public partial class MgGridInfoPanel : ComponentBase, IAsyncDisposable, IInfoPan
decimal decValue => decValue.ToString("N2"),
double dblValue => dblValue.ToString("N2"),
float fltValue => fltValue.ToString("N2"),
- int or long or short or byte => string.Format("{0:N0}", value),
+ int or long or short or byte => $"{value:N0}",
_ => value.ToString() ?? string.Empty
};
}
- private static List GetAllDataColumns(DxGrid grid)
+ private static List GetAllDataColumns(IMgGridBase grid)
{
var columns = new List();
diff --git a/AyCode.Blazor.Components/Components/Grids/MgGridInfoPanel.razor.css b/AyCode.Blazor.Components/Components/Grids/MgGridInfoPanel.razor.css
index 01adbaf..b070bc9 100644
--- a/AyCode.Blazor.Components/Components/Grids/MgGridInfoPanel.razor.css
+++ b/AyCode.Blazor.Components/Components/Grids/MgGridInfoPanel.razor.css
@@ -105,3 +105,31 @@
overflow: hidden;
white-space: nowrap;
}
+/* View mode value styling - matches DevExpress theme */
+.mg-info-panel-value {
+ padding: 0.375rem 0.75rem;
+ min-height: 2rem;
+ display: flex;
+ align-items: center;
+ justify-content: flex-start; /* Always align left */
+ background-color: var(--dxbl-bg, #fff);
+ border: 1px solid var(--dxbl-border-color, #dee2e6);
+ border-radius: var(--dxbl-border-radius, 0.25rem);
+ font-size: var(--dxbl-font-size, 0.875rem);
+ color: var(--dxbl-text, #212529);
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.mg-info-panel-value-numeric {
+ font-variant-numeric: tabular-nums;
+}
+
+.mg-info-panel-value-bool {
+ /* Keep left aligned */
+}
+
+.mg-info-panel-value-date {
+ font-variant-numeric: tabular-nums;
+}
diff --git a/AyCode.Blazor.Components/Components/Grids/MgGridToolbarBase.cs b/AyCode.Blazor.Components/Components/Grids/MgGridToolbarBase.cs
new file mode 100644
index 0000000..e4ee10d
--- /dev/null
+++ b/AyCode.Blazor.Components/Components/Grids/MgGridToolbarBase.cs
@@ -0,0 +1,12 @@
+using DevExpress.Blazor;
+using Microsoft.AspNetCore.Components;
+
+namespace AyCode.Blazor.Components.Components.Grids
+{
+ public class MgGridToolbarBase : DxToolbar
+ {
+ [Parameter] public IMgGridBase Grid { get; set; }
+ [Parameter] public Func RefreshClick { get; set; }
+ [Parameter] public bool ShowOnlyIcon { get; set; } = false;
+ }
+}
diff --git a/AyCode.Blazor.Components/Components/Grids/MgGridToolbarTemplate.razor b/AyCode.Blazor.Components/Components/Grids/MgGridToolbarTemplate.razor
new file mode 100644
index 0000000..1350c1d
--- /dev/null
+++ b/AyCode.Blazor.Components/Components/Grids/MgGridToolbarTemplate.razor
@@ -0,0 +1,134 @@
+@using AyCode.Blazor.Components.Components.Grids
+
+
+
+
+
+
+
+
+
+
+
+
+ @if (!OnlyGridEditTools)
+ {
+
+
+
+
+
+
+
+
+
+
+
+ @ToolbarItemsExtended
+ }
+
+
+@code {
+ [Parameter] public bool OnlyGridEditTools { get; set; } = false;
+ [Parameter] public IMgGridBase Grid { get; set; } = null!;
+ [Parameter] public RenderFragment? ToolbarItemsExtended { get; set; }
+ [Parameter] public EventCallback OnReloadDataClick { get; set; }
+ [Parameter] public bool ShowOnlyIcon { get; set; } = false;
+
+ public MgGridToolbarBase GridToolbar { get; set; } = null!;
+ const string ExportFileName = "ExportResult";
+
+ private bool _isReloadInProgress;
+
+ ///
+ /// Whether the grid is currently in edit mode (New or Edit)
+ ///
+ private bool IsEditing => Grid?.GridEditState != MgGridEditState.None;
+
+ ///
+ /// Whether the grid is currently syncing data
+ ///
+ private bool IsSyncing => Grid?.IsSyncing ?? false;
+
+ ///
+ /// Whether there is a focused row in the grid
+ ///
+ private bool HasFocusedRow => Grid?.GetFocusedRowIndex() >= 0;
+
+ protected override void OnInitialized()
+ {
+ }
+
+ async Task ReloadData_Click(ToolbarItemClickEventArgs e)
+ {
+ _isReloadInProgress = true;
+ try
+ {
+ await OnReloadDataClick.InvokeAsync(e);
+ }
+ finally
+ {
+ _isReloadInProgress = false;
+ }
+ }
+
+ async Task NewItem_Click()
+ {
+ await Grid.StartEditNewRowAsync();
+ }
+
+ async Task EditItem_Click()
+ {
+ await Grid.StartEditRowAsync(Grid.GetFocusedRowIndex());
+ }
+
+ void DeleteItem_Click()
+ {
+ Grid.ShowRowDeleteConfirmation(Grid.GetFocusedRowIndex());
+ }
+
+ async Task SaveItem_Click()
+ {
+ await Grid.SaveChangesAsync();
+ }
+
+ async Task CancelEdit_Click()
+ {
+ await Grid.CancelEditAsync();
+ }
+
+ void PrevRow_Click()
+ {
+ Grid.StepPrevRow();
+ }
+
+ void NextRow_Click()
+ {
+ Grid.StepNextRow();
+ }
+
+ void ColumnChooserItem_Click(ToolbarItemClickEventArgs e)
+ {
+ Grid.ShowColumnChooser();
+ }
+
+ async Task ExportXlsxItem_Click()
+ {
+ await Grid.ExportToXlsxAsync(ExportFileName);
+ }
+
+ async Task ExportXlsItem_Click()
+ {
+ await Grid.ExportToXlsAsync(ExportFileName);
+ }
+
+ async Task ExportCsvItem_Click()
+ {
+ await Grid.ExportToCsvAsync(ExportFileName);
+ }
+
+ async Task ExportPdfItem_Click()
+ {
+ await Grid.ExportToPdfAsync(ExportFileName);
+ }
+}
\ No newline at end of file