
前端跨平台UI组件【免费下载链接】PrismPrism is a framework for building loosely coupled, maintainable, and testable XAML applications in WPF, Xamarin Forms, and Uno / Win UI Applications..项目地址https://gitcode.com/gh_mirrors/pri/Prism点击查看免费下载本指南围绕仓库e2e/Uno/HelloWorld中的官方端到端示例README 见 e2e/Uno/HelloWorld/ReadMe.md展开系统讲解如何在一个单项目 Uno 应用中组合 Prism 的区域导航NavigationView 主区域 嵌套 ContentControl 子区域、对话框服务、模块化加载Playground.Module、DryIoc 容器、ILoadableShell启动加载与InvokeCommandAction交互并完整还原本地 NativeAOT 绑定验证的构建命令、检查清单与 CLI 自动化流程。读完本文你将掌握该 playground 的工程结构、五类目标框架TFM的差异化构建方式以及一套可复用的渲染级绑定回归 物理设备 NativeAOT 发布验证方法。一、示例整体能力概览该示例是 Prism 面向 Uno Platform 的单项目UnoSingleProject演示集中覆盖以下能力区域RegionsNavigationView作为主内容区域容器页面内嵌套ContentControl作为二级DetailRegion对话框Dialogs基于IDialogService与 UnoDialogWindow的通知/确认对话框模块化Modularity独立项目Playground.Module作为IModule加载依赖注入常规构建使用DryIoc适配器Prism.DryIoc.Uno启动加载通过ILoadableShell配合 Uno Toolkit 的ExtendedSplashScreen实现初始化期间的加载态交互Home 页面演示InvokeCommandAction事件触发命令绑定NativeAOT 绑定实验室以真实容器、命名区域导航与普通{Binding}路径验证生成的成员保留member preservation行为。从 HelloWorld.csproj 可以看到应用同时面向五个 TFMnet10.0-desktop、net10.0-android、net10.0-ios、net10.0-windows10.0.26100与net10.0-browserwasm应用标题为Prism Playground并启用了 UnoFeatures 中的 Material、Hosting、Toolkit、Logging 与 LoggingSerilog。二、工程结构与关键代码路径1. 启动入口与容器选择应用根类型HelloWorld.App继承自 PlaygroundApplication.cs 中定义的抽象类PlaygroundApplication : PrismApplication。这个中间层的关键作用是让 XAML 根保持一致同时通过 GlobalUsings.cs 中的条件别名切换容器#if PRISM_NATIVE_AOT_VALIDATION global using PrismApplication Prism.PrismApplicationBase; #else global using Prism.DryIoc; #endif也就是说普通构建下PrismApplication即 DryIoc 适配器提供的PrismApplicationNativeAOT 验证构建下则退化为容器无关的 PrismApplicationBase.cs由应用自己提供容器扩展。在 App.xaml.cs 中public partial class App : PlaygroundApplication { protected override UIElement CreateShell() { return Container.ResolveShell(); } protected override void RegisterTypes(IContainerRegistry containerRegistry) { containerRegistry.RegisterForNavigationBindingLabPage, BindingLabViewModel(BindingLab); containerRegistry.RegisterForNavigationBindingLabPage, BindingLabViewModel(BindingLabDetail); } protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog) { moduleCatalog.AddModulePlaygroundModule(); } }注意同一对BindingLabPage/BindingLabViewModel被注册到两个命名路由BindingLab与BindingLabDetail——这正是 NativeAOT 验证中命名导航与独立上下文机制的基础详见第五节。只有开启PRISM_NATIVE_AOT_VALIDATION条件编译时CreateContainerExtension()才会返回Prism.Container.Microsoft.MicrosoftContainerExtension即 Microsoft.Extensions.DependencyInjection 适配器从而在验证路径中彻底绕开 DryIoc。2. ShellNavigationView 主区域与启动加载Shell.xaml 使用 Uno Toolkit 的ExtendedSplashScreen包裹整棵视觉树内部是一个NavigationViewNavigationView prism:RegionManager.RegionNameContentRegion IsSettingsVisiblefalse PaneDisplayModeLeft NavigationView.MenuItems NavigationViewItem ContentHome TagHomeView / NavigationViewItem ContentRegion lab TagRegionLabView / NavigationViewItem ContentDialog lab TagDialogLabView / NavigationViewItem ContentNativeAOT binding lab TagBindingLab / NavigationViewItem ContentModule TagModuleAboutView / /NavigationView.MenuItems /NavigationView其配套的 Shell.xaml.cs 实现了ILoadableShell构造时创建一个IsExecuting true的CompositeLoadableSource作为 Splash 的 Source直到 Prism 初始化完成才调用FinishLoading()关闭加载态。ILoadableShell的契约定义在 src/Uno/Prism.Uno/ILoadableShell.cs而调用点位于 PrismApplicationBase.cs 的FinalizeInitialization中——模块初始化与OnInitialized执行完毕后才触发loadableShell.FinishLoading()保证了整个 Prism 启动序列完成前用户始终看到加载画面。菜单项的Tag是导航目标NavigationView区域的适配器 NavigationViewRegionAdapter.cs 在SelectionChanged时读取选中项Tag中的非空字符串并调用region.RequestNavigate(navigationTarget)同时把BackRequested接到该区域NavigationService.Journal.GoBack()把region.ActiveViews的第一个活动视图设置为NavigationView.Content。也就是说NavigationView 的返回按钮直接驱动ContentRegion的导航日志journal。3. 模块化Playground.ModulePlaygroundModule.cs 在RegisterTypes中注册了六个导航页HomeView、RegionLabView、DialogLabView、ModuleAboutView、RegionDetailAlphaView、RegionDetailBetaView与两个对话框NotificationDialog、ConfirmDialog并在OnInitialized里解析IRegionManager后执行首屏导航public void OnInitialized(IContainerProvider containerProvider) { var regionManager containerProvider.ResolveIRegionManager(); regionManager.RequestNavigate(ContentRegion, HomeView); }模块项目 Playground.Module.csproj 与宿主应用保持相同的五个 TFM并以ProjectReference直接引用src/Prism.Core与src/Uno/Prism.Uno。这里体现的模块化边界是所有 Region/Dialog 注册都在模块内部完成宿主应用只负责把模块加进目录。4. 嵌套区域ContentControl 二级 DetailRegionRegionLabView的 RegionLabView.xaml 在页面内部放了一个命名区域ContentControl prism:RegionManager.RegionNameDetailRegion HorizontalAlignmentStretch VerticalAlignmentStretch /对应的 RegionLabViewModel.cs 演示了父区域页面管理子区域导航日志的典型做法OnNavigatedTo时订阅IRegionManager.Regions.CollectionChanged以捕获DetailRegion的注册时机将OpenAlphaCommand/OpenBetaCommand的CanExecute与区域是否存在绑定并通过_detailRegion.NavigationService.Journal.GoBack()实现仅回退二级区域的独立返回。这与 Shell 层的NavigationView 返回按钮走 ContentRegion 日志形成两级日志协同。5. 对话框IDialogService 与 IDialogAwareDialogLabViewModel.cs 演示两种对话框调用无回调的通知与带回调的结果确认_dialogService.ShowDialog( nameof(NotificationDialog), new DialogParameters { { title, Notification }, { message, This dialog is registered in PlaygroundModule and hosted by Prism’s Uno DialogService. } }); _dialogService.ShowDialog( nameof(ConfirmDialog), new DialogParameters { { message, Discard unsaved playground changes? } }, r LastResult $Confirm dialog closed: {r.Result});ConfirmDialogViewModel实现IDialogAware通过RequestClose.Invoke(new DialogResult(ButtonResult.OK/Cancel))关闭对话框并在OnDialogOpened中读取参数。底层实现 src/Uno/Prism.Uno/Dialogs/DialogService.cs 揭示了完整生命周期按KnownDialogParameters.WindowName解析IDialogWindow默认ContentDialog→ 设置XamlRoot→ 从IDialogViewRegistry创建视图并断言其 DataContext 为IDialogAware→Loaded时初始化DialogCloseListener→Closing时检查CanCloseDialog()→Closed时回调OnDialogClosed并await callback.Invoke(result)。若异常则直接await callback.Invoke(ex)将异常交给调用方。6. InvokeCommandActionHome 页 HomeView.xaml 通过行为绑定按钮事件到命令Button ContentGo to region lab (InvokeCommandAction) i:Interaction.Behaviors ic:EventTriggerBehavior EventNameClick prism:InvokeCommandAction Command{Binding GoToRegionLabCommand} / /ic:EventTriggerBehavior /i:Interaction.Behaviors /Button实现位于 src/Uno/Prism.Uno/Interactivity/InvokeCommandAction.cs除执行命令外还提供AutoEnable默认 true根据命令CanExecute自动启用/禁用关联元素、CommandParameter与TriggerParameterPath支持点分路径从触发器参数中提取嵌套属性三个依赖属性命令本身在 HomeViewModel.cs 中通过IRegionManager.RequestNavigate(ContentRegion, RegionLabView)完成跳转。三、构建与运行含 WinUI 差异与注意事项README 明确提示Prism 包在本仓库中均为项目引用project references构建时会按需编译src/Uno下的源码因此构建整个 solution 或单独项目前无需额外还原 Prism 包。1. Skia / workload 说明示例在UnoFeatures中刻意省略了SkiaRenderer这样dotnet workload restore才能在 Android/iOS 头head上成功——README 指出这是为避免 Uno 的ReplaceUnoRuntime/RuntimeAssetsSelectorTask在强制为这些 TFM 指定 Skia 时抛错。2. CLI 友好的 TFMdotnet builddotnet build .\e2e\Uno\HelloWorld\HelloWorld.csproj -f net10.0-desktop dotnet build .\e2e\Uno\HelloWorld\HelloWorld.csproj -f net10.0-browserwasmnet10.0-desktopSkia/桌面与net10.0-browserwasmWebAssembly是命令行直接可构建的目标。3. WinUI TFM必须使用 msbuildnet10.0-windows10.0.26100属于 WinUI 类库场景Uno 会阻止对含 XAML 的 WinUI 类库执行dotnet build错误UNOB0008因此 Windows TFM 必须交给 Visual Studio 或msbuild构建与Prism.Uno的 CI 方式一致msbuild .\e2e\Uno\HelloWorld\HelloWorld.csproj -restore -p:TargetFrameworknet10.0-windows10.0.261004. 解决方案文件的使用限制e2e/Uno/HelloWorld.slnx同时包含 Prism 库项目。README 特别警告不要对整套 solution 传入单个-f否则会把包括Prism.Core在内的所有项目强制压到同一个 TFM 上。正确做法是像上文那样按 TFM 单独构建HelloWorld.csproj。5. Windows TFM 的工程级处理HelloWorld.csproj 对windows10TFM 做了专项配置设置IsWinAppSdktrue、关闭默认 PRI/Page 项生成EnableDefaultPriItems/EnableDefaultPageItemsfalse再显式列出App.xaml、Views\Shell.xaml、Views\BindingLabPage.xaml、Styles\ColorPaletteOverride.xaml与Strings\en\Resources.resw。原因注释指出若不这样做Uno 与 Windows SDK 的默认项会重叠如NETSDK1022重复PRIResource/Page。Playground.Module.csproj采用同样的模式并在非 Windows TFM 使用Uno.Microsoft.Xaml.Behaviors.WinUI.Managed、Windows TFM 使用Microsoft.Xaml.Behaviors.WinUI.Managed。四、NativeAOT 绑定实验室功能层面该实验室位于 BindingLabPage.xamlUI 上全部使用普通{Binding}而非编译绑定compiled bindings用于专门验证 NativeAOT 下 Uno 生成的成员保留member preservation是否足以支撑运行时反射绑定。1. 独立 INPC 模型基类关键设计在 BindingContext.cs上下文BindingContext继承自封闭泛型NotifyingContextstring而NotifyingContextTTitle刻意不继承BindableBase而是直接实现INotifyPropertyChanged。注释明确说明这样做的目的bindings must retain inherited members of other INPC models too——即验证绑定访问器对其他 INPC 模型的继承成员同样被保留。模型上还有嵌套动作BindingAction携带Text/Icon/Command其命令是一个DelegateCommand执行后回调UpdateTitle(_actionTitle)。2. ViewModel 与命名路由BindingLabViewModel.cs 实现IRegionAware其IsNavigationTarget只接受自己最初到达的命名路由public bool IsNavigationTarget(NavigationContext navigationContext) string.Equals(_navigationRoute, navigationContext.Uri.ToString(), StringComparison.Ordinal);由于BindingLab与BindingLabDetail注册了同一个 ViewModel 类型这一判断保证root 与 detail 各持有独立的 ViewModel 与上下文实例detail 页面不会复用 root 的模型而再次导航到同一命名路由时则允许复用README 描述为the view-model accepts reuse only for its original named route。BackCommand直接调用_navigation.Regions[ContentRegion].NavigationService.Journal.GoBack()。3. 15 项渲染绑定检查清单点击Run binding checks后BindingLabPage.xaml.cs 通过Expect(...)最多重试 100 次、每次间隔 20ms等待 UI 调度器应用绑定与集合模板逐项断言真实渲染后的控件。完整覆盖必须报告PASS: 15 rendered binding checks#检查场景断言要点1初始嵌套绑定ContextTitle.Text Initial context且导航指示按钮Visible2初始集合项ItemsControl 模板内渲染出Initial item3嵌套动作NestedAction.Content Initial action、图标、Command非空、HasActionButton/HasTitle为 true4继承属性通知UpdateTitle后标题更新、ToggleNavigationVisibility后按钮Collapsed5上下文替换/旧模型脱离替换后新标题生效旧模型再变更不再影响渲染6空上下文全部相关控件回退为空/Collapsed/false依赖TargetNullValue/FallbackValue7上下文恢复重新赋值后标题与可见性恢复8嵌套动作通知UpdateAction后文本/图标更新9嵌套动作替换/旧动作脱离替换后新文本/图标生效HasActionButton保持 true10清空嵌套动作文本、图标、Command 均空11恢复嵌套动作恢复后文本/图标/Command 与HasActionButton全部恢复12嵌套绑定命令执行从控件上取回Command并Execute标题变为Action command invoked13集合项通知Items[0].UpdateTitle后模板文本更新14集合添加Items.Add后行数变为 2 且新项渲染15集合移除Items.RemoveAt(0)后行数为 1、旧项消失、新项保留检查代码中的关键说明嵌套动作BindingAction派生自BindableBase且未加应用侧特性上下文仍测试独立 INPC 路径而生成的属性保留generated property preservation本身不能证明 Uno 为每个独立 INPC 类型都生成了访问器——这正是该实验室存在的意义。4. 命名导航往返验证点击Navigate to named detailNavigateCommand→RequestNavigate(ContentRegion, BindingLabDetail)新实验室页面必须出现其状态栏标识BindingLabDetail在该页执行全部检查后点Back日志journal必须回到原实验室页面并恢复其上下文。README 要求重复该导航往返且 root 与 detail 始终保持独立上下文。手动按钮更新、替换/恢复、置空、可见性切换、集合增删允许逐项独立检查替换/恢复在置空后依然可恢复Home、Region、Dialog、Module 页面在验证全程保持可访问。五、本地 NativeAOT 发布验证权威流程1. 验证属性与工程约束PrismNativeAotValidationtrue仅作用于 Release Android/iOS应用项目在 HelloWorld.csproj 中映射为PropertyGroup Condition$(PrismNativeAotValidation) true and (ios or android) PublishAottrue/PublishAot DefineConstants$(DefineConstants);PRISM_NATIVE_AOT_VALIDATION/DefineConstants UseInterpreterfalse/UseInterpreter /PropertyGroup三点硬性约束由工程内ValidateNativeAotConfiguration/ValidateNativeAotBuild两个 MSBuild Target 强制不得全局传PublishAot否则会传播到被引用的库项目必须Release且目标为 Android/iOS验证构建通过CreateContainerExtension选择真实的Prism.Container.Microsoft适配器直接引用Prism.Uno不引用 DryIoc 适配器不得用容器 shim 或把实现类型拷进示例。中央包配置Directory.Packages.props将 Microsoft 与 Abstractions含共享 analyzer固定到已发布的10.0.94-pre从配置好的 Prism 包源还原即可基线无需版本覆盖或本地容器构建只有测试进一步未发布的容器改动时才用可选属性PrismNativeAotContainerVersion选择匹配的真实本地包。2. iOS 与 Android 发布命令iOS物理设备ios-arm64RIDdotnet publish e2e/Uno/HelloWorld/HelloWorld.csproj \ -c Release -f net10.0-ios -r ios-arm64 \ -p:PrismNativeAotValidationtrueAndroid 使用相同命令改为-f net10.0-android -r android-arm64。前置条件与提醒Uno 6.6 的 NativeAOT 指引覆盖 .NET 10 的 Android 与 iOSAndroid 需要NDK r27 或更新并会发出实验性警告XA1040——需要检查警告与设备实测结果普通 Android AOT 构建绝不能算作 NativeAOT 验证发布命令刻意使用物理设备 RIDios-arm64不要仅凭通用平台文档推断模拟器支持务必先确认所装 SDK 对所选 RID 的真实支持一次更早的原生发布、之后的非原生模拟器登录或已存在的生成元数据文件都不能为当前源码改动背书——必须对当前改动产物执行一次全新的原生发布并跑完渲染检查验证前需确认已安装支持的 SDK/平台/RID 与已验证 NativeAOT 兼容的真实容器配置随后进行本地发布与真机运行并记录确切版本与每一个 trimming/AOT 警告云上的源码/XML 检查不是 NativeAOT 或设备级通过本仓库不包含移动端 CI 任务或工作流改动。3. 可选未发布的本地容器包准备仅当测试未发布的容器改动时需要。完整流程见 e2e/Maui/PrismMauiDemo/NativeAotValidation.mdMaui 侧同套方案对PrismLibrary/Prism.Containers检出物按正常支持 TFM 执行dotnet pack基线为合并提交f3e51fbb生成两个项目共用的单一本地预发布版本然后在发布命令中追加-p:RestoreAdditionalProjectSources$PRISM_CONTAINER_FEED \ -p:PrismNativeAotContainerVersion$PRISM_CONTAINER_VERSIONREADME 特别强调仅用于云生成器/核心单元测试的 net10-only 包不能建立完整的多目标移动端还原或原生执行通过本地包必须覆盖项目正常的全部受支持 TFM。4. CLI 驱动的物理设备自动化检查在 Release NativeAOT 验证构建中设置环境变量PRISM_NATIVEAOT_AUTORUN1启动应用App.xaml.cs 的OnInitialized会先导航到BindingLab随后 BindingLabPage.xaml.cs 的AutoRunAsync自动执行完整流程输出[binding-run] dynamic-code...检查动态代码支持状态在 root 实验室运行 15 项渲染断言并要求PASS通过按钮上真实绑定的Command导航到命名 detail要求 detail 不复用 root 的 ViewModel在 detail 再跑全部断言通过 detail 的 Back 返回断言 root 的 ViewModel、Context与渲染状态全部还原Console标记逐项报告结果上述detail 访问 Back 还原完整重复两次最终输出[binding-run] COMPLETE root two named detail / Back visits。Android 侧的等价入口是启动既有主 Activity 时携带布尔型 Intent extraprism-nativeaot-autoruntrue它会在 UI 初始化前设置同一 opt-in。README 明确该自动化不取代手动横竖屏、滚动、辅助功能与触摸交互检查。六、核心文件索引示例总览与全部构建/验证说明e2e/Uno/HelloWorld/ReadMe.md应用工程五 TFM NativeAOT 开关e2e/Uno/HelloWorld/HelloWorld.csproj应用启动与注册e2e/Uno/HelloWorld/App.xaml.cs、e2e/Uno/HelloWorld/App.xamlShell 与启动加载e2e/Uno/HelloWorld/Views/Shell.xaml、Shell.xaml.cs绑定实验室BindingLabPage.xaml、BindingLabPage.xaml.cs、BindingLabViewModel.cs、BindingContext.cs模块示例PlaygroundModule.cs、Playground.Module.csproj框架侧实现NavigationViewRegionAdaptersrc/Uno/Prism.Uno/Navigation/Regions/NavigationViewRegionAdapter.cs、DialogServicesrc/Uno/Prism.Uno/Dialogs/DialogService.cs、ILoadableShellsrc/Uno/Prism.Uno/ILoadableShell.cs、PrismApplicationBasesrc/Uno/Prism.Uno/PrismApplicationBase.csMaui 侧等价验证文档e2e/Maui/PrismMauiDemo/NativeAotValidation.md七、小结与适用前提该 playground 是 Prism 在 Uno Platform 上的活文档区域含两级导航日志、对话框、模块化、DryIoc 与InvokeCommandAction均可直接对照源码阅读与修改运行而 NativeAOT 绑定实验室则提供了一套以真实容器 普通绑定 渲染断言为核心的本地验证基线。使用时请留意两个前提其一README 中提及的 Uno 入门与 SDK 使用指引、Uno 6.6 NativeAOT 官方指引均来自外部站点本仓库未内置请以当前安装的 Uno SDK 实际行为为准其二移动端发布与真机执行未被云端工作区验证本文所述发布命令与警告如 XA1040需要在具备相应 SDK、workload 与真机的本地环境中实测确认。赞分享前端跨平台UI组件【免费下载链接】PrismPrism is a framework for building loosely coupled, maintainable, and testable XAML applications in WPF, Xamarin Forms, and Uno / Win UI Applications..项目地址https://gitcode.com/gh_mirrors/pri/Prism点击查看免费下载相关推荐高性能API守护神Hertz请求绑定与验证实战指南高性能API守护神Hertz请求绑定与验证实战指南 你还在为API数据校验写重复代码还在担心非法输入导致系统崩溃本文将带你掌握Hertz框架的请求绑定与验后端微服务Web框架Apache Beam Release Candidate 验证实战指南Java / Python / Go 与 Prism Runner 全流程Apache Beam Release Candidate 验证实战指南Java / Python / Go 与 Prism Runner 全流程 Apach大数据批处理流处理数据工程WPF 业务层验证实战基于 IDataErrorInfo 与 DataErrorValidationRule 的绑定校验WPF 业务层验证实战基于 IDataErrorInfo 与 DataErrorValidationRule 的绑定校验 本文围绕 WPF Samples 仓示例工程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考