Re-evaluate all values in xaml page calculated by a markup-extension

前端 未结 2 994
有刺的猬
有刺的猬 2020-12-09 13:36

In a xamarin app on a xaml page I am loading localized strings using a xaml extension (the details are described here). For example:

2条回答
  •  自闭症患者
    2020-12-09 14:15

    I'd tried to implement @Grx70's great proposed solution, but some of the classes and properties the example used are internal to Xamarin so couldn't be used in that way. Picking up on their last comment though, was the clue to get it working, though not quite as elegantly as initially proposed, we can do this:

    public class TranslateExtension : IMarkupExtension
    {       
        public TranslateExtension(string text)
        {
            Text = text;            
        }
    
        public string Text { get; set; }
    
        object IMarkupExtension.ProvideValue(IServiceProvider serviceProvider)
        {
        return ProvideValue(serviceProvider);
        }
    
        public BindingBase ProvideValue(IServiceProvider serviceProvider)
        {
            var binding = new Binding
            {
                Mode = BindingMode.OneWay,
                Path = $"[{Text}]",
            Source = Translator.Instance,
            };
        return binding;
        }        
    }
    

    and this the Translator class as initially proposed, but reproduced here for clarity with the GetString call:

    public class Translator : INotifyPropertyChanged
    {
        public string this[string text]
        {
        get
        {
            return Strings.ResourceManager.GetString(text, Strings.Culture);
        }
        }        
    
        public static Translator Instance { get; } = new Translator();
    
        public event PropertyChangedEventHandler PropertyChanged;
    
        public void Invalidate()
        {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(null));
        }
    }
    

    Then as the original post suggested, instead of binding text with:

    {i18n:Translate Label_Text}
    

    Bind

    {Binding [Label_Text], Source={x:Static i18n:Translator.Instance}}
    

    I'd hit this right at the end of a project (adding the multiple languages), but using Visual Studio Community and Search/Replace with RegEx, the binding can be replaced across the project, replacing:

    \{resources:Translate (.*?)\}
    

    with:

    {Binding [$1], Source={x:Static core:Translator.Instance}}
    

    NOTE: The Regex assumes the 'resources' namespace for the original Translate macro, and 'core' namespace for the Translator class, you may have to update as appropriate. I appreciate this is a small tweak to @Grx70's otherwise great solution (I'm standing on the shoulders of giants with this one), but I'm posting this here for any that follow with the same problem of getting this working.

提交回复
热议问题