如何通过字符串值获取Tabs类常量并打开WPF对应标签页
问题描述
现有WPF客户端代码可通过直接引用Tabs.Employee常量打开对应标签页:
class Startup { public void Init() { var screen = Tabs.Employee; Tabs.OpenTab(screen, null); } }
希望实现通过传入字符串动态获取对应Tabs常量的逻辑,类似:
string screenName = "Employee"; var screen = Tabs.screenName; // 期望的动态调用方式
Tabs类定义如下:
public class Tabs { public delegate void AddDockTab(string controlName, object argument = null); public const string Empty = "Empty"; public const string Employee = "Employee"; public const string Customer = "Customer"; private static UnicontaTabs utab; public static event AddDockTab OnAddDockTab; protected Tabs() { utab = this; } public static void OpenTab(string controlName, object argument) { if (utab != null) { utab.AddTab(controlName, argument); } } protected virtual void AddTab(string controlName, object argument) { Tabs.OnAddDockTab?.Invoke(controlName, argument); } public static IEnumerable<string> GetControlNames() { FieldInfo[] fields = typeof(Tabs).GetFields(BindingFlags.Static | BindingFlags.Public); return fields.Select((FieldInfo f) => f.Name); } }
解决方案
以下三种方法可实现动态传值调用:
方法1:利用反射动态获取常量值
Tabs类已有反射相关的GetControlNames方法,可扩展一个静态方法,通过字段名动态获取对应常量值:
public class Tabs { // 保留原有代码... public static string GetControlValue(string controlName) { // 获取指定名称的静态公共字段 var field = typeof(Tabs).GetField(controlName, BindingFlags.Static | BindingFlags.Public); // 验证字段是否为常量 if (field != null && field.IsLiteral && !field.IsInitOnly) { return field.GetValue(null) as string; } // 未找到时返回默认的Empty常量 return Empty; } }
调用示例:
string screenName = "Employee"; var screen = Tabs.GetControlValue(screenName); Tabs.OpenTab(screen, null);
方法2:静态字典映射(避免反射开销)
如果担心反射的性能问题,可以提前在Tabs类中维护一个字段名与常量值的映射字典,查询效率更高:
public class Tabs { // 保留原有代码... // 静态字典存储字段名和对应常量值 private static readonly Dictionary<string, string> _controlMap = new Dictionary<string, string> { { nameof(Empty), Empty }, { nameof(Employee), Employee }, { nameof(Customer), Customer } }; public static string GetControlValue(string controlName) { // 尝试从字典中取值,失败则返回Empty return _controlMap.TryGetValue(controlName, out var value) ? value : Empty; } }
调用方式与方法1完全一致。
方法3:改用枚举类型(更类型安全)
如果允许调整Tabs类的设计,改用枚举管理标签页名称会更规范,同时支持字符串与枚举的互转:
- 先定义枚举:
public enum TabControlName { Empty, Employee, Customer }
- 修改Tabs类适配枚举:
public class Tabs { public delegate void AddDockTab(string controlName, object argument = null); private static UnicontaTabs utab; public static event AddDockTab OnAddDockTab; protected Tabs() { utab = this; } // 新增枚举重载的OpenTab方法 public static void OpenTab(TabControlName controlName, object argument) { OpenTab(controlName.ToString(), argument); } // 保留原有字符串参数的OpenTab方法 public static void OpenTab(string controlName, object argument) { if (utab != null) { utab.AddTab(controlName, argument); } } protected virtual void AddTab(string controlName, object argument) { Tabs.OnAddDockTab?.Invoke(controlName, argument); } // 重写GetControlNames,从枚举获取名称 public static IEnumerable<string> GetControlNames() { return Enum.GetNames(typeof(TabControlName)); } // 字符串转枚举的方法,处理无效输入 public static bool TryGetControlEnum(string controlName, out TabControlName tabEnum) { return Enum.TryParse(controlName, out tabEnum); } }
调用示例:
string screenName = "Employee"; if (Tabs.TryGetControlEnum(screenName, out var tabEnum)) { Tabs.OpenTab(tabEnum, null); } else { // 处理无效标签页名称的情况 Tabs.OpenTab(TabControlName.Empty, null); }
内容的提问来源于stack exchange,提问作者Kresten
相关产品推荐
相关产品推荐

