Add grid font size selector and fix German character display

Introduced font size adjustment for grids via dropdown toolbar and CSS variable. Added JavaScript for dynamic font size changes. Replaced German umlauts with HTML entities for proper rendering. Refactored grid code and improved error/info message display. Enhances accessibility and user experience.
This commit is contained in:
OlgunR
2026-02-19 17:01:33 +01:00
parent e7aa41aa4d
commit c5ca9f0048
5 changed files with 111 additions and 28 deletions

View File

@@ -25,6 +25,7 @@
<link rel="stylesheet" href="app.css" />
<link rel="stylesheet" href="DbFirst.BlazorWebApp.styles.css" />
<link rel="icon" type="image/png" href="favicon.png" />
<script src="js/size-manager.js"></script>
<HeadOutlet />
</head>

View File

@@ -75,15 +75,15 @@ else if (!string.IsNullOrWhiteSpace(infoMessage))
}
else if (items.Count == 0)
{
<p>Keine Einträge vorhanden.</p>
<p>Keine Eintr&#228;ge vorhanden.</p>
}
else
{
<div class="band-editor">
<div class="band-controls">
<DxButton Text="Band hinzufügen" Click="AddBand" />
<DxButton Text="Band hinzuf&#252;gen" Click="AddBand" />
<DxButton Text="Layout speichern" Click="SaveLayoutAsync" Enabled="@CanSaveBandLayout" />
<DxButton Text="Band-Layout zurücksetzen" Click="ResetBandLayoutAsync" />
<DxButton Text="Band-Layout zur&#252;cksetzen" Click="ResetBandLayoutAsync" />
</div>
@foreach (var band in bandLayout.Bands)
{
@@ -113,6 +113,7 @@ else
<DxGrid Data="@items"
TItem="CatalogReadDto"
KeyFieldName="@nameof(CatalogReadDto.Guid)"
SizeMode="@_sizeMode"
ShowGroupPanel="true"
ShowGroupedColumns="true"
AllowGroup="true"
@@ -131,6 +132,25 @@ else
FocusedRowEnabled="true"
@bind-FocusedRowKey="focusedRowKey"
@ref="gridRef">
<ToolbarTemplate>
<DxToolbar>
<DxToolbarItem Alignment="ToolbarItemAlignment.Right">
<Template Context="_">
<DxDropDownButton Text="@FormatSizeText(_sizeMode)"
RenderStyle="ButtonRenderStyle.Secondary"
RenderStyleMode="ButtonRenderStyleMode.Text"
ItemClick="OnSizeChange">
<Items>
@foreach (var size in _sizeModes)
{
<DxDropDownButtonItem Text="@FormatSizeText(size)" Id="@size.ToString()" />
}
</Items>
</DxDropDownButton>
</Template>
</DxToolbarItem>
</DxToolbar>
</ToolbarTemplate>
<Columns>
@RenderColumns()
</Columns>
@@ -191,8 +211,8 @@ else
new() { FieldName = nameof(CatalogReadDto.CatString), Caption = "String", FilterType = ColumnFilterType.Text },
new() { FieldName = nameof(CatalogReadDto.AddedWho), Caption = "Angelegt von", ReadOnly = true, FilterType = ColumnFilterType.Text },
new() { FieldName = nameof(CatalogReadDto.AddedWhen), Caption = "Angelegt am", ReadOnly = true, FilterType = ColumnFilterType.Date },
new() { FieldName = nameof(CatalogReadDto.ChangedWho), Caption = "Geändert von", ReadOnly = true, FilterType = ColumnFilterType.Text },
new() { FieldName = nameof(CatalogReadDto.ChangedWhen), Caption = "Geändert am", ReadOnly = true, FilterType = ColumnFilterType.Date }
new() { FieldName = nameof(CatalogReadDto.ChangedWho), Caption = "Ge&#228;ndert von", ReadOnly = true, FilterType = ColumnFilterType.Text },
new() { FieldName = nameof(CatalogReadDto.ChangedWhen), Caption = "Ge&#228;ndert am", ReadOnly = true, FilterType = ColumnFilterType.Date }
};
private readonly List<ProcedureOption> procedureOptions = new()
@@ -204,6 +224,23 @@ else
private bool CanSaveBandLayout => !string.IsNullOrWhiteSpace(layoutUser);
private bool gridLayoutApplied;
private DevExpress.Blazor.SizeMode _sizeMode = DevExpress.Blazor.SizeMode.Medium;
private static readonly List<DevExpress.Blazor.SizeMode> _sizeModes =
Enum.GetValues<DevExpress.Blazor.SizeMode>().ToList();
private string FormatSizeText(DevExpress.Blazor.SizeMode size) => size switch
{
DevExpress.Blazor.SizeMode.Small => "Klein",
DevExpress.Blazor.SizeMode.Medium => "Mittel",
DevExpress.Blazor.SizeMode.Large => "Groß",
_ => size.ToString()
};
private void OnSizeChange(DropDownButtonItemClickEventArgs args)
{
_sizeMode = Enum.Parse<DevExpress.Blazor.SizeMode>(args.ItemInfo.Id);
}
protected override async Task OnInitializedAsync()
{
columnLookup = columnDefinitions.ToDictionary(column => column.FieldName, StringComparer.OrdinalIgnoreCase);
@@ -397,7 +434,7 @@ else
if (editModel.UpdateProcedure == 0 &&
!string.Equals(editModel.CatTitle, editModel.OriginalCatTitle, StringComparison.OrdinalIgnoreCase))
{
AddValidationError(editModel, nameof(CatalogEditModel.CatTitle), "Titel kann nicht geändert werden.");
AddValidationError(editModel, nameof(CatalogEditModel.CatTitle), "Titel kann nicht ge&#228;ndert werden.");
return false;
}
@@ -416,17 +453,17 @@ else
var deleted = await Api.DeleteAsync(item.Guid);
if (!deleted.Success)
{
errorMessage = deleted.Error ?? "Löschen fehlgeschlagen.";
errorMessage = deleted.Error ?? "L&#246;schen fehlgeschlagen.";
e.Cancel = true;
return;
}
infoMessage = "Katalog gelöscht.";
infoMessage = "Katalog gel&#246;scht.";
await LoadCatalogs();
}
catch (Exception ex)
{
errorMessage = $"Fehler beim Löschen: {ex.Message}";
errorMessage = $"Fehler beim L&#246;schen: {ex.Message}";
e.Cancel = true;
}
}
@@ -529,7 +566,7 @@ else
bandLayout = new BandLayout();
columnBandAssignments.Clear();
UpdateBandOptions();
infoMessage = "Band-Layout zurückgesetzt.";
infoMessage = "Band-Layout zur&#252;ckgesetzt.";
}
private void ApplyColumnLayoutFromStorage()

View File

@@ -83,12 +83,12 @@ else if (!string.IsNullOrWhiteSpace(infoMessage))
}
else if (items.Count == 0)
{
<p>Keine Einträge vorhanden.</p>
<p>Keine Eintr&#228;ge vorhanden.</p>
}
else
{
<div class="mb-3 page-size-selector">
<span class="page-size-label">Datensätze je Seite:</span>
<span class="page-size-label">Datens&#228;tze je Seite:</span>
<DxComboBox Data="@pageSizeOptions"
TData="PageSizeOption"
TValue="int?"
@@ -101,9 +101,9 @@ else
<div class="band-editor">
<div class="band-controls">
<DxButton Text="Band hinzufügen" Click="AddBand" />
<DxButton Text="Band hinzuf&#252;gen" Click="AddBand" />
<DxButton Text="Layout speichern" Click="SaveLayoutAsync" Enabled="@CanSaveBandLayout" />
<DxButton Text="Band-Layout zurücksetzen" Click="ResetBandLayoutAsync" />
<DxButton Text="Band-Layout zur&#252;cksetzen" Click="ResetBandLayoutAsync" />
</div>
@foreach (var band in bandLayout.Bands)
{
@@ -133,6 +133,7 @@ else
<DxGrid Data="@items"
TItem="MassDataReadDto"
KeyFieldName="@nameof(MassDataReadDto.Id)"
SizeMode="@_sizeMode"
ShowGroupPanel="true"
ShowGroupedColumns="true"
AllowGroup="true"
@@ -151,6 +152,25 @@ else
FocusedRowEnabled="true"
@bind-FocusedRowKey="focusedRowKey"
@ref="gridRef">
<ToolbarTemplate>
<DxToolbar>
<DxToolbarItem Alignment="ToolbarItemAlignment.Right">
<Template Context="_">
<DxDropDownButton Text="@FormatSizeText(_sizeMode)"
RenderStyle="ButtonRenderStyle.Secondary"
RenderStyleMode="ButtonRenderStyleMode.Text"
ItemClick="OnSizeChange">
<Items>
@foreach (var size in _sizeModes)
{
<DxDropDownButtonItem Text="@FormatSizeText(size)" Id="@size.ToString()" />
}
</Items>
</DxDropDownButton>
</Template>
</DxToolbarItem>
</DxToolbar>
</ToolbarTemplate>
<Columns>
@RenderColumns()
</Columns>
@@ -249,6 +269,23 @@ else
private bool gridLayoutApplied;
private DevExpress.Blazor.SizeMode _sizeMode = DevExpress.Blazor.SizeMode.Medium;
private static readonly List<DevExpress.Blazor.SizeMode> _sizeModes =
Enum.GetValues<DevExpress.Blazor.SizeMode>().ToList();
private string FormatSizeText(DevExpress.Blazor.SizeMode size) => size switch
{
DevExpress.Blazor.SizeMode.Small => "Klein",
DevExpress.Blazor.SizeMode.Medium => "Mittel",
DevExpress.Blazor.SizeMode.Large => "Groß",
_ => size.ToString()
};
private void OnSizeChange(DropDownButtonItemClickEventArgs args)
{
_sizeMode = Enum.Parse<DevExpress.Blazor.SizeMode>(args.ItemInfo.Id);
}
protected override async Task OnInitializedAsync()
{
columnLookup = columnDefinitions.ToDictionary(column => column.FieldName, StringComparer.OrdinalIgnoreCase);
@@ -392,7 +429,7 @@ else
bandLayout = new BandLayout();
columnBandAssignments.Clear();
UpdateBandOptions();
infoMessage = "Band-Layout zurückgesetzt.";
infoMessage = "Band-Layout zur&#252;ckgesetzt.";
}
private void ApplyColumnLayoutFromStorage()
@@ -653,7 +690,7 @@ else
var editModel = (MassDataEditModel)e.EditModel;
if (!decimal.TryParse(editModel.AmountText, out var amount))
{
AddValidationError(editModel, nameof(MassDataEditModel.AmountText), "Amount ist ungültig.");
AddValidationError(editModel, nameof(MassDataEditModel.AmountText), "Amount ist ung&#252;ltig.");
e.Cancel = true;
return;
}
@@ -706,11 +743,21 @@ else
private Task OnDataItemDeleting(GridDataItemDeletingEventArgs e)
{
errorMessage = null;
infoMessage = "Löschen ist aktuell noch nicht verfügbar.";
infoMessage = "L&#246;schen ist aktuell noch nicht verf&#252;gbar.";
e.Cancel = true;
return Task.CompletedTask;
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (!gridLayoutApplied && gridRef != null && bandLayout.GridLayout != null)
{
gridRef.LoadLayout(bandLayout.GridLayout);
gridLayoutApplied = true;
await InvokeAsync(StateHasChanged);
}
}
private sealed class BandLayout
{
public List<BandDefinition> Bands { get; set; } = new();
@@ -784,14 +831,4 @@ else
public string Value { get; set; } = string.Empty;
public string Text { get; set; } = string.Empty;
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (!gridLayoutApplied && gridRef != null && bandLayout.GridLayout != null)
{
gridRef.LoadLayout(bandLayout.GridLayout);
gridLayoutApplied = true;
await InvokeAsync(StateHasChanged);
}
}
}

View File

@@ -1,5 +1,10 @@
:root {
--global-size: 16px;
}
html, body {
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: var(--global-size);
}
.app-dark {

View File

@@ -0,0 +1,3 @@
window.setSize = function (fontSize) {
document.documentElement.style.setProperty('--global-size', fontSize);
};