WPF中调用UWP API
创始人
2024-11-12 07:05:25
0

最近在github上看到一个音乐播放器项目,dopamine(项目地址:GitHub - digimezzo/dopamine-windows: Audio player which tries to make organizing and listening to music as simple and pretty as possible.)

在编译时,提示有一个库找不到

找了好一会,才发现这是调用了UWP的库。

在最初Windows 8 出来时,这一套新的运行时叫Windows RT,后面到Windows 10时,改成了UWP。

因为我也没做过UWP方面的开发,大概了解了一下。里面提供了一些新的API,UI上面也更加炫丽。

所以这里做个总结,如何在WPF中调用UWP的库,以后有需要的时候可以用得到。

===========================================================================

调用UWP API

这里我们以调用一个提供对当前地理位置的访问权限的类为例

Windows.Devices.Geolocation.Geolocator

.Net Framework版本

调用方法比较简单,跟引用其它库一样,直接引用UWP的库即可

1、先引用 Windows.winmd(位置:C:\Program Files (x86)\Windows Kits\10\UnionMetadata\10.0.22000.0),后面的版本号以机器上安装的版本为准 。

我也是第一次知道还能引用winmd这种格式

2、引用 System.Runtime.WindowsRuntime.dll(位置:C:\Windows\Microsoft.NET\Framework64\v4.0.30319)

官方博客上说的是C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETCore\v4.5\System.Runtime.WindowsRuntime.dll这个路径,但我电脑上没有这个文件,所以就到Windows目录下去找了。

.Net Core版本

针对.NET6 及以上版本,直接修改项目工程文件,将目标框架修改为带Windows版本号的即可。

  • net6.0-windows10.0.17763.0:Windows 10 版本 1809。
  • net6.0-windows10.0.18362.0:Windows 10 版本 1903。
  • net6.0-windows10.0.19041.0:Windows 10 版本 2004。
  • net6.0-windows10.0.22000.0:Windows 11。

不知道当前系统什么版本,运行输入winver查看

我电脑的系统版本是Windows 1903,所以修改如下:

针对.NET 6以下版本,安装Microsoft.Windows.SDK.Contracts  Nuget包。(这里我没测试过)

  • 10.0.19041.xxxx:Windows 10 版本 2004
  • 10.0.18362.xxxx: Windows 10 版本 1903
  • 10.0.17763.xxxx: Windows 10 版本 1809
  • 10.0.17134.xxxx: Windows 10 版本 1803

测试

新建一个WPF工程,创建如下测试代码:

xaml

1    2         

xaml.cs

1  private async void Button_Click(object sender, RoutedEventArgs e) 2         { 3             var locator = new Windows.Devices.Geolocation.Geolocator(); 4             var location = await locator.GetGeopositionAsync(); 5             var position = location.Coordinate.Point.Position; 6             var latlong = string.Format("lat:{0}, long:{1}", position.Latitude, position.Longitude); 7             var result = MessageBox.Show(latlong); 8         }

开启电脑上的定位开关,运行结果如下:

注意:

有两个主要的 WinRT API 集在桌面应用中不受支持或具有限制:

  • 需要程序包标识符的 API(请参阅需要程序包标识符的功能)。 此类 API 仅在使用 MSIX 打包的桌面应用中受支持。(应用商店相关)
  • 依赖于用户界面 (UI) 功能的 API,这些功能仅在通用 Windows 平台 (UWP) 应用中可用。

基于代码生成 MSIX 程序包可以参考以下链接:基于代码生成 MSIX 程序包概述 - MSIX | Microsoft Learn。这里不做详细介绍了,感兴趣的可以自行了解。

无法在WPF使用UWP跟界面相关的API,解决方案如下:

如何在WPF中使用UWP的控件?

这里主要是借助CommunityToolkit.Wpf.UI.XamlHost包里的WindowsXamlHost控件实现。

以前在WPF中使用Winform控件时,使用了一个叫做WindowsFormHost的控件,原理是创建一个单独的窗口句柄,然后在上面进行绘制。

目测WindowsXamlHost应该也是类似的原理,具体也没有深入了解过。

WindowsXamlHost支持

  • Windows SDK 或 WinUI 库提供UWP 控件

  • 自定义 UWP 控件

使用代码创建及显示UWP控件

1、导入Nuget包,Microsoft.Toolkit.UI.XamlHost

2、引用 Windows.winmd

注意:

截止本文发布,

针对.NET Core版本,Microsoft.ToolKit.UI.XamlHost仅支持.NET 5以下版本。以后应该会支持到.NET 5及以后版本

https://learn.microsoft.com/en-us/answers/questions/1010047/does-net6-0-support-xaml-island

针对.Net FrameWork版本,需要添加app.manifest文件,否则运行时会报错。

添加app.manifest文件的方法是启用ClickOnce安全设置,然后再取消即可。

在MainWindow.cs中添加代码如下:

 1 public partial class MainWindow : Window  2     {  3         public MainWindow()  4         {  5             InitializeComponent();  6             CreateUWPControlsFirst();  7         }  8   9         private void CreateUWPControlsFirst() 10         { 11             //初始化UWP容器环境 12             Windows.UI.Xaml.Hosting.WindowsXamlManager.InitializeForCurrentThread(); 13  14             //创建一个UWP按钮 15             Windows.UI.Xaml.Controls.Button myButton = new Windows.UI.Xaml.Controls.Button(); 16             myButton.Name = "btn_Message"; 17             myButton.Width = 188; 18             myButton.Height = 48; 19             myButton.TabIndex = 0; 20             myButton.Content = "弹出UWP消息框"; 21             myButton.Click += MessageButton_Click; 22             Microsoft.Toolkit.Wpf.UI.XamlHost.WindowsXamlHost myHostControl = new Microsoft.Toolkit.Wpf.UI.XamlHost.WindowsXamlHost(); 23             myHostControl.Name = "myWindowsXamlHostControl"; 24             myHostControl.Child = myButton; 25             myHostControl.HorizontalAlignment = HorizontalAlignment.Center; 26             myHostControl.VerticalAlignment = VerticalAlignment.Center; 27             this.grid.Children.Add(myHostControl); 28         } 29  30         private async void MessageButton_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e) 31         { 32             var messageDialog = new MessageDialog("这是一个示例的消息框"); 33             messageDialog.Commands.Add(new UICommand( 34                 "确定", 35                 new UICommandInvokedHandler(this.Confirm))); 36             messageDialog.Commands.Add(new UICommand( 37                 "取消", 38                 new UICommandInvokedHandler(this.Cancel))); 39             messageDialog.DefaultCommandIndex = 0; 40             messageDialog.CancelCommandIndex = 1; 41             await messageDialog.ShowAsync(); 42         } 43  44         private void Confirm(IUICommand command) 45         { 46              47         } 48  49         private void Cancel(IUICommand command) 50         { 51  52         } 53     }

运行效果:

在XAML中直接创建UWP控件

添加命名空间前缀:

1 xmlns:xamlhost="clr-namespace:Microsoft.Toolkit.Wpf.UI.XamlHost;assembly=Microsoft.Toolkit.Wpf.UI.XamlHost"

使用InitialTypeName属性设置初始控件类型

1 InitialTypeName="Windows.UI.Xaml.Controls.CalendarView"

添加当容器里控件渲染后事件处理程序

1 ChildChanged="MyCalendar_ChildChanged"

完整代码如下:

MainWindow.xaml

 1  10      11          13      14 

MainWindow.xaml.cs

 1    private void MyCalendar_ChildChanged(object sender, EventArgs e)  2         {  3             WindowsXamlHost windowsXamlHost = (WindowsXamlHost)sender;  4             var calendarView =(Windows.UI.Xaml.Controls.CalendarView)windowsXamlHost.Child;  5             if (calendarView != null)  6             {  7                 calendarView.SelectedDatesChanged += (obj, args) =>  8                 {  9                     if (args.AddedDates.Count > 0) 10                     { 11                         MessageBox.Show("当前选择的日期是: " + args.AddedDates[0].DateTime.ToString()); 12                     } 13                 }; 14             } 15         }

 运行效果:

目前已经有部分UWP控件支持直接在XAML中添加,需要对项目进行一定的配置,这里就不做介绍了,上面两种方式在日常开发中应该够用了。后面有时间再更新如何直接在XAML中添加UWP控件。

示例代码 

参考文档:

Call Windows Runtime APIs in desktop apps

Call Windows Runtime APIs in desktop apps - Windows apps | Microsoft Learn

Calling Windows 10 APIs From a Desktop Application

Calling Windows 10 APIs From a Desktop Application - Windows Developer Blog

Windows Runtime APIs not supported in desktop apps

桌面应用中不支持的 Windows 运行时 API - Windows apps | Microsoft Learn

Building an MSIX package from your code

基于代码生成 MSIX 程序包概述 - MSIX | Microsoft Learn

Use XAML Islands to host a UWP XAML control

Use XAML Islands to host a UWP XAML control in a C# WPF app - Windows apps | Microsoft Learn

https://learn.microsoft.com/en-us/windows/apps/desktop/modernize/xaml-islands#host-controls

相关内容

热门资讯

两分钟辅助!阿拉游戏中心辅助工... 两分钟辅助!阿拉游戏中心辅助工具苹果版,总是是有辅助技巧(真实有挂)1、完成阿拉游戏中心辅助工具苹果...
第6分钟辅助!来趣广西友玩脚本... 第6分钟辅助!来趣广西友玩脚本辅助,一直是真的有辅助方法(有挂方法);1、许多玩家不知道来趣广西友玩...
第七分钟辅助!如何下载安装胡乐... 第七分钟辅助!如何下载安装胡乐辅助脚本,真是是有辅助神器(有挂规律)如何下载安装胡乐辅助脚本辅助器是...
第九分钟辅助!新导游正版辅助,... 第九分钟辅助!新导游正版辅助,原来真的是有辅助攻略(有挂规律)一、新导游正版辅助可以开透视的定义与意...
第一分钟辅助!微信开心泉州辅助... 第一分钟辅助!微信开心泉州辅助器,真是是有辅助脚本(有挂透视)1、完成微信开心泉州辅助器辅助器v3....
第7分钟辅助!来几局辅助器,好... 第7分钟辅助!来几局辅助器,好像是真的有辅助技巧(有挂规律)来几局辅助器辅助器是一种具有地方特色的麻...
第四分钟辅助!人海大厅反杀,原... 第四分钟辅助!人海大厅反杀,原来真的是有辅助攻略(发现有挂)1、起透看视 人海大厅反杀辅助软件价格2...
三分钟辅助!湛江吴川0759作... 三分钟辅助!湛江吴川0759作弊,原来有辅助插件(有挂方针)湛江吴川0759作弊能透视中分为三种模型...
第九分钟辅助!威信茶馆透视辅助... 第九分钟辅助!威信茶馆透视辅助工具,确实真的是有辅助软件(有挂技巧)1、金币登录送、破产送、升级送、...
第九分钟辅助!决战手游辅助,真... 第九分钟辅助!决战手游辅助,真是是有辅助工具(有挂技巧)1、游戏颠覆性的策略玩法,独创攻略技巧玩法,...