XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEExtension.NetCore.WinUIHelper

【DLL】WinUI的各种工具类,帮助开发者快速构建一个模块化的WinUI项目

公开
关注 0 Fork 0 Star 0
返回提交历史

XFEstudio/XFEExtension.NetCore.WinUIHelper

新增导航、权限管理及搜索相关功能支持

新增导航附加属性类 `NavigationAddition`,支持为 `NavigationViewItem` 指定导航目标和参数。 引入 `CommunityToolkit.Mvvm`,支持 MVVM 模式下的属性通知。 新增多个抽象类和接口(如 `AutoNavigatableViewModelBase`、`SearchableViewModelBase`、`IListViewModel` 等),实现搜索、导航和权限管理功能。 新增 `PermissionVisibilityService` 和 `PermissionAddition`,支持基于权限级别的 UI 可见性管理。 新增工具类 `ObjectHelper` 和 `PermissionHelper`,提供对象搜索、值复制及权限可见性设置等功能。

0298b1c
XFE工作室室长 <mail@xfegzs.com>
提交于

代码差异

14 个文件 +508 -1
Added XFEExtension.NetCore.WinUIHelper/Implements/AutoNavigatableViewModelBase.cs +9 -0
@@ -0,0 +1,9 @@
1 using XFEExtension.NetCore.WinUIHelper.Interface.Services;
2 using XFEExtension.NetCore.WinUIHelper.Utilities;
3
4 namespace XFEExtension.NetCore.WinUIHelper.Implements;
5
6 public abstract partial class AutoNavigatableViewModelBase<T> : ViewModelBase
7 {
8 public IAutoNavigationParameterService<T> AutoNavigationParameterService { get; } = ServiceManager.GetService<IAutoNavigationParameterService<T>>();
9 }
Added XFEExtension.NetCore.WinUIHelper/Implements/SearchableViewModelBase.cs +35 -0
@@ -0,0 +1,35 @@
1 using CommunityToolkit.Mvvm.ComponentModel;
2 using System.Collections.ObjectModel;
3 using XFEExtension.NetCore.DelegateExtension;
4 using XFEExtension.NetCore.WinUIHelper.Interface;
5
6 namespace XFEExtension.NetCore.WinUIHelper.Implements;
7
8 public abstract partial class SearchableViewModelBase<T, F> : ServiceBaseViewModelBase<F>, ISearchableViewModel<T> where T : class
9 {
10 [ObservableProperty]
11 private T? selectedItem;
12 [ObservableProperty]
13 private string searchText = string.Empty;
14 public bool AutoSearch { get; set; } = true;
15 public ObservableCollection<T> ViewList { get; set; } = [];
16 public List<T> ModelList { get; set; } = [];
17 public Func<string, T, bool> SearchPredicate { get; set; } = (text, item) => ObjectHelper.Search(item, text);
18
19 public event XFEEventHandler<string>? SearchTextChanged;
20
21 partial void OnSearchTextChanged(string value)
22 {
23 SearchTextChanged?.Invoke(value);
24 if (AutoSearch)
25 Search();
26 }
27
28 protected virtual void Add() { }
29 protected virtual async Task AddAsync() => await Task.CompletedTask;
30 protected virtual void Remove() { }
31 protected virtual async Task RemoveAsync() => await Task.CompletedTask;
32 protected virtual void Edit() { }
33 protected virtual async Task EditAsync() => await Task.CompletedTask;
34 protected void Search() => (this as ISearchableViewModel<T>).SearchAndLoadToList();
35 }
Added XFEExtension.NetCore.WinUIHelper/Implements/ServiceBaseViewModelBase.cs +12 -0
@@ -0,0 +1,12 @@
1 using XFEExtension.NetCore.WinUIHelper.Interface.Services;
2 using XFEExtension.NetCore.WinUIHelper.Utilities;
3
4 namespace XFEExtension.NetCore.WinUIHelper.Implements;
5
6 public abstract partial class ServiceBaseViewModelBase<T> : AutoNavigatableViewModelBase<T>
7 {
8 public IDialogService DialogService { get; } = ServiceManager.GetService<IDialogService>();
9 public INavigationViewService? NavigationViewService { get; } = ServiceManager.GetGlobalService<INavigationViewService>();
10 public IMessageService? MessageService { get; } = ServiceManager.GetGlobalService<IMessageService>();
11 public ILoadingService? LoadingService { get; } = ServiceManager.GetGlobalService<ILoadingService>();
12 }
Added XFEExtension.NetCore.WinUIHelper/Implements/Services/PermissionVisibilityService.cs +26 -0
@@ -0,0 +1,26 @@
1 using XFEExtension.NetCore.WinUIHelper.Interface.Services;
2 using XFEExtension.NetCore.WinUIHelper.Utilities.Helpers;
3
4 namespace XFEExtension.NetCore.WinUIHelper.Implements.Services;
5
6 /// <summary>
7 /// Provides functionality to manage the visibility of page elements based on permission levels within the application.
8 /// </summary>
9 /// <remarks>Use this service to initialize the current page context and update the visibility of its child
10 /// elements according to the specified permission level. This service is typically used to control access to UI
11 /// components depending on user roles or permissions.</remarks>
12 public class PermissionVisibilityService : GlobalServiceBase, IPermissionVisibilityService
13 {
14 private Page? currentPage;
15 /// <inheritdoc/>
16 public Page? CurrentPage => currentPage;
17
18 /// <inheritdoc/>
19 public void Initialize(Page page)
20 {
21 currentPage = page;
22 }
23
24 /// <inheritdoc/>
25 public void Refresh(int permissionLevel) => PermissionHelper.SetChildVisibility(currentPage!, permissionLevel);
26 }
Added XFEExtension.NetCore.WinUIHelper/Interface/IAsyncRefreshableViewModel.cs +6 -0
@@ -0,0 +1,6 @@
1 namespace XFEExtension.NetCore.WinUIHelper.Interface;
2
3 public interface IAsyncRefreshableViewModel
4 {
5 Task RefreshAsync();
6 }
Added XFEExtension.NetCore.WinUIHelper/Interface/IListViewModel.cs +71 -0
@@ -0,0 +1,71 @@
1 using System.Collections.ObjectModel;
2
3 namespace XFEExtension.NetCore.WinUIHelper.Interface;
4
5 /// <summary>
6 /// 指定类型列表的视图模型接口
7 /// </summary>
8 /// <typeparam name="T">模型类型</typeparam>
9 public interface IListViewModel<T> where T : class
10 {
11 ObservableCollection<T> ViewList { get; set; }
12 List<T> ModelList { get; set; }
13
14 /// <summary>
15 /// 加载到视图列表
16 /// </summary>
17 /// <param name="list"></param>
18 void LoadToViewList(IEnumerable<T> list)
19 {
20 Clear();
21 foreach (var item in list)
22 Add(item);
23 }
24
25 /// <summary>
26 /// 添加到视图列表
27 /// </summary>
28 /// <param name="list"></param>
29 void AddToViewList(IEnumerable<T> list)
30 {
31 foreach (var item in list)
32 ViewList.Add(item);
33 }
34
35 /// <summary>
36 /// 清除视图列表
37 /// </summary>
38 void Clear() => ViewList.Clear();
39
40 /// <summary>
41 /// 向视图列表添加一个元素
42 /// </summary>
43 /// <param name="item"></param>
44 void Add(T item) => ViewList.Add(item);
45
46 /// <summary>
47 /// 从视图列表中移除指定元素
48 /// </summary>
49 /// <param name="item"></param>
50 void Remove(T item) => ViewList.Remove(item);
51
52 /// <summary>
53 /// 在视图列表指定位置移除一个元素
54 /// </summary>
55 /// <param name="index"></param>
56 void RemoveAt(int index) => ViewList.RemoveAt(index);
57
58 /// <summary>
59 /// 视图列表中是否包含指定元素
60 /// </summary>
61 /// <param name="item"></param>
62 /// <returns></returns>
63 bool Contains(T item) => ViewList.Contains(item);
64
65 /// <summary>
66 /// 使用指定表达式搜索模型列表(而非视图列表)
67 /// </summary>
68 /// <param name="predicte"></param>
69 /// <returns></returns>
70 IEnumerable<T> Search(Func<T, bool> predicte) => ModelList.Where(item => predicte(item));
71 }
Added XFEExtension.NetCore.WinUIHelper/Interface/IRefreshableViewModel.cs +6 -0
@@ -0,0 +1,6 @@
1 namespace XFEExtension.NetCore.WinUIHelper.Interface;
2
3 public interface IRefreshableViewModel
4 {
5 void Refresh();
6 }
Added XFEExtension.NetCore.WinUIHelper/Interface/ISearchableViewModel.cs +34 -0
@@ -0,0 +1,34 @@
1 namespace XFEExtension.NetCore.WinUIHelper.Interface;
2
3 /// <summary>
4 /// 可搜索视图模型接口
5 /// </summary>
6 /// <typeparam name="T"></typeparam>
7 public interface ISearchableViewModel<T> : IListViewModel<T> where T : class
8 {
9 /// <summary>
10 /// 搜索文本
11 /// </summary>
12 string SearchText { get; set; }
13 /// <summary>
14 /// 搜索预测
15 /// </summary>
16 Func<string, T, bool> SearchPredicate { get; set; }
17
18 /// <summary>
19 /// 搜索模型
20 /// </summary>
21 /// <returns></returns>
22 IEnumerable<T> SearchModels(string searchText) => ModelList.Where(item => SearchPredicate(searchText, item));
23
24 /// <summary>
25 /// 搜索模型
26 /// </summary>
27 /// <returns></returns>
28 IEnumerable<T> SearchModels() => ModelList.Where(item => SearchPredicate(SearchText, item));
29
30 /// <summary>
31 /// 搜索并加载模型
32 /// </summary>
33 void SearchAndLoadToList() => LoadToViewList(SearchModels());
34 }
Added XFEExtension.NetCore.WinUIHelper/Interface/Services/IPermissionVisibilityService.cs +14 -0
@@ -0,0 +1,14 @@
1 namespace XFEExtension.NetCore.WinUIHelper.Interface.Services;
2
3 /// <summary>
4 /// Provides functionality to refresh the visibility state of permissions based on the specified permission level.
5 /// </summary>
6 public interface IPermissionVisibilityService : IGlobalService, IPageService
7 {
8 /// <summary>
9 /// Refreshes the current state based on the specified permission level.
10 /// </summary>
11 /// <param name="permissionLevel">The permission level to apply during the refresh operation. Must be a non-negative integer; higher values may
12 /// grant access to additional resources.</param>
13 void Refresh(int permissionLevel);
14 }
Modified XFEExtension.NetCore.WinUIHelper/Utilities/Addition/NavigationAddition.cs +45 -1
@@ -1,17 +1,61 @@
1 1 namespace XFEExtension.NetCore.WinUIHelper.Utilities.Addition;
2 2
3 3 /// <summary>
4 /// 导航附加属性
4 /// Provides attached properties for associating navigation targets and parameters with NavigationViewItem controls.
5 5 /// </summary>
6 /// <remarks>Use the attached properties defined by this class to specify navigation destinations and parameters
7 /// for individual NavigationViewItem instances in a NavigationView. These properties enable declarative navigation
8 /// configuration in XAML or code-behind, allowing navigation logic to retrieve target information and parameters when a
9 /// navigation item is invoked.</remarks>
6 10 public class NavigationAddition
7 11 {
12 /// <summary>
13 /// Retrieves the navigation target associated with the specified navigation view item.
14 /// </summary>
15 /// <param name="item">The navigation view item from which to obtain the navigation target. Cannot be null.</param>
16 /// <returns>A string representing the navigation target for the specified item, or null if no target is set.</returns>
8 17 public static string GetNavigateTo(NavigationViewItem item) => (string)item.GetValue(NavigateToProperty);
18 /// <summary>
19 /// Sets the navigation target value for the specified NavigationViewItem.
20 /// </summary>
21 /// <remarks>Use this method to attach a navigation target to a NavigationViewItem, enabling navigation
22 /// logic to identify the destination when the item is selected.</remarks>
23 /// <param name="item">The NavigationViewItem to associate with the navigation target value. Cannot be null.</param>
24 /// <param name="value">The navigation target value to assign. This value typically represents a page key or URI used for navigation.</param>
9 25 public static void SetNavigateTo(NavigationViewItem item, string value) => item.SetValue(NavigateToProperty, value);
26 /// <summary>
27 /// Identifies the NavigateTo attached property, which specifies the navigation target as a URI or page name for
28 /// supported UI elements.
29 /// </summary>
30 /// <remarks>This dependency property can be set on UI elements to enable navigation behavior, typically
31 /// in frameworks such as WPF or UWP. The value should be a valid URI or page identifier recognized by the
32 /// navigation system. The default value is an empty string.</remarks>
10 33
11 34 public static readonly DependencyProperty NavigateToProperty = DependencyProperty.RegisterAttached("NavigateTo", typeof(string), typeof(NavigationAddition), new PropertyMetadata(""));
12 35
36 /// <summary>
37 /// Retrieves the navigation parameter associated with the specified NavigationViewItem.
38 /// </summary>
39 /// <param name="item">The NavigationViewItem from which to obtain the navigation parameter. Cannot be null.</param>
40 /// <returns>An object representing the navigation parameter for the specified item, or null if no parameter is set.</returns>
13 41 public static object GetNavigateParameter(NavigationViewItem item) => item.GetValue(NavigateParameterProperty);
42 /// <summary>
43 /// Sets the navigation parameter value for the specified NavigationViewItem.
44 /// </summary>
45 /// <remarks>Use this method to attach contextual data to a NavigationViewItem, which can be accessed
46 /// during navigation events. This is useful for passing parameters between navigation targets in a
47 /// NavigationView.</remarks>
48 /// <param name="item">The NavigationViewItem for which to set the navigation parameter. Cannot be null.</param>
49 /// <param name="value">The value to associate with the navigation parameter. This value will be stored and can be retrieved when
50 /// navigating.</param>
14 51 public static void SetNavigateParameter(NavigationViewItem item, object value) => item.SetValue(NavigateParameterProperty, value);
15 52
53 /// <summary>
54 /// Identifies the NavigateParameter attached dependency property, which enables passing a navigation parameter to a
55 /// target element in XAML.
56 /// </summary>
57 /// <remarks>This property is typically used in navigation scenarios to associate additional data with a
58 /// UI element when initiating navigation. The value can be any object and is intended to be retrieved by navigation
59 /// logic or handlers. This property is commonly set in XAML using property element syntax.</remarks>
16 60 public static readonly DependencyProperty NavigateParameterProperty = DependencyProperty.RegisterAttached("NavigateParameter", typeof(object), typeof(NavigationAddition), new PropertyMetadata(null));
17 61 }
Added XFEExtension.NetCore.WinUIHelper/Utilities/Addition/PermissionAddition.cs +36 -0
@@ -0,0 +1,36 @@
1 namespace XFEExtension.NetCore.WinUIHelper.Utilities.Additions;
2
3 /// <summary>
4 /// Provides an attached property for specifying the required permission level on UI elements.
5 /// </summary>
6 /// <remarks>The PermissionAddition class enables developers to associate a required permission value with any
7 /// UIElement using the RequiredPermission attached property. This can be used to control access or visibility of UI
8 /// elements based on user permissions in WPF applications.</remarks>
9 public class PermissionAddition
10 {
11 /// <summary>
12 /// Retrieves the required permission level associated with the specified UI element.
13 /// </summary>
14 /// <param name="item">The UI element from which to obtain the required permission level. Must not be null.</param>
15 /// <returns>An integer representing the required permission level for the specified UI element.</returns>
16 public static int GetRequiredPermission(UIElement item) => (int)item.GetValue(RequiredPermissionProperty);
17 /// <summary>
18 /// Sets the required permission value for the specified UI element.
19 /// </summary>
20 /// <remarks>This method attaches a permission value to the UI element using the RequiredPermission
21 /// attached property. Use this to control access or visibility based on permission levels in your
22 /// application.</remarks>
23 /// <param name="item">The UI element on which to set the required permission. Cannot be null.</param>
24 /// <param name="value">The permission value to assign to the UI element.</param>
25 public static void SetRequiredPermission(UIElement item, int value) => item.SetValue(RequiredPermissionProperty, value);
26 /// <summary>
27 /// Identifies the RequiredPermission attached dependency property, which specifies the required permission level
28 /// for a UI element.
29 /// </summary>
30 /// <remarks>This property can be attached to any DependencyObject to indicate the minimum permission
31 /// level necessary for interaction or visibility. It is typically used in scenarios where UI elements should be
32 /// enabled, visible, or accessible only to users with sufficient permissions. The default value is 0, representing
33 /// no required permission.</remarks>
34
35 public static readonly DependencyProperty RequiredPermissionProperty = DependencyProperty.RegisterAttached("RequiredPermission", typeof(int), typeof(PermissionAddition), new PropertyMetadata(0));
36 }
Added XFEExtension.NetCore.WinUIHelper/Utilities/Helper/ObjectHelper.cs +136 -0
@@ -0,0 +1,136 @@
1 using System.Collections;
2 using System.Reflection;
3
4 namespace MultiPlatformTranslation.Core.Utilities.Helpers;
5
6 /// <summary>
7 /// 对象帮助类
8 /// </summary>
9 public static class ObjectHelper
10 {
11 /// <summary>
12 /// 判断对象及其子属性是否包含指定关键字
13 /// </summary>
14 public static bool Search(object obj, string keyword)
15 {
16 return SearchObject(obj, keyword, []);
17 }
18
19 private static bool SearchObject(object? obj, string keyword, HashSet<object> visited)
20 {
21 if (obj == null || visited.Contains(obj))
22 return false;
23
24 visited.Add(obj);
25
26 // string
27 if (obj is string str)
28 {
29 return str.Contains(keyword, StringComparison.OrdinalIgnoreCase);
30 }
31
32 // 集合
33 if (obj is IEnumerable enumerable && obj is not string)
34 {
35 foreach (var item in enumerable)
36 {
37 if (SearchObject(item, keyword, visited))
38 return true;
39 }
40 return false;
41 }
42
43 // 基础类型
44 if (obj.GetType().IsPrimitive || obj is decimal || obj is DateTime)
45 {
46 return obj.ToString()?.Contains(keyword, StringComparison.OrdinalIgnoreCase) == true;
47 }
48
49 // 复杂对象属性
50 foreach (var prop in obj.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
51 {
52 try
53 {
54 var value = prop.GetValue(obj);
55 if (SearchObject(value, keyword, visited))
56 return true;
57 }
58 catch { /* 忽略无法访问的属性 */ }
59 }
60
61 return false;
62 }
63
64 /// <summary>
65 /// 将 source 对象的值复制到 target 对象中,支持嵌套对象的递归复制
66 /// </summary>
67 /// <typeparam name="T"></typeparam>
68 /// <param name="source"></param>
69 /// <param name="target"></param>
70 public static void CopyValues<T>(this T source, T target)
71 {
72 if (source == null || target == null) return;
73
74 var type = typeof(T);
75
76 foreach (var prop in type.GetProperties(BindingFlags.Public | BindingFlags.Instance))
77 {
78 if (!prop.CanRead || !prop.CanWrite) continue;
79
80 var value = prop.GetValue(source);
81
82 if (value == null)
83 {
84 prop.SetValue(target, null);
85 }
86 else if (prop.PropertyType.IsValueType || prop.PropertyType == typeof(string))
87 {
88 // 值类型和字符串直接赋值
89 prop.SetValue(target, value);
90 }
91 else
92 {
93 // 引用类型(子对象)
94 var targetValue = prop.GetValue(target);
95 if (targetValue == null)
96 {
97 targetValue = Activator.CreateInstance(prop.PropertyType);
98 prop.SetValue(target, targetValue);
99 }
100
101 // 递归复制
102 var method = typeof(ObjectHelper)
103 .GetMethod(nameof(CopyValues), BindingFlags.Static | BindingFlags.Public)!
104 .MakeGenericMethod(prop.PropertyType);
105 method.Invoke(null, [value, targetValue]);
106 }
107 }
108
109 foreach (var field in type.GetFields(BindingFlags.Public | BindingFlags.Instance))
110 {
111 var value = field.GetValue(source);
112 if (value == null)
113 {
114 field.SetValue(target, null);
115 }
116 else if (field.FieldType.IsValueType || field.FieldType == typeof(string))
117 {
118 field.SetValue(target, value);
119 }
120 else
121 {
122 var targetValue = field.GetValue(target);
123 if (targetValue == null)
124 {
125 targetValue = Activator.CreateInstance(field.FieldType);
126 field.SetValue(target, targetValue);
127 }
128
129 var method = typeof(ObjectHelper)
130 .GetMethod(nameof(CopyValues), BindingFlags.Static | BindingFlags.Public)!
131 .MakeGenericMethod(field.FieldType);
132 method.Invoke(null, [value, targetValue]);
133 }
134 }
135 }
136 }
Added XFEExtension.NetCore.WinUIHelper/Utilities/Helper/PermissionHelper.cs +77 -0
Modified XFEExtension.NetCore.WinUIHelper/XFEExtension.NetCore.WinUIHelper.csproj +1 -0