From 7fbedddea4fdbc6db5d8b2dee2feb26be633ba46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BE=89=E9=B8=AD=E8=9B=8B?= Date: Tue, 27 Jan 2026 03:49:34 +0800 Subject: [PATCH] =?UTF-8?q?refactor(AutoTranslateInterceptor):=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E8=87=AA=E5=8A=A8=E7=BF=BB=E8=AF=91=E6=8B=A6=E6=88=AA?= =?UTF-8?q?=E5=99=A8=E7=9A=84=E5=8A=A0=E8=BD=BD=E4=B8=8E=E5=BA=94=E7=94=A8?= =?UTF-8?q?=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除 HomePage 中冗余的 EnableAutoTranslate 属性设置,改为继承属性 - 通过类构造函数注册全局 Loaded 事件处理器,替代在每个元素上单独添加 - 引入请求队列机制,批量处理待应用翻译的元素,避免重复调度 - 扩展属性类型检查,支持 object 类型以处理更多动态内容场景 --- .../View/Behavior/AutoTranslateInterceptor.cs | 116 ++++++++++++++++-- BetterGenshinImpact/View/Pages/HomePage.xaml | 2 - 2 files changed, 107 insertions(+), 11 deletions(-) diff --git a/BetterGenshinImpact/View/Behavior/AutoTranslateInterceptor.cs b/BetterGenshinImpact/View/Behavior/AutoTranslateInterceptor.cs index 65c05bd9..432b2ed1 100644 --- a/BetterGenshinImpact/View/Behavior/AutoTranslateInterceptor.cs +++ b/BetterGenshinImpact/View/Behavior/AutoTranslateInterceptor.cs @@ -13,12 +13,29 @@ namespace BetterGenshinImpact.View.Behavior { public static class AutoTranslateInterceptor { + static AutoTranslateInterceptor() + { + EventManager.RegisterClassHandler( + typeof(FrameworkElement), + FrameworkElement.LoadedEvent, + new RoutedEventHandler(OnAnyElementLoaded), + true); + EventManager.RegisterClassHandler( + typeof(FrameworkContentElement), + FrameworkContentElement.LoadedEvent, + new RoutedEventHandler(OnAnyElementLoaded), + true); + } + public static readonly DependencyProperty EnableAutoTranslateProperty = DependencyProperty.RegisterAttached( "EnableAutoTranslate", typeof(bool), typeof(AutoTranslateInterceptor), - new PropertyMetadata(false, OnEnableAutoTranslateChanged)); + new FrameworkPropertyMetadata( + false, + FrameworkPropertyMetadataOptions.Inherits, + OnEnableAutoTranslateChanged)); public static void SetEnableAutoTranslate(DependencyObject element, bool value) => element.SetValue(EnableAutoTranslateProperty, value); @@ -33,6 +50,68 @@ namespace BetterGenshinImpact.View.Behavior typeof(AutoTranslateInterceptor), new PropertyMetadata(null)); + private static void OnAnyElementLoaded(object sender, RoutedEventArgs e) + { + if (sender is not DependencyObject obj) + { + return; + } + + FindNearestScope(obj)?.RequestApply(obj); + } + + private static Scope? FindNearestScope(DependencyObject obj) + { + DependencyObject? current = obj; + while (current != null) + { + if (current is FrameworkElement fe && fe.GetValue(ScopeProperty) is Scope scope) + { + return scope; + } + + current = GetParentObject(current); + } + + return null; + } + + private static DependencyObject? GetParentObject(DependencyObject obj) + { + if (obj is FrameworkElement fe) + { + if (fe.Parent != null) + { + return fe.Parent; + } + + if (fe.TemplatedParent is DependencyObject templatedParent) + { + return templatedParent; + } + } + + if (obj is FrameworkContentElement fce) + { + if (fce.Parent != null) + { + return fce.Parent; + } + + if (fce.TemplatedParent is DependencyObject templatedParent) + { + return templatedParent; + } + } + + if (obj is Visual || obj is System.Windows.Media.Media3D.Visual3D) + { + return VisualTreeHelper.GetParent(obj); + } + + return LogicalTreeHelper.GetParent(obj); + } + private static void OnEnableAutoTranslateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (d is not FrameworkElement fe) @@ -76,16 +155,14 @@ namespace BetterGenshinImpact.View.Behavior private readonly FrameworkElement _root; private readonly List _unsubscribe = new(); private bool _applied; - private readonly RoutedEventHandler _anyLoadedHandler; private readonly HashSet _trackedContextMenus = new(); private readonly HashSet _trackedToolTips = new(); + private readonly HashSet _pendingApply = new(); + private bool _applyScheduled; public Scope(FrameworkElement root) { _root = root; - _anyLoadedHandler = OnAnyLoaded; - _root.AddHandler(FrameworkElement.LoadedEvent, _anyLoadedHandler, true); - _unsubscribe.Add(() => _root.RemoveHandler(FrameworkElement.LoadedEvent, _anyLoadedHandler)); } public void OnLoaded(object sender, RoutedEventArgs e) @@ -131,20 +208,41 @@ namespace BetterGenshinImpact.View.Behavior _unsubscribe.Clear(); } - private void OnAnyLoaded(object sender, RoutedEventArgs e) + public void RequestApply(DependencyObject obj) { if (!_applied) { return; } - if (e.OriginalSource is not DependencyObject obj) + if (!_pendingApply.Add(obj)) { return; } + if (_applyScheduled) + { + return; + } + + _applyScheduled = true; _root.Dispatcher.BeginInvoke( - () => Apply(obj), + () => + { + _applyScheduled = false; + if (!_applied) + { + _pendingApply.Clear(); + return; + } + + var items = _pendingApply.ToArray(); + _pendingApply.Clear(); + foreach (var item in items) + { + Apply(item); + } + }, DispatcherPriority.Loaded); } @@ -325,7 +423,7 @@ namespace BetterGenshinImpact.View.Behavior { var entry = enumerator.Current; var property = entry.Property; - if (property.PropertyType != typeof(string)) + if (property.PropertyType != typeof(string) && property.PropertyType != typeof(object)) { continue; } diff --git a/BetterGenshinImpact/View/Pages/HomePage.xaml b/BetterGenshinImpact/View/Pages/HomePage.xaml index f2677e4c..fb31c5a2 100644 --- a/BetterGenshinImpact/View/Pages/HomePage.xaml +++ b/BetterGenshinImpact/View/Pages/HomePage.xaml @@ -7,7 +7,6 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:pages="clr-namespace:BetterGenshinImpact.ViewModel.Pages" xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml" - xmlns:behavior="clr-namespace:BetterGenshinImpact.View.Behavior" Title="HomePage" d:DataContext="{d:DesignInstance Type=pages:HomePageViewModel}" d:DesignHeight="850" @@ -16,7 +15,6 @@ ui:Design.Foreground="{DynamicResource TextFillColorPrimaryBrush}" FontFamily="{StaticResource TextThemeFontFamily}" Foreground="{DynamicResource TextFillColorPrimaryBrush}" - behavior:AutoTranslateInterceptor.EnableAutoTranslate="True" mc:Ignorable="d">