C
C#4mo ago
Honza K.

Avalonia UI - binding in markup extension?

Hi, I'm trying to create a localization extension for my new desktop app and I want to support binding in my localization markup extension, how can I do that? I can receive the binding (CompiledBindingExtension) as a parameter and somehow I managed to get a value out of it to translate it but only by changing the Converter instance in the binding, which can be no-go in the future and also if I changed the language, all other localized strings changed because I used a ReflectionBinding for them but I don't know how to do it when I accept binding as a parameter? I'm kinda lost... Can anyone help me please? Here is my current implementation that only accept string keys: (I deleted the implementation for the binding as it was not working properly...)
1 Reply
Honza K.
Honza K.4mo ago
public class StringLocalizationExtension : MarkupExtension
{
#pragma warning disable IDE0290 // Use primary constructor
public StringLocalizationExtension(string key)
{
Key = key;
}
#pragma warning restore IDE0290 // Use primary constructor
public string? Key { get; set; }

public override object ProvideValue(IServiceProvider serviceProvider)
{
var binding = new ReflectionBindingExtension($"[{Key}]")
{
Mode = BindingMode.OneWay,
Source = Internal.StringLocalizationResolver.Instance,
};

return binding.ProvideValue(serviceProvider);
}
}

public class StringLocalizationResolver(ICAFluentUINet.Abstractions.Localization.IStringLocalizer stringLocalizer) : INotifyPropertyChanged
{
private readonly IStringLocalizer _stringLocalizer = stringLocalizer;
private const string IndexerName = "Item";
private const string IndexerArrayName = "Item[]";

#pragma warning disable CS8612 // Nullability of reference types in type doesn't match implicitly implemented member.
public event PropertyChangedEventHandler PropertyChanged;
#pragma warning restore CS8612 // Nullability of reference types in type doesn't match implicitly implemented member.
public static StringLocalizationResolver? Instance { get; set; }

public string this[string key] => _stringLocalizer.Get(key);

public void Invalidate()
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(IndexerName));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(IndexerArrayName));
}
}
public class StringLocalizationExtension : MarkupExtension
{
#pragma warning disable IDE0290 // Use primary constructor
public StringLocalizationExtension(string key)
{
Key = key;
}
#pragma warning restore IDE0290 // Use primary constructor
public string? Key { get; set; }

public override object ProvideValue(IServiceProvider serviceProvider)
{
var binding = new ReflectionBindingExtension($"[{Key}]")
{
Mode = BindingMode.OneWay,
Source = Internal.StringLocalizationResolver.Instance,
};

return binding.ProvideValue(serviceProvider);
}
}

public class StringLocalizationResolver(ICAFluentUINet.Abstractions.Localization.IStringLocalizer stringLocalizer) : INotifyPropertyChanged
{
private readonly IStringLocalizer _stringLocalizer = stringLocalizer;
private const string IndexerName = "Item";
private const string IndexerArrayName = "Item[]";

#pragma warning disable CS8612 // Nullability of reference types in type doesn't match implicitly implemented member.
public event PropertyChangedEventHandler PropertyChanged;
#pragma warning restore CS8612 // Nullability of reference types in type doesn't match implicitly implemented member.
public static StringLocalizationResolver? Instance { get; set; }

public string this[string key] => _stringLocalizer.Get(key);

public void Invalidate()
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(IndexerName));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(IndexerArrayName));
}
}