fixed bug drop list is empty after language switch
This commit is contained in:
@@ -5,7 +5,11 @@ namespace CursorLang.Services;
|
|||||||
/// <summary>Язык интерфейса для выбора в настройках.</summary>
|
/// <summary>Язык интерфейса для выбора в настройках.</summary>
|
||||||
/// <param name="Code">Код культуры: «ru», «en».</param>
|
/// <param name="Code">Код культуры: «ru», «en».</param>
|
||||||
/// <param name="DisplayName">Название на самом этом языке.</param>
|
/// <param name="DisplayName">Название на самом этом языке.</param>
|
||||||
public sealed record LanguageOption(string Code, string DisplayName);
|
public sealed record LanguageOption(string Code, string DisplayName)
|
||||||
|
{
|
||||||
|
// Средства доступности берут имя элемента списка отсюда
|
||||||
|
public override string ToString() => DisplayName;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Даёт строки интерфейса и умеет менять язык без перезапуска.
|
/// Даёт строки интерфейса и умеет менять язык без перезапуска.
|
||||||
|
|||||||
@@ -7,8 +7,32 @@ using CursorLang.Services;
|
|||||||
|
|
||||||
namespace CursorLang.ViewModels;
|
namespace CursorLang.ViewModels;
|
||||||
|
|
||||||
/// <summary>Вариант выбора в списке: значение и его подпись на текущем языке.</summary>
|
/// <summary>
|
||||||
public sealed record EnumOption<T>(T Value, string Display);
|
/// Вариант выбора в списке. Подпись меняется вместе с языком, а сам объект
|
||||||
|
/// живёт всё время работы окна: если пересоздавать элементы списка,
|
||||||
|
/// ComboBox сбрасывает выбранное значение.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class EnumOption<T> : ObservableObject where T : struct, Enum
|
||||||
|
{
|
||||||
|
private string _display;
|
||||||
|
|
||||||
|
public EnumOption(T value, string display)
|
||||||
|
{
|
||||||
|
Value = value;
|
||||||
|
_display = display;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T Value { get; }
|
||||||
|
|
||||||
|
public string Display
|
||||||
|
{
|
||||||
|
get => _display;
|
||||||
|
set => SetProperty(ref _display, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Средства доступности берут имя элемента списка отсюда
|
||||||
|
public override string ToString() => Display;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Окно настроек. Значения правятся прямо в <see cref="AppSettings"/>,
|
/// Окно настроек. Значения правятся прямо в <see cref="AppSettings"/>,
|
||||||
@@ -38,7 +62,9 @@ public sealed partial class SettingsViewModel : ObservableObject, IDisposable
|
|||||||
Settings.PropertyChanged += OnSettingsChanged;
|
Settings.PropertyChanged += OnSettingsChanged;
|
||||||
Localization.PropertyChanged += OnLocalizationChanged;
|
Localization.PropertyChanged += OnLocalizationChanged;
|
||||||
|
|
||||||
BuildLocalizedOptions();
|
PlacementModes = CreateOptions<PopupPlacementMode>();
|
||||||
|
CursorCorners = CreateOptions<CursorCorner>();
|
||||||
|
ScreenPositions = CreateOptions<ScreenPosition>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public AppSettings Settings { get; }
|
public AppSettings Settings { get; }
|
||||||
@@ -47,11 +73,11 @@ public sealed partial class SettingsViewModel : ObservableObject, IDisposable
|
|||||||
|
|
||||||
public IReadOnlyList<Color> BackgroundPalette { get; } = Palette;
|
public IReadOnlyList<Color> BackgroundPalette { get; } = Palette;
|
||||||
|
|
||||||
public IReadOnlyList<EnumOption<PopupPlacementMode>> PlacementModes { get; private set; } = [];
|
public IReadOnlyList<EnumOption<PopupPlacementMode>> PlacementModes { get; }
|
||||||
|
|
||||||
public IReadOnlyList<EnumOption<CursorCorner>> CursorCorners { get; private set; } = [];
|
public IReadOnlyList<EnumOption<CursorCorner>> CursorCorners { get; }
|
||||||
|
|
||||||
public IReadOnlyList<EnumOption<ScreenPosition>> ScreenPositions { get; private set; } = [];
|
public IReadOnlyList<EnumOption<ScreenPosition>> ScreenPositions { get; }
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
@@ -68,26 +94,31 @@ public sealed partial class SettingsViewModel : ObservableObject, IDisposable
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Подписи вариантов приходят из ресурсов, поэтому при смене языка
|
// Подписи вариантов приходят из ресурсов, поэтому при смене языка
|
||||||
// списки нужно собрать заново — привязки сами перечитают их
|
// обновляем только текст — сами элементы списков остаются прежними
|
||||||
private void OnLocalizationChanged(object? sender, PropertyChangedEventArgs e)
|
private void OnLocalizationChanged(object? sender, PropertyChangedEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.PropertyName == Binding.IndexerName)
|
if (e.PropertyName != Binding.IndexerName)
|
||||||
{
|
{
|
||||||
BuildLocalizedOptions();
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Translate(PlacementModes);
|
||||||
|
Translate(CursorCorners);
|
||||||
|
Translate(ScreenPositions);
|
||||||
|
}
|
||||||
|
|
||||||
|
private EnumOption<T>[] CreateOptions<T>() where T : struct, Enum =>
|
||||||
|
[.. Enum.GetValues<T>().Select(value => new EnumOption<T>(value, GetDisplayName(value)))];
|
||||||
|
|
||||||
|
private void Translate<T>(IReadOnlyList<EnumOption<T>> options) where T : struct, Enum
|
||||||
|
{
|
||||||
|
foreach (EnumOption<T> option in options)
|
||||||
|
{
|
||||||
|
option.Display = GetDisplayName(option.Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BuildLocalizedOptions()
|
// Ключ ресурса собирается из имени типа и значения: PopupPlacementMode_AtCursor
|
||||||
{
|
private string GetDisplayName<T>(T value) where T : struct, Enum =>
|
||||||
PlacementModes = BuildOptions<PopupPlacementMode>(nameof(PopupPlacementMode));
|
Localization[$"{typeof(T).Name}_{value}"];
|
||||||
CursorCorners = BuildOptions<CursorCorner>(nameof(CursorCorner));
|
|
||||||
ScreenPositions = BuildOptions<ScreenPosition>(nameof(ScreenPosition));
|
|
||||||
|
|
||||||
OnPropertyChanged(nameof(PlacementModes));
|
|
||||||
OnPropertyChanged(nameof(CursorCorners));
|
|
||||||
OnPropertyChanged(nameof(ScreenPositions));
|
|
||||||
}
|
|
||||||
|
|
||||||
private EnumOption<T>[] BuildOptions<T>(string resourcePrefix) where T : struct, Enum =>
|
|
||||||
[.. Enum.GetValues<T>().Select(value => new EnumOption<T>(value, Localization[$"{resourcePrefix}_{value}"]))];
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user