mirror of
https://github.com/babalae/better-genshin-impact.git
synced 2026-03-15 07:43:20 +08:00
refactor(AutoTranslateInterceptor): 优化自动翻译拦截器的加载与应用机制
- 移除 HomePage 中冗余的 EnableAutoTranslate 属性设置,改为继承属性 - 通过类构造函数注册全局 Loaded 事件处理器,替代在每个元素上单独添加 - 引入请求队列机制,批量处理待应用翻译的元素,避免重复调度 - 扩展属性类型检查,支持 object 类型以处理更多动态内容场景
This commit is contained in:
@@ -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<Action> _unsubscribe = new();
|
||||
private bool _applied;
|
||||
private readonly RoutedEventHandler _anyLoadedHandler;
|
||||
private readonly HashSet<ContextMenu> _trackedContextMenus = new();
|
||||
private readonly HashSet<ToolTip> _trackedToolTips = new();
|
||||
private readonly HashSet<DependencyObject> _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;
|
||||
}
|
||||
|
||||
@@ -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">
|
||||
|
||||
<b:Interaction.Triggers>
|
||||
|
||||
Reference in New Issue
Block a user