Files
SQLVision/SQLVision.UI/Controls/ControlFactory.cs
2026-01-05 00:37:54 +03:00

397 lines
13 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Microsoft.UI;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media;
using SQLVision.Core.Enums;
using SQLVision.Core.Interfaces;
using SQLVision.Core.Models;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
namespace SQLVision.UI.Controls;
public class ControlFactory : IControlFactory
{
private readonly IServiceProvider _serviceProvider;
private readonly ILogger<ControlFactory> _logger;
public ControlFactory(IServiceProvider serviceProvider, ILogger<ControlFactory> logger)
{
_serviceProvider = serviceProvider;
_logger = logger;
}
public FrameworkElement CreateControl(ScriptParameter parameter, Action<object> onValueChanged)
{
try
{
var control = parameter.Type switch
{
ParameterType.String => CreateTextBox(parameter, onValueChanged),
ParameterType.Int => CreateNumberBox(parameter, onValueChanged),
ParameterType.Decimal => CreateNumberBox(parameter, onValueChanged, true),
ParameterType.DateTime => CreateDatePicker(parameter, onValueChanged),
ParameterType.Bool => CreateCheckBox(parameter, onValueChanged),
ParameterType.Table => CreateComboBox(parameter, onValueChanged),
ParameterType.MultiSelect => CreateListBox(parameter, onValueChanged),
ParameterType.Color => CreateColorPicker(parameter, onValueChanged),
ParameterType.File => CreateFilePicker(parameter, onValueChanged),
ParameterType.Json => CreateJsonEditor(parameter, onValueChanged),
_ => CreateTextBox(parameter, onValueChanged)
};
// Настройка общих свойств
control.Tag = parameter;
control.IsEnabled = !parameter.IsRequired || parameter.DefaultValue == null;
// Добавление подсказки
if (!string.IsNullOrEmpty(parameter.Description))
{
ToolTipService.SetToolTip(control, parameter.Description);
}
return control;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error creating control for parameter {Parameter}", parameter.Name);
return CreateFallbackControl(parameter, onValueChanged);
}
}
private FrameworkElement CreateTextBox(ScriptParameter parameter, Action<object> onValueChanged)
{
var textBox = new TextBox
{
Header = parameter.DisplayName,
PlaceholderText = parameter.Watermark ?? $"Введите {parameter.DisplayName.ToLower()}",
Text = parameter.DefaultValue?.ToString() ?? string.Empty
};
textBox.TextChanged += (s, e) => onValueChanged(textBox.Text);
return textBox;
}
private FrameworkElement CreateNumberBox(ScriptParameter parameter, Action<object> onValueChanged, bool isDecimal = false)
{
var numberBox = new NumberBox
{
Header = parameter.DisplayName,
PlaceholderText = parameter.Watermark ?? $"Введите {parameter.DisplayName.ToLower()}",
SmallChange = isDecimal ? 0.1 : 1,
LargeChange = isDecimal ? 1 : 10,
SpinButtonPlacementMode = NumberBoxSpinButtonPlacementMode.Inline,
AcceptsExpression = false
};
if (isDecimal)
{
numberBox.Value = Convert.ToDouble(parameter.DefaultValue ?? 0);
numberBox.ValueChanged += (s, e) => onValueChanged(e.NewValue);
}
else
{
numberBox.Value = Convert.ToInt32(parameter.DefaultValue ?? 0);
numberBox.ValueChanged += (s, e) => onValueChanged((int)e.NewValue);
}
// Применение правил валидации
if (parameter.ValidationRules != null)
{
if (parameter.ValidationRules.TryGetValue("min", out var min))
numberBox.Minimum = Convert.ToDouble(min);
if (parameter.ValidationRules.TryGetValue("max", out var max))
numberBox.Maximum = Convert.ToDouble(max);
}
return numberBox;
}
private FrameworkElement CreateDatePicker(ScriptParameter parameter, Action<object> onValueChanged)
{
var datePicker = new DatePicker
{
Header = parameter.DisplayName,
Date = parameter.DefaultValue is DateTime defaultDate ?
DateTimeOffset.Parse(defaultDate.ToString()) : DateTimeOffset.Now
};
datePicker.DateChanged += (s, e) => onValueChanged(e.NewDate.DateTime);
return datePicker;
}
private FrameworkElement CreateCheckBox(ScriptParameter parameter, Action<object> onValueChanged)
{
var checkBox = new CheckBox
{
Content = parameter.DisplayName,
IsChecked = parameter.DefaultValue is bool defaultBool ? defaultBool : false
};
checkBox.Checked += (s, e) => onValueChanged(true);
checkBox.Unchecked += (s, e) => onValueChanged(false);
return checkBox;
}
private FrameworkElement CreateComboBox(ScriptParameter parameter, Action<object> onValueChanged)
{
var comboBox = new ComboBox
{
Header = parameter.DisplayName,
PlaceholderText = parameter.Watermark ?? $"Выберите {parameter.DisplayName.ToLower()}",
DisplayMemberPath = parameter.DisplayMember,
SelectedValuePath = parameter.ValueMember
};
// Загрузка данных асинхронно
LoadComboBoxDataAsync(comboBox, parameter).ConfigureAwait(false);
comboBox.SelectionChanged += (s, e) =>
{
if (comboBox.SelectedValue != null)
onValueChanged(comboBox.SelectedValue);
};
return comboBox;
}
private async Task LoadComboBoxDataAsync(ComboBox comboBox, ScriptParameter parameter)
{
if (string.IsNullOrEmpty(parameter.TableQuery)) return;
try
{
// Используем сервис выполнения SQL для загрузки данных
var executionService = _serviceProvider.GetService<ISqlExecutionService>();
var result = await executionService.ExecuteAsync(
parameter.TableQuery,
new Dictionary<string, object>(),
GetConnectionString());
if (result.IsSuccess && result.Data.Tables.Count > 0)
{
comboBox.ItemsSource = result.Data.Tables[0].DefaultView;
// Установка значения по умолчанию
if (parameter.DefaultValue != null)
{
comboBox.SelectedValue = parameter.DefaultValue;
}
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error loading combo box data for {Parameter}", parameter.Name);
}
}
private FrameworkElement CreateListBox(ScriptParameter parameter, Action<object> onValueChanged)
{
var listBox = new ListBox
{
Header = parameter.DisplayName,
SelectionMode = ListViewSelectionMode.Multiple
};
// Загрузка данных для ListBox
// Аналогично ComboBox
listBox.SelectionChanged += (s, e) =>
{
var selectedValues = listBox.SelectedItems.Cast<DataRowView>()
.Select(r => r[parameter.ValueMember])
.ToList();
onValueChanged(selectedValues);
};
return listBox;
}
private FrameworkElement CreateColorPicker(ScriptParameter parameter, Action<object> onValueChanged)
{
var colorPicker = new ColorPicker
{
Header = parameter.DisplayName,
ColorSpectrumShape = ColorSpectrumShape.Box,
IsMoreButtonVisible = true,
IsColorSliderVisible = true,
IsColorChannelTextInputVisible = true,
IsHexInputVisible = true
};
if (parameter.DefaultValue is string defaultColor)
{
if (ColorHelper.TryParse(defaultColor, out var color))
{
colorPicker.Color = color;
}
}
colorPicker.ColorChanged += (s, e) =>
onValueChanged($"#{e.NewColor.R:X2}{e.NewColor.G:X2}{e.NewColor.B:X2}");
return colorPicker;
}
private FrameworkElement CreateFilePicker(ScriptParameter parameter, Action<object> onValueChanged)
{
var stackPanel = new StackPanel { Orientation = Orientation.Horizontal, Spacing = 8 };
var textBox = new TextBox
{
Header = parameter.DisplayName,
PlaceholderText = "Путь к файлу",
Width = 200,
IsReadOnly = true
};
var button = new Button
{
Content = "Выбрать",
VerticalAlignment = VerticalAlignment.Bottom
};
button.Click += async (s, e) =>
{
var openPicker = new FileOpenPicker();
openPicker.ViewMode = PickerViewMode.List;
openPicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
if (parameter.ValidationRules != null &&
parameter.ValidationRules.TryGetValue("extensions", out var extensions))
{
foreach (var ext in extensions.ToString().Split(','))
{
openPicker.FileTypeFilter.Add(ext.Trim());
}
}
else
{
openPicker.FileTypeFilter.Add("*");
}
var file = await openPicker.PickSingleFileAsync();
if (file != null)
{
textBox.Text = file.Path;
onValueChanged(file.Path);
}
};
stackPanel.Children.Add(textBox);
stackPanel.Children.Add(button);
return stackPanel;
}
private FrameworkElement CreateJsonEditor(ScriptParameter parameter, Action<object> onValueChanged)
{
var textBox = new TextBox
{
Header = parameter.DisplayName,
PlaceholderText = "Введите JSON",
AcceptsReturn = true,
TextWrapping = TextWrapping.Wrap,
Height = 100,
FontFamily = new FontFamily("Consolas")
};
if (parameter.DefaultValue != null)
{
textBox.Text = JsonSerializer.Serialize(parameter.DefaultValue,
new JsonSerializerOptions { WriteIndented = true });
}
textBox.TextChanged += (s, e) =>
{
try
{
var json = JsonSerializer.Deserialize<JsonElement>(textBox.Text);
onValueChanged(json);
}
catch
{
// Игнорируем ошибки парсинга JSON
}
};
return textBox;
}
private FrameworkElement CreateFallbackControl(ScriptParameter parameter, Action<object> onValueChanged)
{
return new TextBox
{
Header = parameter.DisplayName,
Text = $"Ошибка создания контрола для типа {parameter.Type}",
IsReadOnly = true,
Foreground = new SolidColorBrush(Colors.Red)
};
}
public void UpdateControlState(FrameworkElement control, ScriptParameter parameter, Dictionary<string, object> currentValues)
{
// Обновление состояния контрола на основе зависимостей
if (!string.IsNullOrEmpty(parameter.DependsOn))
{
var isEnabled = CheckDependency(parameter, currentValues);
control.IsEnabled = isEnabled;
if (!isEnabled)
{
// Сброс значения, если контрол отключен
ResetControlValue(control);
}
}
}
private bool CheckDependency(ScriptParameter parameter, Dictionary<string, object> currentValues)
{
if (!currentValues.TryGetValue(parameter.DependsOn, out var dependencyValue))
return false;
if (parameter.DependencyValues != null)
{
return parameter.DependencyValues
.Any(kvp => object.Equals(kvp.Value, dependencyValue));
}
return dependencyValue != null && !string.IsNullOrWhiteSpace(dependencyValue.ToString());
}
private void ResetControlValue(FrameworkElement control)
{
switch (control)
{
case TextBox textBox:
textBox.Text = string.Empty;
break;
case ComboBox comboBox:
comboBox.SelectedIndex = -1;
break;
case CheckBox checkBox:
checkBox.IsChecked = false;
break;
case DatePicker datePicker:
datePicker.Date = DateTimeOffset.Now;
break;
}
}
private string GetConnectionString()
{
// Получение строки подключения из конфигурации
var configuration = _serviceProvider.GetService<IConfiguration>();
return configuration.GetConnectionString("Default") ??
configuration["Database:DefaultConnection"];
}
}