Windows Community Toolkit 再次更新到 5.0。以前可以在 WPF 中使用有限的 UWP 控件,而现在有了 WindowsXamlHost,则可以使用更多 UWP 原生控件了。


关于 Windows Community Toolkit 早期版本的 Xaml Bridge,可以参见:

安装 NuGet 包

你需要做的第一步,是在你的 WPF 项目中安装 Microsoft.Toolkit.Wpf.UI.XamlHost。建议直接在 项目的 NuGet 管理器中搜索并安装。

配置 WPF 项目能访问 UWP 的类型

因为我们即将开始使用到 UWP 中的控件类型,所以需要配置项目能够访问到 Windows Runtime 的类型。


▲ 添加引用

你需要在你的 WPF 项目中添加以下 6 个引用才能访问 UWP 的类型:

  • C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETCore\v4.5

    • 引用 System.Runtime.WindowsRuntime
    • 引用 System.Runtime.WindowsRuntime.UI.Xaml
    • 引用 System.Runtime.InteropServices.WindowsRuntime
  • C:\Program Files (x86)\Windows Kits\10\UnionMetadata\Facade
    • 引用 Windows.winmd
  • C:\Program Files (x86)\Windows Kits\10\References\
    • 在此目录下选择你的 SDK 版本(如 16299,17763 等)

      • Windows.Foundation.UniversalApiContract\

        • 在此目录下选择你的 API 版本(如 4.0.0.0)

          • 引用 Windows.Foundation.UniversalApiContract.winmd
      • Windows.Foundation.FoundationContract
        • 在此目录下选择你的 API 版本(如 3.0.0.0)

          • 引用 Windows.Foundation.FoundationContract.winmd

在你添加完这些引用之后,还需要选中这些引用,右击属性,把所有的 “复制到本地” 选项设置为 “否”。


▲ 添加 Windows Runtime 的 .NET Framework 类型引用


▲ 添加 Windows.WinMD 的引用


▲ 在添加引用时注意选择 SDK 的版本号


▲ 添加 Windows.Foundation.UniversalApiContract.winmd


▲ 添加 Windows.Foundation.FoundationContract.winmd

开始在 WPF 中使用 UWP 的控件

你可以像使用普通 WPF 控件一样将 WindowsXamlHost 添加到你的 WPF 界面中:

  • 拖拽到界面设计器中
  • 拖拽到 XAML 代码行中
  • 直接在 XAML 代码中写


▲ 添加 WindowsXamlHost 控件

接着,指定 InitialTypeName 属性为 UWP 中的控件的名称(带命名空间)。这样,当 WindowsXamlHost 初始化的时候,也会初始化一个 UWP 的控件。

这里为了简单,我初始化一个 UWP 的按钮。但必须得为 UWP 的按钮进行一些初始化,所以我监听了 ChangedChanged 事件:

<XamlHost:WindowsXamlHost Grid.Column="1"
InitialTypeName="Windows.UI.Xaml.Controls.Button"
ChildChanged="WindowsXamlHost_ChildChanged" />
private void WindowsXamlHost_ChildChanged(object sender, EventArgs e)
{
var host = (WindowsXamlHost) sender;
var button = (Windows.UI.Xaml.Controls.Button) host.Child;
button.Width = 120;
button.Height = 40;
button.Content = "walterlv.com";
button.Click += UwpButton_Click;
} private void UwpButton_Click(object sender, RoutedEventArgs e)
{
}

可以忽略的错误

在启动的时候,你可能会遇到一些异常。比如下面这个:

因为我们不是原生的 UWP,而是 Host 在 WPF 中的 UWP 控件,所以会没有 Application。这在 UWP 控件初始化内部已经 catch 了,所以你可以忽略。

最终效果

当将程序跑起来之后,你就能看到 WPF 窗口中的 UWP 控件了。

值得注意的地方

  1. 目前 WindowsXamlHost 还不够稳定,会出现一些闪退

    • 这点就需要为 WindowsCommunityToolkit 贡献 Issues 或代码了
  2. Host 的 UWP 控件是一个新的 HwndSource,这相当于 UWP 的控件是通过子窗口的形式与 WPF 窗口放在一起的
    • 于是,只能指定一个矩形区域完全属于 UWP,在这个区域 WPF 控件无法与其获得交互或渲染叠加

关于 DPI 适配

为了让 UWP 控件能够在 WPF 窗口中获得正确的 Per-Monitor 的 DPI 适配效果,你需要设置为 PerMonitorV2 的 DPI 感知级别。

在 PerMonitorV2 的 DPI 感知级别下,UWP 控件能够正常获得 DPI 缩放。

在 100% DPI 的屏幕下:

在 150% DPI 的屏幕下:

而如果只是指定为 PerMonitor,那么切换 DPI 或者切换屏幕的时候,只有 WPF 部分会缩放,而 UWP 部分不会变化。

关于 PerMonitorV2 和 PerMonitor 的理解和区别,可以参见:

关于如何在 WPF 下开启 PerMonitorV2 级别的 DPI 感知可以参见:

更复杂的 UWP 控件嵌入

如果希望将更多的 WPF 窗口内的 UI 部分交给 UWP 来做,那么就不能只是仅仅初始化一个 Button 就完了。

你需要引入一个 UWP 控件库。阅读以下文章了解更多:


参考资料

WindowsXamlHost:在 WPF 中使用 UWP 的控件(Windows Community Toolkit)的更多相关文章

  1. WPF中通过代码设置控件的坐标

    用WPF做贪吃蛇小游戏时,发现了一个问题: 贪吃蛇的移动,我是通过不断刷新Rectangle来实现(贪吃蛇的身体由一组Rectangle组成),因此需要不断调整Rectangle的坐标,但是WPF中没 ...

  2. WPF 中如何使用第三方控件 ,可以使用WindowsFormsHost 类

    允许在 WPF 页面上承载 Windows Forms控件的元素. 命名空间:   System.Windows.Forms.Integration 程序集:   WindowsFormsIntegr ...

  3. WPF中MVVM模式下控件自有的事件绑定

    1.原因 在WPF中单纯的命令绑定往往不能满足覆盖所有的事件,例如ComboBox的SelectionChanged事件,DataGrid的SelectionChanged事件等等,这时就可以用事件绑 ...

  4. 在WPF中引用WinForm的控件

     以ArcEngine为例: mapControl = new AxMapControl(); MapHost.Child = mapControl; //MapHost为WindowsFormHos ...

  5. wpf 中的DataTemplate 绑定控件

    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" x ...

  6. WPF中在后台实现控件样式

    加入现在有一个Button的样式如下: <Style TargetType="{x:Type Button}" x:Key="MyButton">. ...

  7. WindowsXamlHost:在 WPF 中使用 UWP 控件库中的控件

    在 WindowsXamlHost:在 WPF 中使用 UWP 的控件(Windows Community Toolkit) 一文中,我们说到了在 WPF 中引入简单的 UWP 控件以及相关的注意事项 ...

  8. MSDN 杂志:UI 前沿技术 - WPF 中的多点触控操作事件

    原文  MSDN 杂志:UI 前沿技术 - WPF 中的多点触控操作事件 UI 前沿技术 WPF 中的多点触控操作事件 Charles Petzold 下载代码示例 就在过去几年,多点触控还只是科幻电 ...

  9. VS编程,编辑WPF过程中,点击设计器中界面某一控件,在XAML中高亮突出显示相应的控件代码的设置方法。

    原文:VS编程,编辑WPF过程中,点击设计器中界面某一控件,在XAML中高亮突出显示相应的控件代码的设置方法. 版权声明:我不生产代码,我只是代码的搬运工. https://blog.csdn.net ...

随机推荐

  1. 关于c语言struct和typedef

    C++中使用: struct test{    int x, y;};就可以定义一个名为 test的结构体,但C中很可能编译通不过.C语言并不支持在struct后使用标示符定义结构体的名字,test将 ...

  2. FTP服务器配置实践

    1.为linux系统分配IP地址:192.168.X.1/24,并重启网络服务,客户端XP系统IP地址为:192.168.X.2/24, 2.查询本机是否安装了vsftpd服务,结果显示未安装,挂载光 ...

  3. poj1434 Fill the Cisterns!

    地址:http://poj.org/problem?id=1434 题目:Fill the Cisterns! Fill the Cisterns! Time Limit: 5000MS   Memo ...

  4. 基于OpenCV进行图像拼接原理解析和编码实现(提纲 代码和具体内容在课件中)

    一.背景 1.1概念定义 我们这里想要实现的图像拼接,既不是如题图1和2这样的"图片艺术拼接",也不是如图3这样的"显示拼接",而是实现类似"BaiD ...

  5. 关于AutoResetEvent 和ManualResetEvent

    在公司的代码里面看到这两个类的使用了,第一次去msdn上的时候,看的一头雾水(关键是没有找对方法) http://www.cnblogs.com/qingyun163/archive/2013/01/ ...

  6. jquery chosen 插件 动态设置+更新选项值

    我要在表单里使用一个select下拉菜单(是不是multiple无所谓),所以选择了jquery chosen这个插件.现在有一个需求,需要根据表单的另一个域来动态加载该select元素的选项. 1 ...

  7. Hive 建外链表到 Hbase(分内部表、外部表两种方式)

    一. Hive 建内部表,链到hbase :特点:Hive drop表后,Hbase 表同步删除 drop table if exists hbase_kimbo_test1;CREATE TABLE ...

  8. WPF——RenderTransform特效

    WPF: RenderTransform特效 WPF中的变形(RenderTransform)类是为了达到直接去改变某个Silverlight对象的形状(比如缩放.旋转一个元素)的目的而设计的,Ren ...

  9. Mybatis之SSM配置

    applicationContext-dao.xml <?xml version="1.0" encoding="UTF-8"?> <bean ...

  10. hdu1517找规律

    挺像巴什博弈的,直接递推就能找到规律了,从2开始到9,s win,10到18,o win,18到162,s win,一直向下推进 #include<map> #include<set ...