TrykleMvvmToolkit.Wpf 缝合 x:Static 和 DynamicResource(静态属性动态绑定,i18n多语言支持)

希望自定义一个扩展标记,将静态属性绑定到控件上,并且可以通知

这样做的目的

  • DynamicResource 不太方便编写,比如做多语言,可能需要写多份同Key不同Value的文件,但DynamicResource天生具有通知能力,并且可以在设计时显示默认值
  • x:Static 可以在VS上设计时显示默认值,但net4.5提供的静态属性通知不能进行继承,继承类无法被正确调用,代码编写负担加重
  • {DynamicResource {x:Static SystemColors.ControlTextBrushKey}} 这样子的写法设计器只识别系统的属性

于是我将 DynamicResource 和x:Static 放在一起变成

Text="{t:DynamicStaticProperty local:Lang.Btn1Text}"

原理

以StaticExtension基类派生,以类型和属性名组合一个内部key,
设置输入的值到Application.Current.Resources,
如果左边是依赖属性则返回DynamicResource表达式的值
如果非依赖属性则返回原有静态值
下面的静态属性类,在Set方法中,会内部将Application.Current.Resources的值进行变更
也就是说,调用 x:Static 基类解析,但是返回 DynamicResource 的表达式结果
(传递的泛型类型为内部key的一部分)

 public class Lang : DynamicStaticPropertyBase<Lang>
    { 
        public static string Btn1Text { get => Get("Apple"); set => Set(value); }

        public static void SelectLangCN()
        {
            Btn1Text = "苹果";
        }
        public static void SelectLangEN()
        {
            Btn1Text = "APPPPPle";
        }
    }

演进步骤

多语言

这个扩展本身为多语言而编写,但目前自己并没有做多语言的经验和需求
所以暂时就搞这么多,也许以后会类似这样的操作

public class Lang : DynamicStaticPropertyBase<Lang>
    {
        [Lang(LangType.CN, "苹果")]
        [Lang(LangType.CN, "Appppppple")]
        public static string Btn1Text { get => Get("Apple"); set => Set(value); }


        //底层实现切换语言自动反射、自动载入文件等方式
    }

    public enum LangType
    {
        CN,
        EN,
    }

    [AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
    public class LangAttribute : Attribute
    {
        public LangAttribute(object LangType, string text)
        {

        }
    }

2022.12.11 已完善
对于非常量字面类型的值还支持调用方法设置,或者从文件读取值

 SetLangKeyValue(LangType.EN, nameof(BackColor), new SolidColorBrush(Colors.Red));

2023.1.2 新的问题

绑定的对象是当前vm实例,格式化字符串是静态的
静态的变化将不会触发变更

<TextBlock Text="{Binding SelectedIndex, StringFormat={t:DynamicStaticProperty local:Lang.IndexFormat}}" />
  • 目前的操作,就只能一个一个拼控件了,把需要多语言的控件拆开
posted @ 2022-10-24 13:30  trykle  阅读(169)  评论(0)    收藏  举报