From 251b8730b977c442edd8e2b291dcb8c7a12a7e71 Mon Sep 17 00:00:00 2001
From: lrc <571244399@qq.com>
Date: Sat, 25 Jul 2026 23:38:49 +0800
Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96ui=E7=BB=91=E5=AE=9A=E4=BE=A7?=
=?UTF-8?q?=E9=80=BB=E8=BE=91?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../Scripts/AvrgBindingTrie.cs | 77 ++++++
.../Scripts/AvrgMemberMetaDataSet.cs | 16 ++
.../Scripts/AvrgMvvmBinding.cs | 64 ++++-
.../Scripts/AvrgMvvmBindingCollection.cs | 48 +++-
.../Scripts/AvrgMvvmScheduler.cs | 123 ++++++---
.../Scripts/AvrgSubPropertyAccessor.cs | 79 ++++++
.../Scripts/ValidationState.cs | 13 +
.../Scripts/XuiFieldTempEntry.cs | 4 +-
.../Scripts/XuiavrgInspectorManager.cs | 14 +-
.../AvrgValues/XUIAvrgMDColorValue.cs | 37 +--
.../AvrgValues/XUIAvrgMDDropdownValue.cs | 61 +++--
.../AvrgValues/XUIAvrgMDInputFieldValue.cs | 71 +++--
.../AvrgValues/XUIAvrgMDLabelValue.cs | 44 +---
.../AvrgValues/XUIAvrgMDSliderValue.cs | 105 ++++----
.../AvrgValues/XUIAvrgMDTextureValue.cs | 51 ++--
.../AvrgValues/XUIAvrgMDToggleGroupValue.cs | 11 +-
.../AvrgValues/XUIAvrgMDToggleValue.cs | 69 ++---
.../OverrideUI/AvrgValues/XUIAvrgMDValue.cs | 247 ++++++++++--------
.../AvrgValues/XUIAvrgMDVectorValue.cs | 84 ++----
19 files changed, 782 insertions(+), 436 deletions(-)
create mode 100644 Runtime/InterfaceAttributeReflectionGenerator/Scripts/AvrgBindingTrie.cs
create mode 100644 Runtime/InterfaceAttributeReflectionGenerator/Scripts/AvrgSubPropertyAccessor.cs
create mode 100644 Runtime/InterfaceAttributeReflectionGenerator/Scripts/ValidationState.cs
diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/AvrgBindingTrie.cs b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/AvrgBindingTrie.cs
new file mode 100644
index 0000000..feeb9e1
--- /dev/null
+++ b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/AvrgBindingTrie.cs
@@ -0,0 +1,77 @@
+using System.Collections.Generic;
+
+namespace XericUI.ReflectionUIGenerator
+{
+ ///
+ /// 绑定名称前缀树(Trie),支持通过完整路径或成员名后缀快速查找 AvrgMvvmBinding。
+ ///
+ /// 使用场景:
+ /// - Find("XericUI.MyData.speed") → 完整路径精确命中
+ /// - FindByMemberName("speed") → 沿 Trie 叶节点查找末段匹配
+ ///
+ /// 在 BuildMDVM 时构建,绑定到 AvrgMvvmBindingCollection。
+ ///
+ internal class AvrgBindingTrie
+ {
+ private class Node
+ {
+ public AvrgMvvmBinding Binding;
+ public readonly Dictionary Children = new();
+ }
+
+ private readonly Node _root = new();
+ private readonly Dictionary _memberNameIndex = new();
+
+ public void Insert(string fullPath, AvrgMvvmBinding binding)
+ {
+ if (string.IsNullOrEmpty(fullPath) || binding == null) return;
+
+ var parts = fullPath.Split('.');
+ var current = _root;
+ foreach (var part in parts)
+ {
+ if (!current.Children.TryGetValue(part, out var child))
+ {
+ child = new Node();
+ current.Children[part] = child;
+ }
+ current = child;
+ }
+ current.Binding = binding;
+
+ // 同时建成员名索引(末段)
+ string memberName = parts[parts.Length - 1];
+ if (!_memberNameIndex.ContainsKey(memberName))
+ _memberNameIndex[memberName] = binding;
+ }
+
+ /// 通过完整路径精确查找(如 "XericUI.MyData.speed")
+ public AvrgMvvmBinding Find(string fullPath)
+ {
+ if (string.IsNullOrEmpty(fullPath)) return null;
+
+ var parts = fullPath.Split('.');
+ var current = _root;
+ foreach (var part in parts)
+ {
+ if (!current.Children.TryGetValue(part, out current))
+ return null;
+ }
+ return current?.Binding;
+ }
+
+ /// 通过成员名查找(如 "speed")— O(1) 直接索引
+ public AvrgMvvmBinding FindByMemberName(string memberName)
+ {
+ _memberNameIndex.TryGetValue(memberName, out var binding);
+ return binding;
+ }
+
+ /// 清除所有索引
+ public void Clear()
+ {
+ _root.Children.Clear();
+ _memberNameIndex.Clear();
+ }
+ }
+}
diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/AvrgMemberMetaDataSet.cs b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/AvrgMemberMetaDataSet.cs
index 56be430..9c1fde4 100644
--- a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/AvrgMemberMetaDataSet.cs
+++ b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/AvrgMemberMetaDataSet.cs
@@ -91,6 +91,12 @@ namespace XericUI.ReflectionUIGenerator
bindingCollection.SourceMetaDataSet = this;
var scheduler = new AvrgMvvmScheduler(resolverConfig);
+ // ★ 构建前缀树索引
+ var trie = new AvrgBindingTrie();
+ string typePrefix = businessTarget != null
+ ? businessTarget.GetType().FullName + "."
+ : "";
+
foreach (var metaData in _metaDataList)
{
if (metaData.AccessorFactory == null) continue;
@@ -137,9 +143,14 @@ namespace XericUI.ReflectionUIGenerator
string subPath = subMetaData.PropertyPath;
if (string.IsNullOrEmpty(subPath)) continue;
+ // 创建子属性访问器
+ var subAccessor = new AvrgSubPropertyAccessor(
+ accessor, subPath, subMetaData);
+
var subBinding = new AvrgMvvmBinding
{
MetaData = subMetaData,
+ Accessor = subAccessor,
ReadFunc = () => ReadSubProperty(accessor.GetValue(), subPath),
WriteAction = (val) =>
{
@@ -157,8 +168,13 @@ namespace XericUI.ReflectionUIGenerator
// 注册到调度器
scheduler.Register(binding);
bindingCollection.Add(binding);
+
+ // ★ 插入前缀树(完整路径: Type.FullName.MemberName)
+ string fullPath = typePrefix + metaData.MemberName;
+ trie.Insert(fullPath, binding);
}
+ bindingCollection.SetTrie(trie);
bindingCollection.AttachScheduler(scheduler);
return bindingCollection;
}
diff --git a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/AvrgMvvmBinding.cs b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/AvrgMvvmBinding.cs
index c8faa0f..757e32b 100644
--- a/Runtime/InterfaceAttributeReflectionGenerator/Scripts/AvrgMvvmBinding.cs
+++ b/Runtime/InterfaceAttributeReflectionGenerator/Scripts/AvrgMvvmBinding.cs
@@ -45,21 +45,75 @@ namespace XericUI.ReflectionUIGenerator
/// 数据侧写入的缓存值
public object DataCachedValue { get; set; }
+ // ============ 验证状态 ============
+
+ private ValidationState _validationState = ValidationState.Normal;
+
+ /// 当前验证状态
+ public ValidationState CurrentValidationState => _validationState;
+
+ /// 验证状态变更事件 — UI 组件订阅以切换样式
+ public event Action OnValidationStateChanged;
+
+ ///
+ /// 校验值是否满足元数据约束
+ /// 返回:Normal(通过)、Warning(放行但警告)、Invalid(驳回)
+ ///
+ public ValidationState ValidateValue(object value)
+ {
+ if (MetaData == null) return ValidationState.Normal;
+
+ // 1. 空值检查(Required)
+ if (MetaData.Required && (value == null || (value is string s && string.IsNullOrEmpty(s))))
+ return ValidationState.Invalid;
+
+ // 2. 范围检查(RangeMin/RangeMax)
+ if (value is IConvertible)
+ {
+ float num = Convert.ToSingle(value);
+
+ if (MetaData.RangeMin.HasValue && num < MetaData.RangeMin.Value)
+ return ValidationState.Invalid;
+
+ if (MetaData.RangeMax.HasValue && num > MetaData.RangeMax.Value)
+ return ValidationState.Invalid;
+ }
+
+ return ValidationState.Normal;
+ }
+
+ /// 更新验证状态并触发回调(仅状态变化时触发)
+ internal void SetValidationState(ValidationState newState)
+ {
+ if (_validationState != newState)
+ {
+ _validationState = newState;
+ OnValidationStateChanged?.Invoke(_validationState);
+ }
+ }
+
+ /// 重置验证状态为 Normal(不触发事件)
+ internal void ResetValidationState()
+ {
+ _validationState = ValidationState.Normal;
+ }
+
// ============ UI 绑定 ============
- /// UI 值变更回调委托 — UI 组件订阅此回调以更新显示
- public Action