Cache selected views in SimpleViewLocator

Add a `ConditionalWeakTable`-based view cache keyed by view model instance for `MsgViewModel`, `ClashProxiesViewModel`, and `ClashConnectionsViewModel` so repeated bindings reuse the same control. The locator now also handles missing registrations and null factory results more explicitly by returning descriptive `TextBlock` messages.
This commit is contained in:
2dust
2026-09-04 15:14:00 +08:00
parent b8e8321603
commit 8ebbd7f4f8

View File

@@ -1,3 +1,4 @@
using System.Runtime.CompilerServices;
using Avalonia.Controls.Templates;
using v2rayN.Desktop.ViewModels;
using v2rayN.Desktop.Views;
@@ -9,6 +10,7 @@ public class SimpleViewLocator : IDataTemplate
private static readonly Lazy<SimpleViewLocator> _instance = new(() => new SimpleViewLocator());
private readonly Dictionary<Type, Func<Control?>> _locator = new();
private readonly ConditionalWeakTable<object, Control> _cachedViews = new();
private SimpleViewLocator()
{
@@ -45,9 +47,18 @@ public class SimpleViewLocator : IDataTemplate
return new TextBlock { Text = "No VM provided" };
}
_locator.TryGetValue(data.GetType(), out var factory);
var vmType = data.GetType();
if (!_locator.TryGetValue(vmType, out var factory))
{
return new TextBlock { Text = $"VM Not Registered: {vmType}" };
}
return factory?.Invoke() ?? new TextBlock { Text = $"VM Not Registered: {data.GetType()}" };
if (ShouldCache(vmType))
{
return _cachedViews.GetValue(data, _ => CreateView(factory, vmType));
}
return CreateView(factory, vmType);
}
public bool Match(object? data)
@@ -55,6 +66,18 @@ public class SimpleViewLocator : IDataTemplate
return data is MyReactiveObject;
}
private static bool ShouldCache(Type vmType)
{
return vmType == typeof(MsgViewModel)
|| vmType == typeof(ClashProxiesViewModel)
|| vmType == typeof(ClashConnectionsViewModel);
}
private static Control CreateView(Func<Control?> factory, Type vmType)
{
return factory.Invoke() ?? new TextBlock { Text = $"View Factory Returned Null: {vmType}" };
}
public void RegisterViewFactory<TViewModel>(Func<Control> factory) where TViewModel : class
{
_locator.Add(typeof(TViewModel), factory);