zoukankan      html  css  js  c++  java
  • .NET Core学习笔记(2)—— WPF使用UWP Custom Control

    自.NET Core 3.0开始,某软加入了对WPF的支持。同时对XAML Islands也做了进一步加强。在.NET Core 3.0之前,我们只能在WPF程序中,通过两种方式有限制地使用Standard UWP Control:

    1. 微软包装好的第一方控件,比如InkCanvas,InkToolbar,MediaPlayerElement和MapControl,这些可以直接当成WPF的控件写到XAML中。

    2. 通过WindowsXamlHost来使用的其他微软第一方Standard UWP Control,这种方式不支持XAML,需要在cs代码中进行类型转换和订阅事件。

    这两种方式都存在一些问题:

    • 很多UWP      Control和WPF Control虽然同名,但实际仍是不同namespace下的不同class,在传递数据时会遇到很大的麻烦,例如设置FontFamily,Brush时会发现其实是两套同名class,分别属于System.Windows.Media和Windows.UI.Xaml.Media这两套namespace。

    • 不支持XAML导致UI的实现受到极大的限制,对Style和Template的使用极不友好。导致在一个WPF程序中,很难将UI界面上同时存在的WPF Control和UWP Control设置成相同的外观。

    而在.NET Core 3.0中,我们终于可以在WPF中嵌入UWP Custom Control。虽仍然是通过WindowsXamlHost来导入Custom Control,但这意味着:

    1. 我们可以创建一个独立的UWP Control Library。在该Library中,和UWP API的交互将不存在任何障碍。同时通过良好的封装,将类型转换的逻辑写在内部,对外仅暴露WPF类型的情况下,可以有效的避免UWP Control和WPF Control同名的问题。在外部调用的WPF程序看来,这就是一个纯的WPF Control。

    2. 因为Style和Template不再受到限制,对UI的控制力完全释放,我们甚至可以将整个页面放到UWP      Custom Control中,制作一个完全使用UWP Control的exe程序。

    下面我们就来看看如何具体实现:

    首先我们需要安装.NET Core 3.0,在此基础之上我们才可以创建基于.NET Core的WPF程序了。

    创建一个空的WPF工程后,在NuGet中搜索Microsoft.Toolkit.Wpf.UI.XamlHost并进行安装。这个Package将提供WindowsXamlHost对象供我们导入UWP Custom Control。完成后,记得将WPF工程的类型,从默认的Any CPU改成x64或者x86。这是因为UWP工程不支持Any CPU。

    接下来创建的第二个工程,是一个空的UWP工程,UWP的版本确保是1903或者更新。通过NuGet安装Microsoft.Toolkit.Win32.UI.XamlApplication。这个空的UWP工程将成为WPF程序和UWP Custom Control之间的桥梁。

    对于这个空的UWP工程,我们仅需保留App.xml文件,将App的继承关系改为继承自XamlApplication对象。

    <xaml:XamlApplication
        x:Class="MyUWPApp.App"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:xaml="using:Microsoft.Toolkit.Win32.UI.XamlHost"
        xmlns:local="using:MyUWPApp">
    </xaml:XamlApplication>

     App.xaml.cs中,也仅保留构造函数即可。

        sealed partial class App : Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication
        {
            /// <summary>
            /// Initializes the singleton application object.  This is the first line of authored code
            /// executed, and as such is the logical equivalent of main() or WinMain().
            /// </summary>
            public App()
            {
                this.Initialize();
            }
        }

    接着将MainPage.xaml文件整个删除,编译通过后,在WPF工程里添加对MyUWPApp的reference,这个中间人的工程就准备完毕了。

    接下来让我们创建真正的UWP Custom Control Library。首先选择Class Library(Universal Windows),创建完成后,右键工程文件选择Unload再选择Edit,在工程文件的最下方,添加下述配置项:

      <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
           Other similar extension points exist, see Microsoft.Common.targets.
      <Target Name="BeforeBuild">
      </Target>
      <Target Name="AfterBuild">
      </Target>
      -->
      <PropertyGroup>
        <EnableTypeInfoReflection>false</EnableTypeInfoReflection>
        <EnableXBindDiagnostics>false</EnableXBindDiagnostics>
      </PropertyGroup>
    </Project>

    保存后Reload工程。完成上述操作后,再新建几个简单的UWP Custome Control。之后需要在WPF和MyUWPApp这两个工程中,分别添加对UWPClassLibrary工程的reference。这些reference的添加都是必须的,缺少了其中的任何一项,都会导致最终Host UWP Control失败。

    此时让我们返回到WPF工程中,开始使用UWPClassLibrary中刚刚创建的UWP Custom Control。

        <Grid>
            <xaml:WindowsXamlHost InitialTypeName="UWPClassLibrary.SplitViewDemo"  ChildChanged="WindowsXamlHost_ChildChanged_1" />
        </Grid>

    和之前使用微软第一方Control较为类似,也是通过WindowsXamlHost 节点指定类型,以及在ChildChanged事件来进行类型转换获取对象实例。

            private void WindowsXamlHost_ChildChanged_1(object sender, EventArgs e)
            {
                global::Microsoft.Toolkit.Wpf.UI.XamlHost.WindowsXamlHost windowsXamlHost =
                    sender as global::Microsoft.Toolkit.Wpf.UI.XamlHost.WindowsXamlHost;
                global::UWPClassLibrary.SplitViewDemo userControl =
                    windowsXamlHost.GetUwpInternalObject() as global::UWPClassLibrary.SplitViewDemo;
      
                if (userControl != null)
                {
                    userControl.IconList = new ObservableCollection<NavItem>
                {
                    new NavItem { Symbol= Symbol.Save},
                    new NavItem { Symbol= Symbol.Scan},
                    new NavItem { Symbol= Symbol.Share},
                    new NavItem { Symbol= Symbol.Stop},
                    new NavItem { Symbol= Symbol.Video},
                    new NavItem { Symbol= Symbol.Volume},
                };
                }
            }

    在我们的Sample工程中,我将名为SplitViewDemo的UserControl整个丢到了WPF工程的Page中。运行后我们可以发现,这看起来就像是套了WPF外壳的UWP页面。

     本篇动手实践的部分较多,还请各位同学下载Sample工程一探究竟。

    Github:

    https://github.com/manupstairs/WpfHostUwpControlSample

  • 相关阅读:
    【算法学习笔记】27.动态规划 解题报告 SJTU OJ 1254 传手绢
    【算法学习笔记】26.扫描维护法 解题报告 SJTU OJ 1133 数星星
    【算法学习笔记】25.贪心法 均分纸牌问题的分析
    【算法学习笔记】24.记忆化搜索 解题报告 SJTU OJ 1002 二哥种花生
    【算法学习笔记】23.动态规划 解题报告 SJTU OJ 1280 整装待发
    【算法学习笔记】22.算法设计初步 二分查找 上下界判断
    【算法学习笔记】21.算法设计初步 求第k个数 划分法 快排法
    【算法学习笔记】20.算法设计初步 归并排序 求逆序数
    【算法学习笔记】19.算法设计初步 最大子列和问题的几种方法
    【算法学习笔记】18.暴力求解法06 隐式图搜索2 八数码问题 未启发
  • 原文地址:https://www.cnblogs.com/manupstairs/p/12085084.html
Copyright © 2011-2022 走看看