386 lines
18 KiB
Plaintext
386 lines
18 KiB
Plaintext
@using DevExpress.Blazor
|
|
@using Microsoft.AspNetCore.Components.Rendering
|
|
@using System.Reflection
|
|
|
|
<div @ref="_panelElement" class="mg-grid-info-panel @(_isEditMode ? "edit-mode" : "") @GetColumnCountClass()">
|
|
@* Header *@
|
|
@if (HeaderTemplate != null)
|
|
{
|
|
@HeaderTemplate(CreateContext())
|
|
}
|
|
else if (_currentGrid != null)
|
|
{
|
|
<div class="mg-info-panel-header">@_currentGrid.Caption</div>
|
|
}
|
|
|
|
@* Toolbar *@
|
|
@if (_currentGrid != null)
|
|
{
|
|
<div class="mg-info-panel-toolbar">
|
|
<MgGridToolbarTemplate Grid="_currentGrid" OnlyGridEditTools="true" ShowOnlyIcon="true" />
|
|
</div>
|
|
}
|
|
|
|
@* Content *@
|
|
<div class="mg-info-panel-content">
|
|
@if (GetActiveDataItem() != null && _currentGrid != null)
|
|
{
|
|
@if (BeforeColumnsTemplate != null)
|
|
{
|
|
@BeforeColumnsTemplate(CreateContext())
|
|
}
|
|
|
|
@if (ColumnsTemplate != null)
|
|
{
|
|
@ColumnsTemplate(CreateContext())
|
|
}
|
|
else
|
|
{
|
|
@RenderDefaultColumns()
|
|
}
|
|
|
|
@if (AfterColumnsTemplate != null)
|
|
{
|
|
@AfterColumnsTemplate(CreateContext())
|
|
}
|
|
}
|
|
else
|
|
{
|
|
<div class="mg-info-panel-empty">
|
|
<p>Válasszon ki egy sort az adatok megtekintéséhez</p>
|
|
</div>
|
|
}
|
|
</div>
|
|
|
|
@* Footer *@
|
|
@if (FooterTemplate != null)
|
|
{
|
|
@FooterTemplate(CreateContext())
|
|
}
|
|
</div>
|
|
|
|
@code {
|
|
[Parameter] public RenderFragment<InfoPanelContext>? HeaderTemplate { get; set; }
|
|
[Parameter] public RenderFragment<InfoPanelContext>? BeforeColumnsTemplate { get; set; }
|
|
[Parameter] public RenderFragment<InfoPanelContext>? ColumnsTemplate { get; set; }
|
|
[Parameter] public RenderFragment<InfoPanelContext>? AfterColumnsTemplate { get; set; }
|
|
[Parameter] public RenderFragment<InfoPanelContext>? FooterTemplate { get; set; }
|
|
|
|
/// <summary>
|
|
/// Called when the data item changes (row selection changed)
|
|
/// </summary>
|
|
[Parameter] public EventCallback<object?> OnDataItemChanged { get; set; }
|
|
|
|
private InfoPanelContext CreateContext() => new(GetActiveDataItem(), _isEditMode);
|
|
|
|
private string GetColumnCountClass() => FixedColumnCount switch
|
|
{
|
|
1 => "mg-columns-1",
|
|
2 => "mg-columns-2",
|
|
3 => "mg-columns-3",
|
|
4 => "mg-columns-4",
|
|
_ => ""
|
|
};
|
|
|
|
private RenderFragment RenderDefaultColumns() => builder =>
|
|
{
|
|
var dataItem = GetActiveDataItem();
|
|
if (dataItem == null) return;
|
|
|
|
var dataItemType = dataItem.GetType();
|
|
var seq = 0;
|
|
|
|
builder.OpenElement(seq++, "div");
|
|
builder.AddAttribute(seq++, "class", "mg-info-panel-grid");
|
|
|
|
foreach (var column in GetVisibleColumns())
|
|
{
|
|
var displayText = GetDisplayTextFromGrid(column);
|
|
var value = GetCellValue(column);
|
|
var settingsType = GetEditSettingsType(column);
|
|
var isEditable = _isEditMode && !column.ReadOnly;
|
|
|
|
builder.OpenElement(seq++, "div");
|
|
builder.AddAttribute(seq++, "class", "mg-info-panel-item");
|
|
|
|
builder.OpenElement(seq++, "label");
|
|
builder.AddAttribute(seq++, "class", isEditable ? "mg-info-panel-label editable" : "mg-info-panel-label");
|
|
builder.AddContent(seq++, GetColumnCaption(column));
|
|
builder.CloseElement();
|
|
|
|
builder.OpenElement(seq++, "div");
|
|
if (isEditable)
|
|
{
|
|
RenderEditableCell(column, dataItem, dataItemType, value, displayText, settingsType)(builder);
|
|
}
|
|
else
|
|
{
|
|
RenderCellContent(value, displayText)(builder);
|
|
}
|
|
builder.CloseElement();
|
|
|
|
builder.CloseElement();
|
|
}
|
|
|
|
builder.CloseElement();
|
|
};
|
|
|
|
private static string GetColumnCaption(DxGridDataColumn column) =>
|
|
!string.IsNullOrWhiteSpace(column.Caption) ? column.Caption : column.FieldName;
|
|
|
|
private RenderFragment RenderEditableCell(DxGridDataColumn column, object dataItem, Type dataItemType, object? value, string displayText, EditSettingsType settingsType)
|
|
{
|
|
return builder =>
|
|
{
|
|
var seq = 0;
|
|
var propertyInfo = dataItemType.GetProperty(column.FieldName);
|
|
|
|
if (propertyInfo == null)
|
|
{
|
|
RenderCellContent(value, displayText)(builder);
|
|
return;
|
|
}
|
|
|
|
var underlyingType = Nullable.GetUnderlyingType(propertyInfo.PropertyType) ?? propertyInfo.PropertyType;
|
|
|
|
if (settingsType == EditSettingsType.ComboBox && GetEditSettingsCached(dataItemType, column.FieldName) is DxComboBoxSettings comboSettings)
|
|
{
|
|
RenderComboBoxEditor(builder, ref seq, dataItem, propertyInfo, comboSettings);
|
|
return;
|
|
}
|
|
|
|
if (underlyingType == typeof(bool)) RenderCheckBoxEditor(builder, ref seq, dataItem, propertyInfo);
|
|
else if (underlyingType == typeof(DateTime)) RenderDateTimeEditor(builder, ref seq, dataItem, propertyInfo, column.DisplayFormat);
|
|
else if (underlyingType == typeof(DateOnly)) RenderDateOnlyEditor(builder, ref seq, dataItem, propertyInfo, column.DisplayFormat);
|
|
else if (underlyingType == typeof(int)) RenderSpinIntEditor(builder, ref seq, dataItem, propertyInfo);
|
|
else if (underlyingType == typeof(decimal)) RenderSpinDecimalEditor(builder, ref seq, dataItem, propertyInfo);
|
|
else if (underlyingType == typeof(double)) RenderSpinDoubleEditor(builder, ref seq, dataItem, propertyInfo);
|
|
else if (settingsType == EditSettingsType.Memo) RenderMemoEditor(builder, ref seq, dataItem, propertyInfo);
|
|
else RenderTextBoxEditor(builder, ref seq, dataItem, propertyInfo);
|
|
};
|
|
}
|
|
|
|
private void RenderCheckBoxEditor(RenderTreeBuilder builder, ref int seq, object dataItem, PropertyInfo propertyInfo)
|
|
{
|
|
builder.OpenComponent<DxCheckBox<bool>>(seq++);
|
|
builder.AddAttribute(seq++, "Checked", (bool)(propertyInfo.GetValue(dataItem) ?? false));
|
|
builder.AddAttribute(seq++, "CheckedChanged", EventCallback.Factory.Create<bool>(this, v => { propertyInfo.SetValue(dataItem, v); InvokeAsync(StateHasChanged); }));
|
|
builder.CloseComponent();
|
|
}
|
|
|
|
private void RenderDateTimeEditor(RenderTreeBuilder builder, ref int seq, object dataItem, PropertyInfo propertyInfo, string? displayFormat)
|
|
{
|
|
var isNullable = Nullable.GetUnderlyingType(propertyInfo.PropertyType) != null;
|
|
var value = propertyInfo.GetValue(dataItem);
|
|
|
|
if (isNullable)
|
|
{
|
|
builder.OpenComponent<DxDateEdit<DateTime?>>(seq++);
|
|
builder.AddAttribute(seq++, "Date", (DateTime?)value);
|
|
builder.AddAttribute(seq++, "DateChanged", EventCallback.Factory.Create<DateTime?>(this, v => { propertyInfo.SetValue(dataItem, v); InvokeAsync(StateHasChanged); }));
|
|
}
|
|
else
|
|
{
|
|
builder.OpenComponent<DxDateEdit<DateTime>>(seq++);
|
|
builder.AddAttribute(seq++, "Date", (DateTime)(value ?? DateTime.MinValue));
|
|
builder.AddAttribute(seq++, "DateChanged", EventCallback.Factory.Create<DateTime>(this, v => { propertyInfo.SetValue(dataItem, v); InvokeAsync(StateHasChanged); }));
|
|
}
|
|
builder.AddAttribute(seq++, "DisplayFormat", displayFormat ?? "yyyy-MM-dd HH:mm");
|
|
builder.CloseComponent();
|
|
}
|
|
|
|
private void RenderDateOnlyEditor(RenderTreeBuilder builder, ref int seq, object dataItem, PropertyInfo propertyInfo, string? displayFormat)
|
|
{
|
|
var isNullable = Nullable.GetUnderlyingType(propertyInfo.PropertyType) != null;
|
|
var value = propertyInfo.GetValue(dataItem);
|
|
|
|
if (isNullable)
|
|
{
|
|
builder.OpenComponent<DxDateEdit<DateOnly?>>(seq++);
|
|
builder.AddAttribute(seq++, "Date", (DateOnly?)value);
|
|
builder.AddAttribute(seq++, "DateChanged", EventCallback.Factory.Create<DateOnly?>(this, v => { propertyInfo.SetValue(dataItem, v); InvokeAsync(StateHasChanged); }));
|
|
}
|
|
else
|
|
{
|
|
builder.OpenComponent<DxDateEdit<DateOnly>>(seq++);
|
|
builder.AddAttribute(seq++, "Date", (DateOnly)(value ?? DateOnly.MinValue));
|
|
builder.AddAttribute(seq++, "DateChanged", EventCallback.Factory.Create<DateOnly>(this, v => { propertyInfo.SetValue(dataItem, v); InvokeAsync(StateHasChanged); }));
|
|
}
|
|
builder.AddAttribute(seq++, "DisplayFormat", displayFormat ?? "yyyy-MM-dd");
|
|
builder.CloseComponent();
|
|
}
|
|
|
|
private void RenderSpinIntEditor(RenderTreeBuilder builder, ref int seq, object dataItem, PropertyInfo propertyInfo)
|
|
{
|
|
var isNullable = Nullable.GetUnderlyingType(propertyInfo.PropertyType) != null;
|
|
var value = propertyInfo.GetValue(dataItem);
|
|
|
|
if (isNullable)
|
|
{
|
|
builder.OpenComponent<DxSpinEdit<int?>>(seq++);
|
|
builder.AddAttribute(seq++, "Value", (int?)value);
|
|
builder.AddAttribute(seq++, "ValueChanged", EventCallback.Factory.Create<int?>(this, v => { propertyInfo.SetValue(dataItem, v); InvokeAsync(StateHasChanged); }));
|
|
}
|
|
else
|
|
{
|
|
builder.OpenComponent<DxSpinEdit<int>>(seq++);
|
|
builder.AddAttribute(seq++, "Value", (int)(value ?? 0));
|
|
builder.AddAttribute(seq++, "ValueChanged", EventCallback.Factory.Create<int>(this, v => { propertyInfo.SetValue(dataItem, v); InvokeAsync(StateHasChanged); }));
|
|
}
|
|
builder.CloseComponent();
|
|
}
|
|
|
|
private void RenderSpinDecimalEditor(RenderTreeBuilder builder, ref int seq, object dataItem, PropertyInfo propertyInfo)
|
|
{
|
|
var isNullable = Nullable.GetUnderlyingType(propertyInfo.PropertyType) != null;
|
|
var value = propertyInfo.GetValue(dataItem);
|
|
|
|
if (isNullable)
|
|
{
|
|
builder.OpenComponent<DxSpinEdit<decimal?>>(seq++);
|
|
builder.AddAttribute(seq++, "Value", (decimal?)value);
|
|
builder.AddAttribute(seq++, "ValueChanged", EventCallback.Factory.Create<decimal?>(this, v => { propertyInfo.SetValue(dataItem, v); InvokeAsync(StateHasChanged); }));
|
|
}
|
|
else
|
|
{
|
|
builder.OpenComponent<DxSpinEdit<decimal>>(seq++);
|
|
builder.AddAttribute(seq++, "Value", (decimal)(value ?? 0m));
|
|
builder.AddAttribute(seq++, "ValueChanged", EventCallback.Factory.Create<decimal>(this, v => { propertyInfo.SetValue(dataItem, v); InvokeAsync(StateHasChanged); }));
|
|
}
|
|
builder.CloseComponent();
|
|
}
|
|
|
|
private void RenderSpinDoubleEditor(RenderTreeBuilder builder, ref int seq, object dataItem, PropertyInfo propertyInfo)
|
|
{
|
|
var isNullable = Nullable.GetUnderlyingType(propertyInfo.PropertyType) != null;
|
|
var value = propertyInfo.GetValue(dataItem);
|
|
|
|
if (isNullable)
|
|
{
|
|
builder.OpenComponent<DxSpinEdit<double?>>(seq++);
|
|
builder.AddAttribute(seq++, "Value", (double?)value);
|
|
builder.AddAttribute(seq++, "ValueChanged", EventCallback.Factory.Create<double?>(this, v => { propertyInfo.SetValue(dataItem, v); InvokeAsync(StateHasChanged); }));
|
|
}
|
|
else
|
|
{
|
|
builder.OpenComponent<DxSpinEdit<double>>(seq++);
|
|
builder.AddAttribute(seq++, "Value", (double)(value ?? 0d));
|
|
builder.AddAttribute(seq++, "ValueChanged", EventCallback.Factory.Create<double>(this, v => { propertyInfo.SetValue(dataItem, v); InvokeAsync(StateHasChanged); }));
|
|
}
|
|
builder.CloseComponent();
|
|
}
|
|
|
|
private void RenderTextBoxEditor(RenderTreeBuilder builder, ref int seq, object dataItem, PropertyInfo propertyInfo)
|
|
{
|
|
builder.OpenComponent<DxTextBox>(seq++);
|
|
builder.AddAttribute(seq++, "Text", propertyInfo.GetValue(dataItem)?.ToString() ?? "");
|
|
builder.AddAttribute(seq++, "TextChanged", EventCallback.Factory.Create<string>(this, v => { propertyInfo.SetValue(dataItem, v); InvokeAsync(StateHasChanged); }));
|
|
builder.CloseComponent();
|
|
}
|
|
|
|
private void RenderMemoEditor(RenderTreeBuilder builder, ref int seq, object dataItem, PropertyInfo propertyInfo)
|
|
{
|
|
builder.OpenComponent<DxMemo>(seq++);
|
|
builder.AddAttribute(seq++, "Text", propertyInfo.GetValue(dataItem)?.ToString() ?? "");
|
|
builder.AddAttribute(seq++, "TextChanged", EventCallback.Factory.Create<string>(this, v => { propertyInfo.SetValue(dataItem, v); InvokeAsync(StateHasChanged); }));
|
|
builder.AddAttribute(seq++, "Rows", 3);
|
|
builder.CloseComponent();
|
|
}
|
|
|
|
private void RenderComboBoxEditor(RenderTreeBuilder builder, ref int seq, object dataItem, PropertyInfo propertyInfo, DxComboBoxSettings settings)
|
|
{
|
|
var value = propertyInfo.GetValue(dataItem);
|
|
var underlyingType = Nullable.GetUnderlyingType(propertyInfo.PropertyType) ?? propertyInfo.PropertyType;
|
|
var itemType = settings.Data?.GetType().GetGenericArguments().FirstOrDefault() ?? typeof(object);
|
|
|
|
if (underlyingType == typeof(int))
|
|
RenderComboBoxInt(builder, ref seq, dataItem, propertyInfo, settings, itemType, value);
|
|
else if (underlyingType == typeof(long))
|
|
RenderComboBoxLong(builder, ref seq, dataItem, propertyInfo, settings, itemType, value);
|
|
else if (underlyingType == typeof(Guid))
|
|
RenderComboBoxGuid(builder, ref seq, dataItem, propertyInfo, settings, itemType, value);
|
|
else
|
|
{
|
|
builder.OpenComponent<DxTextBox>(seq++);
|
|
builder.AddAttribute(seq++, "Text", ResolveComboBoxDisplayText(settings, value ?? new object()) ?? value?.ToString() ?? "");
|
|
builder.AddAttribute(seq++, "ReadOnly", true);
|
|
builder.CloseComponent();
|
|
}
|
|
}
|
|
|
|
private void RenderComboBoxInt(RenderTreeBuilder builder, ref int seq, object dataItem, PropertyInfo propertyInfo, DxComboBoxSettings settings, Type itemType, object? currentValue)
|
|
{
|
|
var isNullable = Nullable.GetUnderlyingType(propertyInfo.PropertyType) != null;
|
|
var comboType = isNullable ? typeof(DxComboBox<,>).MakeGenericType(itemType, typeof(int?)) : typeof(DxComboBox<,>).MakeGenericType(itemType, typeof(int));
|
|
|
|
builder.OpenComponent(seq++, comboType);
|
|
builder.AddAttribute(seq++, "Data", settings.Data);
|
|
builder.AddAttribute(seq++, "ValueFieldName", settings.ValueFieldName);
|
|
builder.AddAttribute(seq++, "TextFieldName", settings.TextFieldName);
|
|
builder.AddAttribute(seq++, "Value", isNullable ? currentValue as int? : (currentValue is int intVal ? intVal : 0));
|
|
builder.AddAttribute(seq++, "ValueChanged", isNullable
|
|
? EventCallback.Factory.Create<int?>(this, v => { propertyInfo.SetValue(dataItem, v); StateHasChanged(); })
|
|
: EventCallback.Factory.Create<int>(this, v => { propertyInfo.SetValue(dataItem, v); StateHasChanged(); }));
|
|
builder.AddAttribute(seq++, "ClearButtonDisplayMode", DataEditorClearButtonDisplayMode.Auto);
|
|
builder.CloseComponent();
|
|
}
|
|
|
|
private void RenderComboBoxLong(RenderTreeBuilder builder, ref int seq, object dataItem, PropertyInfo propertyInfo, DxComboBoxSettings settings, Type itemType, object? currentValue)
|
|
{
|
|
var isNullable = Nullable.GetUnderlyingType(propertyInfo.PropertyType) != null;
|
|
var comboType = isNullable ? typeof(DxComboBox<,>).MakeGenericType(itemType, typeof(long?)) : typeof(DxComboBox<,>).MakeGenericType(itemType, typeof(long));
|
|
|
|
builder.OpenComponent(seq++, comboType);
|
|
builder.AddAttribute(seq++, "Data", settings.Data);
|
|
builder.AddAttribute(seq++, "ValueFieldName", settings.ValueFieldName);
|
|
builder.AddAttribute(seq++, "TextFieldName", settings.TextFieldName);
|
|
builder.AddAttribute(seq++, "Value", isNullable ? currentValue as long? : (currentValue is long longVal ? longVal : 0L));
|
|
builder.AddAttribute(seq++, "ValueChanged", isNullable
|
|
? EventCallback.Factory.Create<long?>(this, v => { propertyInfo.SetValue(dataItem, v); StateHasChanged(); })
|
|
: EventCallback.Factory.Create<long>(this, v => { propertyInfo.SetValue(dataItem, v); StateHasChanged(); }));
|
|
builder.AddAttribute(seq++, "ClearButtonDisplayMode", DataEditorClearButtonDisplayMode.Auto);
|
|
builder.CloseComponent();
|
|
}
|
|
|
|
private void RenderComboBoxGuid(RenderTreeBuilder builder, ref int seq, object dataItem, PropertyInfo propertyInfo, DxComboBoxSettings settings, Type itemType, object? currentValue)
|
|
{
|
|
var isNullable = Nullable.GetUnderlyingType(propertyInfo.PropertyType) != null;
|
|
var comboType = isNullable ? typeof(DxComboBox<,>).MakeGenericType(itemType, typeof(Guid?)) : typeof(DxComboBox<,>).MakeGenericType(itemType, typeof(Guid));
|
|
|
|
builder.OpenComponent(seq++, comboType);
|
|
builder.AddAttribute(seq++, "Data", settings.Data);
|
|
builder.AddAttribute(seq++, "ValueFieldName", settings.ValueFieldName);
|
|
builder.AddAttribute(seq++, "TextFieldName", settings.TextFieldName);
|
|
builder.AddAttribute(seq++, "Value", isNullable ? currentValue as Guid? : (currentValue is Guid guidVal ? guidVal : Guid.Empty));
|
|
builder.AddAttribute(seq++, "ValueChanged", isNullable
|
|
? EventCallback.Factory.Create<Guid?>(this, v => { propertyInfo.SetValue(dataItem, v); StateHasChanged(); })
|
|
: EventCallback.Factory.Create<Guid>(this, v => { propertyInfo.SetValue(dataItem, v); StateHasChanged(); }));
|
|
builder.AddAttribute(seq++, "ClearButtonDisplayMode", DataEditorClearButtonDisplayMode.Auto);
|
|
builder.CloseComponent();
|
|
}
|
|
|
|
private RenderFragment RenderCellContent(object? value, string displayText)
|
|
{
|
|
return builder =>
|
|
{
|
|
var seq = 0;
|
|
builder.OpenElement(seq++, "span");
|
|
builder.AddAttribute(seq++, "class", "mg-info-panel-value");
|
|
builder.AddAttribute(seq++, "title", displayText);
|
|
|
|
if (value is bool boolValue)
|
|
{
|
|
builder.OpenElement(seq++, "span");
|
|
builder.AddAttribute(seq++, "class", boolValue ? "dx-icon dx-icon-check" : "dx-icon dx-icon-close");
|
|
builder.CloseElement();
|
|
}
|
|
else
|
|
{
|
|
builder.AddContent(seq++, displayText);
|
|
}
|
|
|
|
builder.CloseElement();
|
|
};
|
|
}
|
|
}
|