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}}" />
- 目前的操作,就只能一个一个拼控件了,把需要多语言的控件拆开
浙公网安备 33010602011771号