LangExtension.cs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. using System;
  2. using System.Windows;
  3. using System.Windows.Data;
  4. using System.Windows.Markup;
  5. using HandyControl.Properties.Langs;
  6. namespace HandyControl.Tools.Extension;
  7. public class LangExtension : MarkupExtension
  8. {
  9. private readonly DependencyObject _proxy;
  10. public LangExtension()
  11. {
  12. _proxy = new DependencyObject();
  13. Source = LangProvider.Instance;
  14. }
  15. public LangExtension(string key) : this()
  16. {
  17. Key = key;
  18. }
  19. public static readonly DependencyProperty KeyProperty = DependencyProperty.RegisterAttached(
  20. "Key", typeof(object), typeof(LangExtension), new PropertyMetadata(default));
  21. public object Key
  22. {
  23. get => _proxy.GetValue(KeyProperty);
  24. set => _proxy.SetValue(KeyProperty, value);
  25. }
  26. private static readonly DependencyProperty TargetPropertyProperty = DependencyProperty.RegisterAttached(
  27. "TargetProperty", typeof(DependencyProperty), typeof(LangExtension), new PropertyMetadata(default(DependencyProperty)));
  28. private static void SetTargetProperty(DependencyObject element, DependencyProperty value)
  29. => element.SetValue(TargetPropertyProperty, value);
  30. private static DependencyProperty GetTargetProperty(DependencyObject element)
  31. => (DependencyProperty) element.GetValue(TargetPropertyProperty);
  32. public BindingMode Mode { get; set; }
  33. public IValueConverter Converter { get; set; }
  34. public object ConverterParameter { get; set; }
  35. public object Source { get; set; }
  36. public override object ProvideValue(IServiceProvider serviceProvider)
  37. {
  38. if (!(serviceProvider.GetService(typeof(IProvideValueTarget)) is IProvideValueTarget provideValueTarget)) return this;
  39. if (provideValueTarget.TargetObject.GetType().FullName == "System.Windows.SharedDp") return this;
  40. if (!(provideValueTarget.TargetObject is DependencyObject targetObject)) return this;
  41. if (!(provideValueTarget.TargetProperty is DependencyProperty targetProperty)) return this;
  42. switch (Key)
  43. {
  44. case string key:
  45. {
  46. var binding = CreateLangBinding(key);
  47. BindingOperations.SetBinding(targetObject, targetProperty, binding);
  48. return binding.ProvideValue(serviceProvider);
  49. }
  50. case Binding keyBinding when targetObject is FrameworkElement element:
  51. {
  52. if (element.DataContext != null)
  53. {
  54. var binding = SetLangBinding(element, targetProperty, keyBinding.Path, element.DataContext);
  55. return binding.ProvideValue(serviceProvider);
  56. }
  57. SetTargetProperty(element, targetProperty);
  58. element.DataContextChanged += LangExtension_DataContextChanged;
  59. break;
  60. }
  61. case Binding keyBinding when targetObject is FrameworkContentElement element:
  62. {
  63. if (element.DataContext != null)
  64. {
  65. var binding = SetLangBinding(element, targetProperty, keyBinding.Path, element.DataContext);
  66. return binding.ProvideValue(serviceProvider);
  67. }
  68. SetTargetProperty(element, targetProperty);
  69. element.DataContextChanged += LangExtension_DataContextChanged;
  70. break;
  71. }
  72. }
  73. return string.Empty;
  74. }
  75. private void LangExtension_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
  76. {
  77. switch (sender)
  78. {
  79. case FrameworkElement element:
  80. {
  81. element.DataContextChanged -= LangExtension_DataContextChanged;
  82. if (!(Key is Binding keyBinding)) return;
  83. var targetProperty = GetTargetProperty(element);
  84. SetTargetProperty(element, null);
  85. SetLangBinding(element, targetProperty, keyBinding.Path, element.DataContext);
  86. break;
  87. }
  88. case FrameworkContentElement element:
  89. {
  90. element.DataContextChanged -= LangExtension_DataContextChanged;
  91. if (!(Key is Binding keyBinding)) return;
  92. var targetProperty = GetTargetProperty(element);
  93. SetTargetProperty(element, null);
  94. SetLangBinding(element, targetProperty, keyBinding.Path, element.DataContext);
  95. break;
  96. }
  97. }
  98. }
  99. private BindingBase SetLangBinding(DependencyObject targetObject, DependencyProperty targetProperty, PropertyPath path, object dataContext)
  100. {
  101. if (targetProperty == null) return null;
  102. BindingOperations.SetBinding(targetObject, targetProperty, new Binding
  103. {
  104. Path = path,
  105. Source = dataContext,
  106. Mode = BindingMode.OneWay
  107. });
  108. var key = targetObject.GetValue(targetProperty) as string;
  109. if (string.IsNullOrEmpty(key)) return null;
  110. var binding = CreateLangBinding(key);
  111. BindingOperations.SetBinding(targetObject, targetProperty, binding);
  112. return binding;
  113. }
  114. private BindingBase CreateLangBinding(string key) => new Binding(key)
  115. {
  116. Converter = Converter,
  117. ConverterParameter = ConverterParameter,
  118. UpdateSourceTrigger = UpdateSourceTrigger.Explicit,
  119. Source = Source,
  120. Mode = BindingMode.OneWay
  121. };
  122. }