Рефакторинг
This commit is contained in:
@@ -57,7 +57,7 @@
|
|||||||
Spacing="2">
|
Spacing="2">
|
||||||
<TextBlock Foreground="#C62828"
|
<TextBlock Foreground="#C62828"
|
||||||
Text="{Binding AddVariableError}"
|
Text="{Binding AddVariableError}"
|
||||||
IsVisible="{Binding AddVariableError, Converter={x:Static StringConverters.IsNotNullOrEmpty}}" />
|
IsVisible="{Binding HasAddVariableError}" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
<Border Grid.Row="3"
|
<Border Grid.Row="3"
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System.ComponentModel;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Sms.TaskTwo.ViewModels;
|
using Sms.TaskTwo.ViewModels;
|
||||||
|
|
||||||
@@ -5,8 +6,6 @@ namespace Sms.TaskTwo.Avalonia.Views;
|
|||||||
|
|
||||||
public partial class MainWindow : Window
|
public partial class MainWindow : Window
|
||||||
{
|
{
|
||||||
private readonly Dictionary<EnvironmentVariableRowViewModel, DataGridRow> _gridRows = new();
|
|
||||||
|
|
||||||
public MainWindow()
|
public MainWindow()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
@@ -24,71 +23,25 @@ public partial class MainWindow : Window
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_gridRows.TryGetValue(row, out var previousRow) && previousRow != e.Row)
|
|
||||||
{
|
|
||||||
previousRow.DataContextChanged -= OnRowDataContextChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
_gridRows[row] = e.Row;
|
|
||||||
ApplyRowClasses(e.Row, row);
|
ApplyRowClasses(e.Row, row);
|
||||||
|
|
||||||
row.RowAppearanceChanged -= OnRowAppearanceChanged;
|
PropertyChangedEventHandler? handler = null;
|
||||||
row.RowAppearanceChanged += OnRowAppearanceChanged;
|
handler = (_, args) =>
|
||||||
|
|
||||||
e.Row.DataContextChanged -= OnRowDataContextChanged;
|
|
||||||
e.Row.DataContextChanged += OnRowDataContextChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnRowDataContextChanged(object? sender, EventArgs e)
|
|
||||||
{
|
|
||||||
if (sender is not DataGridRow gridRow)
|
|
||||||
{
|
{
|
||||||
return;
|
if (args.PropertyName is nameof(EnvironmentVariableRowViewModel.UseUserStore))
|
||||||
}
|
{
|
||||||
|
ApplyRowClasses(e.Row, row);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
var row = _gridRows.FirstOrDefault(pair => pair.Value == gridRow).Key;
|
row.PropertyChanged += handler;
|
||||||
if (row is null)
|
e.Row.DetachedFromVisualTree += (_, _) => row.PropertyChanged -= handler;
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
row.RowAppearanceChanged -= OnRowAppearanceChanged;
|
|
||||||
_gridRows.Remove(row);
|
|
||||||
gridRow.DataContextChanged -= OnRowDataContextChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnRowAppearanceChanged(object? sender, EventArgs e)
|
|
||||||
{
|
|
||||||
if (sender is not EnvironmentVariableRowViewModel row)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_gridRows.TryGetValue(row, out var gridRow))
|
|
||||||
{
|
|
||||||
ApplyRowClasses(gridRow, row);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ApplyRowClasses(DataGridRow gridRow, EnvironmentVariableRowViewModel row)
|
private static void ApplyRowClasses(DataGridRow gridRow, EnvironmentVariableRowViewModel row)
|
||||||
{
|
{
|
||||||
gridRow.Classes.Remove("appSettings");
|
gridRow.Classes.Set("appSettings", row.IsFromAppSettings);
|
||||||
gridRow.Classes.Remove("custom");
|
gridRow.Classes.Set("custom", row.IsCustom);
|
||||||
gridRow.Classes.Remove("userStore");
|
gridRow.Classes.Set("userStore", row.UseUserStore);
|
||||||
|
|
||||||
if (row.IsFromAppSettings)
|
|
||||||
{
|
|
||||||
gridRow.Classes.Add("appSettings");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (row.IsCustom)
|
|
||||||
{
|
|
||||||
gridRow.Classes.Add("custom");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (row.UseUserStore)
|
|
||||||
{
|
|
||||||
gridRow.Classes.Add("userStore");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,12 +36,11 @@ public sealed class EnvironmentVariablesService
|
|||||||
_options = options.Value;
|
_options = options.Value;
|
||||||
_log = log;
|
_log = log;
|
||||||
_configuredNames = new HashSet<string>(_options.Names, StringComparer.Ordinal);
|
_configuredNames = new HashSet<string>(_options.Names, StringComparer.Ordinal);
|
||||||
|
ReloadMetadata();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void EnsureConfiguredVariablesExist()
|
public void EnsureConfiguredVariablesExist()
|
||||||
{
|
{
|
||||||
ReloadMetadata();
|
|
||||||
|
|
||||||
foreach (var name in _options.Names)
|
foreach (var name in _options.Names)
|
||||||
{
|
{
|
||||||
if (_store.IsPersistedInUserStore(name))
|
if (_store.IsPersistedInUserStore(name))
|
||||||
@@ -51,8 +50,7 @@ public sealed class EnvironmentVariablesService
|
|||||||
|
|
||||||
var value = ResolveRequiredValue(name);
|
var value = ResolveRequiredValue(name);
|
||||||
_store.Set(name, value);
|
_store.Set(name, value);
|
||||||
_log.WriteLine(
|
LogInfo($"Created configured variable: {name}={value}");
|
||||||
$"{DateTime.Now:yyyy-MM-dd HH:mm:ss} [INFO] Created configured variable: {name}={value}");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,7 +95,6 @@ public sealed class EnvironmentVariablesService
|
|||||||
|
|
||||||
public bool TryAddCustomVariable(string name, string value, out string? errorMessage)
|
public bool TryAddCustomVariable(string name, string value, out string? errorMessage)
|
||||||
{
|
{
|
||||||
ReloadMetadata();
|
|
||||||
name = name.Trim();
|
name = name.Trim();
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(name))
|
if (string.IsNullOrWhiteSpace(name))
|
||||||
@@ -127,20 +124,16 @@ public sealed class EnvironmentVariablesService
|
|||||||
_customNames.Add(name);
|
_customNames.Add(name);
|
||||||
PersistCustomNames();
|
PersistCustomNames();
|
||||||
_store.Set(name, value);
|
_store.Set(name, value);
|
||||||
_log.WriteLine(
|
LogInfo($"Created custom variable: {name}={value}");
|
||||||
$"{DateTime.Now:yyyy-MM-dd HH:mm:ss} [INFO] Created custom variable: {name}={value}");
|
|
||||||
|
|
||||||
errorMessage = null;
|
errorMessage = null;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public EnvironmentVariableRow GetRowSnapshot(string name)
|
public EnvironmentVariableRow GetRowSnapshot(string name) =>
|
||||||
{
|
CreateRow(name, ResolveRequiredValue(name));
|
||||||
ReloadMetadata();
|
|
||||||
return CreateRow(name, ResolveRequiredValue(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetDisplayValue(string name) => ResolveRequiredValue(name);
|
public string GetRequiredValue(string name) => ResolveRequiredValue(name);
|
||||||
|
|
||||||
public string? GetProcessValue(string name) =>
|
public string? GetProcessValue(string name) =>
|
||||||
_store.GetProcessEnvironment().TryGetValue(name, out var value) ? value : null;
|
_store.GetProcessEnvironment().TryGetValue(name, out var value) ? value : null;
|
||||||
@@ -149,8 +142,7 @@ public sealed class EnvironmentVariablesService
|
|||||||
{
|
{
|
||||||
var previous = _store.GetUserPersistedValue(name);
|
var previous = _store.GetUserPersistedValue(name);
|
||||||
_store.Set(name, value);
|
_store.Set(name, value);
|
||||||
_log.WriteLine(
|
LogInfo($"Changed value: {name}={value} (previous: {previous ?? "<none>"})");
|
||||||
$"{DateTime.Now:yyyy-MM-dd HH:mm:ss} [INFO] Changed value: {name}={value} (previous: {previous ?? "<none>"})");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SaveComment(string name, string comment)
|
public void SaveComment(string name, string comment)
|
||||||
@@ -158,22 +150,18 @@ public sealed class EnvironmentVariablesService
|
|||||||
var previous = _comments.GetValueOrDefault(name, string.Empty);
|
var previous = _comments.GetValueOrDefault(name, string.Empty);
|
||||||
_comments[name] = comment;
|
_comments[name] = comment;
|
||||||
PersistComments();
|
PersistComments();
|
||||||
_log.WriteLine(
|
LogInfo($"Changed comment: {name}={comment} (previous: {(string.IsNullOrEmpty(previous) ? "<none>" : previous)})");
|
||||||
$"{DateTime.Now:yyyy-MM-dd HH:mm:ss} [INFO] Changed comment: {name}={comment} (previous: {(string.IsNullOrEmpty(previous) ? "<none>" : previous)})");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveVariable(string name)
|
public void RemoveVariable(string name)
|
||||||
{
|
{
|
||||||
ReloadMetadata();
|
|
||||||
|
|
||||||
if (IsCustom(name))
|
if (IsCustom(name))
|
||||||
{
|
{
|
||||||
_customNames.Remove(name);
|
_customNames.Remove(name);
|
||||||
PersistCustomNames();
|
PersistCustomNames();
|
||||||
_comments.Remove(name);
|
_comments.Remove(name);
|
||||||
PersistComments();
|
PersistComments();
|
||||||
_log.WriteLine(
|
LogInfo($"Removed custom variable from list: {name}");
|
||||||
$"{DateTime.Now:yyyy-MM-dd HH:mm:ss} [INFO] Removed custom variable from list: {name}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DeleteFromUserStore(name);
|
DeleteFromUserStore(name);
|
||||||
@@ -188,8 +176,7 @@ public sealed class EnvironmentVariablesService
|
|||||||
|
|
||||||
var previous = _store.GetUserPersistedValue(name);
|
var previous = _store.GetUserPersistedValue(name);
|
||||||
_store.RemoveFromUserStore(name);
|
_store.RemoveFromUserStore(name);
|
||||||
_log.WriteLine(
|
LogInfo($"Removed from user store: {name} (previous: {previous ?? "<none>"})");
|
||||||
$"{DateTime.Now:yyyy-MM-dd HH:mm:ss} [INFO] Removed from user store: {name} (previous: {previous ?? "<none>"})");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsCustom(string name) => _customNames.Contains(name, StringComparer.Ordinal);
|
public bool IsCustom(string name) => _customNames.Contains(name, StringComparer.Ordinal);
|
||||||
@@ -227,12 +214,7 @@ public sealed class EnvironmentVariablesService
|
|||||||
|
|
||||||
if (_configuredNames.Contains(name) || _customNames.Contains(name))
|
if (_configuredNames.Contains(name) || _customNames.Contains(name))
|
||||||
{
|
{
|
||||||
if (_options.Defaults.TryGetValue(name, out var defaultValue))
|
return _options.Defaults.TryGetValue(name, out var defaultValue) ? defaultValue : string.Empty;
|
||||||
{
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return string.Empty;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
@@ -252,8 +234,7 @@ public sealed class EnvironmentVariablesService
|
|||||||
}
|
}
|
||||||
catch (JsonException ex)
|
catch (JsonException ex)
|
||||||
{
|
{
|
||||||
_log.WriteLine(
|
LogWarn($"Failed to parse custom variables {_options.CustomVariablesVariableName}: {ex.Message}");
|
||||||
$"{DateTime.Now:yyyy-MM-dd HH:mm:ss} [WARN] Failed to parse custom variables {_options.CustomVariablesVariableName}: {ex.Message}");
|
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -279,8 +260,7 @@ public sealed class EnvironmentVariablesService
|
|||||||
}
|
}
|
||||||
catch (JsonException ex)
|
catch (JsonException ex)
|
||||||
{
|
{
|
||||||
_log.WriteLine(
|
LogWarn($"Failed to parse comments variable {_options.CommentsVariableName}: {ex.Message}");
|
||||||
$"{DateTime.Now:yyyy-MM-dd HH:mm:ss} [WARN] Failed to parse comments variable {_options.CommentsVariableName}: {ex.Message}");
|
|
||||||
return new Dictionary<string, string>(StringComparer.Ordinal);
|
return new Dictionary<string, string>(StringComparer.Ordinal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -290,4 +270,10 @@ public sealed class EnvironmentVariablesService
|
|||||||
var json = JsonSerializer.Serialize(_comments, JsonOptions);
|
var json = JsonSerializer.Serialize(_comments, JsonOptions);
|
||||||
_store.Set(_options.CommentsVariableName, json);
|
_store.Set(_options.CommentsVariableName, json);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void LogInfo(string message) =>
|
||||||
|
_log.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss} [INFO] {message}");
|
||||||
|
|
||||||
|
private void LogWarn(string message) =>
|
||||||
|
_log.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss} [WARN] {message}");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ public sealed partial class EnvironmentVariableRowViewModel : ObservableObject
|
|||||||
private bool _useUserStore;
|
private bool _useUserStore;
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
|
[NotifyPropertyChangedFor(nameof(ActualValueDisplay))]
|
||||||
private string _actualValue = string.Empty;
|
private string _actualValue = string.Empty;
|
||||||
|
|
||||||
public string ActualValueDisplay =>
|
public string ActualValueDisplay =>
|
||||||
@@ -49,8 +50,6 @@ public sealed partial class EnvironmentVariableRowViewModel : ObservableObject
|
|||||||
|
|
||||||
partial void OnUseUserStoreChanged(bool value)
|
partial void OnUseUserStoreChanged(bool value)
|
||||||
{
|
{
|
||||||
RowAppearanceChanged?.Invoke(this, EventArgs.Empty);
|
|
||||||
|
|
||||||
if (_isLoading)
|
if (_isLoading)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -58,9 +57,7 @@ public sealed partial class EnvironmentVariableRowViewModel : ObservableObject
|
|||||||
|
|
||||||
if (IsFromAppSettings && !value)
|
if (IsFromAppSettings && !value)
|
||||||
{
|
{
|
||||||
BeginLoad();
|
RunWithoutSave(() => UseUserStore = true);
|
||||||
UseUserStore = true;
|
|
||||||
EndLoad();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,14 +76,10 @@ public sealed partial class EnvironmentVariableRowViewModel : ObservableObject
|
|||||||
}
|
}
|
||||||
|
|
||||||
_service.DeleteFromUserStore(Field);
|
_service.DeleteFromUserStore(Field);
|
||||||
BeginLoad();
|
RunWithoutSave(() => RequiredValue = _service.GetRequiredValue(Field));
|
||||||
RequiredValue = _service.GetDisplayValue(Field);
|
|
||||||
EndLoad();
|
|
||||||
RefreshActualValue(_service.GetProcessValue(Field));
|
RefreshActualValue(_service.GetProcessValue(Field));
|
||||||
}
|
}
|
||||||
|
|
||||||
partial void OnActualValueChanged(string value) => OnPropertyChanged(nameof(ActualValueDisplay));
|
|
||||||
|
|
||||||
partial void OnRequiredValueChanged(string value)
|
partial void OnRequiredValueChanged(string value)
|
||||||
{
|
{
|
||||||
if (_isLoading || !UseUserStore)
|
if (_isLoading || !UseUserStore)
|
||||||
@@ -98,22 +91,22 @@ public sealed partial class EnvironmentVariableRowViewModel : ObservableObject
|
|||||||
RefreshActualValue(_service.GetProcessValue(Field));
|
RefreshActualValue(_service.GetProcessValue(Field));
|
||||||
}
|
}
|
||||||
|
|
||||||
public event EventHandler? RowAppearanceChanged;
|
|
||||||
|
|
||||||
public void ApplySnapshot(EnvironmentVariableRow row, bool suppressSave = false)
|
public void ApplySnapshot(EnvironmentVariableRow row, bool suppressSave = false)
|
||||||
{
|
{
|
||||||
if (suppressSave)
|
if (suppressSave)
|
||||||
{
|
{
|
||||||
BeginLoad();
|
RunWithoutSave(ApplyValues);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ApplyValues();
|
||||||
}
|
}
|
||||||
|
|
||||||
RequiredValue = row.Value;
|
void ApplyValues()
|
||||||
Comment = row.Comment;
|
|
||||||
UseUserStore = row.IsFromAppSettings || row.IsPersistedInUserStore;
|
|
||||||
|
|
||||||
if (suppressSave)
|
|
||||||
{
|
{
|
||||||
EndLoad();
|
RequiredValue = row.Value;
|
||||||
|
Comment = row.Comment;
|
||||||
|
UseUserStore = row.IsFromAppSettings || row.IsPersistedInUserStore;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,10 +115,6 @@ public sealed partial class EnvironmentVariableRowViewModel : ObservableObject
|
|||||||
ActualValue = processValue ?? string.Empty;
|
ActualValue = processValue ?? string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void BeginLoad() => _isLoading = true;
|
|
||||||
|
|
||||||
public void EndLoad() => _isLoading = false;
|
|
||||||
|
|
||||||
partial void OnCommentChanged(string value)
|
partial void OnCommentChanged(string value)
|
||||||
{
|
{
|
||||||
if (_isLoading)
|
if (_isLoading)
|
||||||
@@ -135,4 +124,17 @@ public sealed partial class EnvironmentVariableRowViewModel : ObservableObject
|
|||||||
|
|
||||||
_service.SaveComment(Field, value);
|
_service.SaveComment(Field, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void RunWithoutSave(Action action)
|
||||||
|
{
|
||||||
|
_isLoading = true;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
action();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_isLoading = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,8 +30,11 @@ public sealed partial class MainWindowViewModel : ObservableObject
|
|||||||
private string _newVariableValue = string.Empty;
|
private string _newVariableValue = string.Empty;
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
|
[NotifyPropertyChangedFor(nameof(HasAddVariableError))]
|
||||||
private string? _addVariableError;
|
private string? _addVariableError;
|
||||||
|
|
||||||
|
public bool HasAddVariableError => !string.IsNullOrEmpty(AddVariableError);
|
||||||
|
|
||||||
partial void OnShowAllVariablesChanged(bool value) => SyncRowsFromService();
|
partial void OnShowAllVariablesChanged(bool value) => SyncRowsFromService();
|
||||||
|
|
||||||
partial void OnNewVariableNameChanged(string value) => AddVariableCommand.NotifyCanExecuteChanged();
|
partial void OnNewVariableNameChanged(string value) => AddVariableCommand.NotifyCanExecuteChanged();
|
||||||
@@ -59,18 +62,18 @@ public sealed partial class MainWindowViewModel : ObservableObject
|
|||||||
|
|
||||||
private EnvironmentVariableRowViewModel CreateRowViewModel(EnvironmentVariableRow row)
|
private EnvironmentVariableRowViewModel CreateRowViewModel(EnvironmentVariableRow row)
|
||||||
{
|
{
|
||||||
EnvironmentVariableRowViewModel? viewModel = null;
|
var field = row.Field;
|
||||||
viewModel = new EnvironmentVariableRowViewModel(
|
return new EnvironmentVariableRowViewModel(
|
||||||
row,
|
row,
|
||||||
_service,
|
_service,
|
||||||
onCustomRemoved: () =>
|
onCustomRemoved: () =>
|
||||||
{
|
{
|
||||||
if (viewModel is not null)
|
var existing = Rows.FirstOrDefault(r => r.Field == field);
|
||||||
|
if (existing is not null)
|
||||||
{
|
{
|
||||||
Rows.Remove(viewModel);
|
Rows.Remove(existing);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return viewModel;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private int FindInsertIndexForCustomVariable()
|
private int FindInsertIndexForCustomVariable()
|
||||||
@@ -128,11 +131,6 @@ public sealed partial class MainWindowViewModel : ObservableObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RefreshProcessStates();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RefreshProcessStates()
|
|
||||||
{
|
|
||||||
foreach (var row in Rows)
|
foreach (var row in Rows)
|
||||||
{
|
{
|
||||||
row.RefreshActualValue(_service.GetProcessValue(row.Field));
|
row.RefreshActualValue(_service.GetProcessValue(row.Field));
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
Startup="OnStartup"
|
Startup="OnStartup"
|
||||||
Exit="OnExit">
|
Exit="OnExit">
|
||||||
<Application.Resources>
|
<Application.Resources>
|
||||||
|
<BooleanToVisibilityConverter x:Key="BooleanToVisibility" />
|
||||||
<Style x:Key="RoundedGridStyle" TargetType="DataGrid">
|
<Style x:Key="RoundedGridStyle" TargetType="DataGrid">
|
||||||
<Setter Property="RowHeight" Value="32" />
|
<Setter Property="RowHeight" Value="32" />
|
||||||
<Setter Property="Background" Value="Transparent" />
|
<Setter Property="Background" Value="Transparent" />
|
||||||
@@ -15,6 +16,51 @@
|
|||||||
<Setter Property="CanUserSortColumns" Value="False" />
|
<Setter Property="CanUserSortColumns" Value="False" />
|
||||||
<Setter Property="AutoGenerateColumns" Value="False" />
|
<Setter Property="AutoGenerateColumns" Value="False" />
|
||||||
</Style>
|
</Style>
|
||||||
|
<Style x:Key="VariableRowStyle" TargetType="DataGridRow">
|
||||||
|
<Setter Property="Background" Value="White" />
|
||||||
|
<Setter Property="BorderBrush" Value="Transparent" />
|
||||||
|
<Setter Property="BorderThickness" Value="0" />
|
||||||
|
<Style.Triggers>
|
||||||
|
<DataTrigger Binding="{Binding IsFromAppSettings}" Value="True">
|
||||||
|
<Setter Property="Background" Value="#E3F2FD" />
|
||||||
|
</DataTrigger>
|
||||||
|
<DataTrigger Binding="{Binding IsCustom}" Value="True">
|
||||||
|
<Setter Property="Background" Value="#FFF8E1" />
|
||||||
|
</DataTrigger>
|
||||||
|
<MultiDataTrigger>
|
||||||
|
<MultiDataTrigger.Conditions>
|
||||||
|
<Condition Binding="{Binding IsFromAppSettings}" Value="True" />
|
||||||
|
<Condition Binding="{Binding UseUserStore}" Value="True" />
|
||||||
|
</MultiDataTrigger.Conditions>
|
||||||
|
<Setter Property="Background" Value="#C8E6C9" />
|
||||||
|
</MultiDataTrigger>
|
||||||
|
<DataTrigger Binding="{Binding UseUserStore}" Value="True">
|
||||||
|
<Setter Property="BorderBrush" Value="#2E7D32" />
|
||||||
|
<Setter Property="BorderThickness" Value="0,0,0,2" />
|
||||||
|
</DataTrigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
<Style x:Key="WatermarkTextBlockStyle" TargetType="TextBlock">
|
||||||
|
<Setter Property="IsHitTestVisible" Value="False" />
|
||||||
|
<Setter Property="Margin" Value="6,0,0,0" />
|
||||||
|
<Setter Property="VerticalAlignment" Value="Center" />
|
||||||
|
<Setter Property="Foreground" Value="#9E9E9E" />
|
||||||
|
<Setter Property="Visibility" Value="Collapsed" />
|
||||||
|
</Style>
|
||||||
|
<Style x:Key="NameWatermarkStyle" TargetType="TextBlock" BasedOn="{StaticResource WatermarkTextBlockStyle}">
|
||||||
|
<Style.Triggers>
|
||||||
|
<DataTrigger Binding="{Binding NewVariableName}" Value="">
|
||||||
|
<Setter Property="Visibility" Value="Visible" />
|
||||||
|
</DataTrigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
<Style x:Key="ValueWatermarkStyle" TargetType="TextBlock" BasedOn="{StaticResource WatermarkTextBlockStyle}">
|
||||||
|
<Style.Triggers>
|
||||||
|
<DataTrigger Binding="{Binding NewVariableValue}" Value="">
|
||||||
|
<Setter Property="Visibility" Value="Visible" />
|
||||||
|
</DataTrigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
<Style TargetType="DataGridColumnHeader">
|
<Style TargetType="DataGridColumnHeader">
|
||||||
<Setter Property="Background" Value="Transparent" />
|
<Setter Property="Background" Value="Transparent" />
|
||||||
<Setter Property="BorderBrush" Value="Transparent" />
|
<Setter Property="BorderBrush" Value="Transparent" />
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
namespace Sms.TaskTwo.Wpf;
|
|
||||||
|
|
||||||
public static class AppResources
|
|
||||||
{
|
|
||||||
public const string WindowTitle = "Тестовое WPF-приложение для SmartMealService";
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
using System.Globalization;
|
|
||||||
using System.Windows;
|
|
||||||
using System.Windows.Data;
|
|
||||||
|
|
||||||
namespace Sms.TaskTwo.Wpf.Converters;
|
|
||||||
|
|
||||||
public sealed class StringNotEmptyToVisibilityConverter : IValueConverter
|
|
||||||
{
|
|
||||||
public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture) =>
|
|
||||||
value is string text && !string.IsNullOrEmpty(text)
|
|
||||||
? Visibility.Visible
|
|
||||||
: Visibility.Collapsed;
|
|
||||||
|
|
||||||
public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) =>
|
|
||||||
throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
@@ -2,17 +2,12 @@
|
|||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:vm="clr-namespace:Sms.TaskTwo.ViewModels;assembly=Sms.TaskTwo.ViewModels"
|
xmlns:vm="clr-namespace:Sms.TaskTwo.ViewModels;assembly=Sms.TaskTwo.ViewModels"
|
||||||
xmlns:app="clr-namespace:Sms.TaskTwo.Wpf"
|
Title="Тестовое WPF-приложение для SmartMealService"
|
||||||
xmlns:conv="clr-namespace:Sms.TaskTwo.Wpf.Converters"
|
|
||||||
Title="{x:Static app:AppResources.WindowTitle}"
|
|
||||||
Width="960"
|
Width="960"
|
||||||
Height="600"
|
Height="600"
|
||||||
MinWidth="760"
|
MinWidth="760"
|
||||||
MinHeight="480"
|
MinHeight="480"
|
||||||
Background="#F5F5F5">
|
Background="#F5F5F5">
|
||||||
<Window.Resources>
|
|
||||||
<conv:StringNotEmptyToVisibilityConverter x:Key="StringNotEmptyToVisibility" />
|
|
||||||
</Window.Resources>
|
|
||||||
<Border CornerRadius="12"
|
<Border CornerRadius="12"
|
||||||
Background="White"
|
Background="White"
|
||||||
BorderBrush="#C8C8C8"
|
BorderBrush="#C8C8C8"
|
||||||
@@ -56,41 +51,11 @@
|
|||||||
VerticalAlignment="Center" />
|
VerticalAlignment="Center" />
|
||||||
<Grid Grid.Column="1" Margin="8,0,0,0">
|
<Grid Grid.Column="1" Margin="8,0,0,0">
|
||||||
<TextBox Text="{Binding NewVariableName, UpdateSourceTrigger=PropertyChanged}" />
|
<TextBox Text="{Binding NewVariableName, UpdateSourceTrigger=PropertyChanged}" />
|
||||||
<TextBlock Text="Имя переменной"
|
<TextBlock Text="Имя переменной" Style="{StaticResource NameWatermarkStyle}" />
|
||||||
IsHitTestVisible="False"
|
|
||||||
Margin="6,0,0,0"
|
|
||||||
VerticalAlignment="Center"
|
|
||||||
Foreground="#9E9E9E">
|
|
||||||
<TextBlock.Style>
|
|
||||||
<Style TargetType="TextBlock">
|
|
||||||
<Setter Property="Visibility" Value="Collapsed" />
|
|
||||||
<Style.Triggers>
|
|
||||||
<DataTrigger Binding="{Binding NewVariableName}" Value="">
|
|
||||||
<Setter Property="Visibility" Value="Visible" />
|
|
||||||
</DataTrigger>
|
|
||||||
</Style.Triggers>
|
|
||||||
</Style>
|
|
||||||
</TextBlock.Style>
|
|
||||||
</TextBlock>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid Grid.Column="2" Margin="8,0,0,0">
|
<Grid Grid.Column="2" Margin="8,0,0,0">
|
||||||
<TextBox Text="{Binding NewVariableValue, UpdateSourceTrigger=PropertyChanged}" />
|
<TextBox Text="{Binding NewVariableValue, UpdateSourceTrigger=PropertyChanged}" />
|
||||||
<TextBlock Text="Значение"
|
<TextBlock Text="Значение" Style="{StaticResource ValueWatermarkStyle}" />
|
||||||
IsHitTestVisible="False"
|
|
||||||
Margin="6,0,0,0"
|
|
||||||
VerticalAlignment="Center"
|
|
||||||
Foreground="#9E9E9E">
|
|
||||||
<TextBlock.Style>
|
|
||||||
<Style TargetType="TextBlock">
|
|
||||||
<Setter Property="Visibility" Value="Collapsed" />
|
|
||||||
<Style.Triggers>
|
|
||||||
<DataTrigger Binding="{Binding NewVariableValue}" Value="">
|
|
||||||
<Setter Property="Visibility" Value="Visible" />
|
|
||||||
</DataTrigger>
|
|
||||||
</Style.Triggers>
|
|
||||||
</Style>
|
|
||||||
</TextBlock.Style>
|
|
||||||
</TextBlock>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
<Button Grid.Column="3"
|
<Button Grid.Column="3"
|
||||||
Content="Добавить"
|
Content="Добавить"
|
||||||
@@ -99,12 +64,11 @@
|
|||||||
Margin="8,0,0,0" />
|
Margin="8,0,0,0" />
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<StackPanel Grid.Row="2"
|
<TextBlock Grid.Row="2"
|
||||||
Margin="12,4,12,0">
|
Margin="12,4,12,0"
|
||||||
<TextBlock Foreground="#C62828"
|
Foreground="#C62828"
|
||||||
Text="{Binding AddVariableError}"
|
Text="{Binding AddVariableError}"
|
||||||
Visibility="{Binding AddVariableError, Converter={StaticResource StringNotEmptyToVisibility}}" />
|
Visibility="{Binding HasAddVariableError, Converter={StaticResource BooleanToVisibility}}" />
|
||||||
</StackPanel>
|
|
||||||
|
|
||||||
<Border Grid.Row="3"
|
<Border Grid.Row="3"
|
||||||
Margin="12,4,12,12"
|
Margin="12,4,12,12"
|
||||||
@@ -115,9 +79,8 @@
|
|||||||
BorderThickness="1">
|
BorderThickness="1">
|
||||||
<DataGrid x:Name="VariablesGrid"
|
<DataGrid x:Name="VariablesGrid"
|
||||||
Style="{StaticResource RoundedGridStyle}"
|
Style="{StaticResource RoundedGridStyle}"
|
||||||
ItemsSource="{Binding Rows}"
|
RowStyle="{StaticResource VariableRowStyle}"
|
||||||
LoadingRow="OnLoadingRow"
|
ItemsSource="{Binding Rows}">
|
||||||
UnloadingRow="OnUnloadingRow">
|
|
||||||
<DataGrid.Columns>
|
<DataGrid.Columns>
|
||||||
<DataGridTemplateColumn Header=""
|
<DataGridTemplateColumn Header=""
|
||||||
Width="44">
|
Width="44">
|
||||||
|
|||||||
@@ -1,128 +1,13 @@
|
|||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
|
||||||
using System.Windows.Media;
|
|
||||||
using Sms.TaskTwo.ViewModels;
|
using Sms.TaskTwo.ViewModels;
|
||||||
|
|
||||||
namespace Sms.TaskTwo.Wpf.Views;
|
namespace Sms.TaskTwo.Wpf.Views;
|
||||||
|
|
||||||
public partial class MainWindow : Window
|
public partial class MainWindow : Window
|
||||||
{
|
{
|
||||||
private static readonly Brush AppSettingsBrush = new SolidColorBrush(Color.FromRgb(0xE3, 0xF2, 0xFD));
|
public MainWindow(MainWindowViewModel viewModel)
|
||||||
private static readonly Brush CustomBrush = new SolidColorBrush(Color.FromRgb(0xFF, 0xF8, 0xE1));
|
|
||||||
private static readonly Brush AppSettingsUserStoreBrush = new SolidColorBrush(Color.FromRgb(0xC8, 0xE6, 0xC9));
|
|
||||||
private static readonly Brush UserStoreBorderBrush = new SolidColorBrush(Color.FromRgb(0x2E, 0x7D, 0x32));
|
|
||||||
private static readonly Brush DefaultRowBrush = Brushes.White;
|
|
||||||
|
|
||||||
private readonly Dictionary<EnvironmentVariableRowViewModel, DataGridRow> _gridRows = new();
|
|
||||||
|
|
||||||
public MainWindow()
|
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
|
||||||
|
|
||||||
public MainWindow(MainWindowViewModel viewModel) : this()
|
|
||||||
{
|
|
||||||
DataContext = viewModel;
|
DataContext = viewModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnLoadingRow(object sender, DataGridRowEventArgs e)
|
|
||||||
{
|
|
||||||
if (e.Row.DataContext is not EnvironmentVariableRowViewModel row)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_gridRows.TryGetValue(row, out var previousRow) && previousRow != e.Row)
|
|
||||||
{
|
|
||||||
UnsubscribeRow(previousRow, row);
|
|
||||||
}
|
|
||||||
|
|
||||||
_gridRows[row] = e.Row;
|
|
||||||
ApplyRowStyle(e.Row, row);
|
|
||||||
|
|
||||||
row.RowAppearanceChanged -= OnRowAppearanceChanged;
|
|
||||||
row.RowAppearanceChanged += OnRowAppearanceChanged;
|
|
||||||
|
|
||||||
e.Row.DataContextChanged -= OnRowDataContextChanged;
|
|
||||||
e.Row.DataContextChanged += OnRowDataContextChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnUnloadingRow(object sender, DataGridRowEventArgs e)
|
|
||||||
{
|
|
||||||
var row = _gridRows.FirstOrDefault(pair => pair.Value == e.Row).Key;
|
|
||||||
if (row is null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
UnsubscribeRow(e.Row, row);
|
|
||||||
_gridRows.Remove(row);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UnsubscribeRow(DataGridRow gridRow, EnvironmentVariableRowViewModel row)
|
|
||||||
{
|
|
||||||
row.RowAppearanceChanged -= OnRowAppearanceChanged;
|
|
||||||
gridRow.DataContextChanged -= OnRowDataContextChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnRowDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
|
|
||||||
{
|
|
||||||
if (sender is not DataGridRow gridRow)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var row = _gridRows.FirstOrDefault(pair => pair.Value == gridRow).Key;
|
|
||||||
if (row is null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
UnsubscribeRow(gridRow, row);
|
|
||||||
_gridRows.Remove(row);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnRowAppearanceChanged(object? sender, EventArgs e)
|
|
||||||
{
|
|
||||||
if (sender is not EnvironmentVariableRowViewModel row)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_gridRows.TryGetValue(row, out var gridRow))
|
|
||||||
{
|
|
||||||
ApplyRowStyle(gridRow, row);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void ApplyRowStyle(DataGridRow gridRow, EnvironmentVariableRowViewModel row)
|
|
||||||
{
|
|
||||||
if (row.IsFromAppSettings && row.UseUserStore)
|
|
||||||
{
|
|
||||||
gridRow.Background = AppSettingsUserStoreBrush;
|
|
||||||
}
|
|
||||||
else if (row.IsFromAppSettings)
|
|
||||||
{
|
|
||||||
gridRow.Background = AppSettingsBrush;
|
|
||||||
}
|
|
||||||
else if (row.IsCustom)
|
|
||||||
{
|
|
||||||
gridRow.Background = CustomBrush;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
gridRow.Background = DefaultRowBrush;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (row.UseUserStore)
|
|
||||||
{
|
|
||||||
gridRow.BorderBrush = UserStoreBorderBrush;
|
|
||||||
gridRow.BorderThickness = new Thickness(0, 0, 0, 2);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
gridRow.BorderBrush = Brushes.Transparent;
|
|
||||||
gridRow.BorderThickness = new Thickness(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user