WPF 中托管 UWP

托管标准 UWP 控件

1. 新建空白应用(通用 Windows)项目,确保目标版本和最低版本均设置为 Windows 10 版本 1903 或更高版本。在 UWP 应用项目中,安装 Microsoft.Toolkit.Win32.UI.XamlApplication 

2. 修改App的默认基类为XamlApplication

<xaml:XamlApplication
    ...
    xmlns:xaml="using:Microsoft.Toolkit.Win32.UI.XamlHost"
    ...>

</xaml:XamlApplication>
    sealed partial class App //: Application

3. 从 UWP 应用项目中删除OnLaunched方法,或者删除 MainPage.xaml 文件

以上目的是提供 Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication 类的实例,供WPF使用

 

4. 创建 WPF 应用 ,安装 Microsoft.Toolkit.Wpf.UI.Controls,此包提供使用适用于 WPF 的已包装 UWP 控件所需的所有内容(包括 InkCanvasInkToolbar 和 WindowsXamlHost 控件。

5. 将解决方案配置为面向特定平台,例如 x86 或 x64。 大多数 XAML 岛方案在面向任何 CPU 的项目中不受支持  

6. 在 WPF 项目中,添加对 UWP 应用项目的引用

7. 将WPF程序的默认入口更改为新 Program 类的 Main 方法

public class Program
{
    [System.STAThreadAttribute()]
    public static void Main()
    {
        using (new MyUWPApp.App())
        {
            MyWPFApp.App app = new MyWPFApp.App();
       app.InitializeComponent(); app.Run(); } } }

8. 现已将项目配置为使用 UWP XAML 岛,接下来可以将 InkCanvas 和 InkToolbar 包装的 UWP 控件添加到应用了。

xmlns:Controls="clr-namespace:Microsoft.Toolkit.Wpf.UI.Controls;assembly=Microsoft.Toolkit.Wpf.UI.Controls"

<Controls:InkToolbar x:Name="myInkToolbar" TargetInkCanvas="{x:Reference myInkCanvas}" Grid.Row="0" Width="300"
        Height="50" Margin="10,10,10,10" HorizontalAlignment="Left" VerticalAlignment="Top" />
    <Controls:InkCanvas x:Name="myInkCanvas" Grid.Row="1" HorizontalAlignment="Left" Width="600" Height="400"
        Margin="10,10,10,10" VerticalAlignment="Top" />

9. 默认情况下,仅为数字笔启用 InkCanvas 控件。 不过,你可以更改此行为。

public MainWindow()
        {
            InitializeComponent();

            this.myInkCanvas.InkPresenter.InputDeviceTypes = CoreInputDeviceTypes.Mouse | CoreInputDeviceTypes.Touch;
}

还可以使用 WindowsXamlHost 控件将 CalendarView 添加到应用中

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

<xamlhost:WindowsXamlHost x:Name="myCalendar" InitialTypeName="Windows.UI.Xaml.Controls.CalendarView" Grid.Row="2" 
          Margin="10,10,10,10" Width="600" Height="300" ChildChanged="MyCalendar_ChildChanged"  />
private void MyCalendar_ChildChanged(object sender, EventArgs e)
{
    WindowsXamlHost windowsXamlHost = (WindowsXamlHost)sender;

    Windows.UI.Xaml.Controls.CalendarView calendarView =
        (Windows.UI.Xaml.Controls.CalendarView)windowsXamlHost.Child;

    if (calendarView != null)
    {
        calendarView.SelectedDatesChanged += (obj, args) =>
        {
            if (args.AddedDates.Count > 0)
            {
                MessageBox.Show("The user selected a new date: " + 
                    args.AddedDates[0].DateTime.ToString());
            }
        };
    }
}

 

托管自定义 UWP 控件

只有 WPF 应用(.NET Core) 支持托管自定义UWP

要在 WPF 应用中托管自定义 UWP 控件,必须有此控件的源代码,才能通过应用对其进行编译。 通常在 UWP 类库项目中定义自定义控件,以便于移植。

1. 修改UWP的App.xaml.cs 文件

public App()
        {
            //this.InitializeComponent();
            //this.Suspending += OnSuspending;
            this.Initialize();
        }

2. 新建一个“类库(通用 Windows)” 项目,确保目标版本和最低版本均设置为 Windows 10 版本 1903 或更高版本 。

3. 修改类库的项目文件,在结尾的 </Project> 元素前面,添加以下 XML,以禁用多个属性,然后保存项目文件。 

<PropertyGroup>
  <EnableTypeInfoReflection>false</EnableTypeInfoReflection>
  <EnableXBindDiagnostics>false</EnableXBindDiagnostics>
</PropertyGroup>

4. 假设此用户控件的内容如下

<StackPanel Background="LightCoral">
    <TextBlock>This is a simple custom UWP control</TextBlock>
    <Rectangle Fill="Blue" Height="100" Width="100"/>
    <TextBlock Text="{x:Bind XamlIslandMessage}" FontSize="50"></TextBlock>
</StackPanel>
public sealed partial class MyUserControl : UserControl
{
    public string XamlIslandMessage { get; set; }

    public MyUserControl()
    {
        this.InitializeComponent();
    }
}

5. 生成该类库,添加引用到WPF项目中。同时将类库引用添加到UWP应用项目中

6. 在WPF中添加 

        <xamlhost:WindowsXamlHost InitialTypeName="ClassLibrary1.MyUserControl1" ChildChanged="WindowsXamlHost_ChildChanged" />
        private void WindowsXamlHost_ChildChanged(object sender, EventArgs e)
        {
            global::Microsoft.Toolkit.Wpf.UI.XamlHost.WindowsXamlHost windowsXamlHost =
        sender as global::Microsoft.Toolkit.Wpf.UI.XamlHost.WindowsXamlHost;
            global::ClassLibrary1.MyUserControl1 userControl =
                windowsXamlHost.GetUwpInternalObject() as global::ClassLibrary1.MyUserControl1;

            if (userControl != null)
            {
                userControl.XamlIslandMessage = "Binding from WPF to UWP XAML";
            }
        }

 

将 WinUI 库中的控件添加到自定义控件

如果桌面应用在 MSIX 包中打包,则可以使用 Microsoft.UI.Xaml NugGet 包的预发行版本或发行版本。 如果桌面应用未使用 MSIX 打包,则必须安装 Microsoft.UI.Xaml NuGet 包的预发行版本。

最好使用预发行版本

1. 在UWP应用和类库项目中都安装 Microsoft.UI.Xaml 

2. 在UWP应用项目App.xaml中添加

<Application.Resources>
    <XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
</Application.Resources>

添加到 ResourceDictionary 的资源的顺序会影响它们的应用顺序。 XamlControlsResources 字典会重写许多默认的资源键,因此应先将其添加到 Application.Resources,使之不会在应用中重写任何其他自定义样式或资源。

3. 在类库项目中添加声明 xmlns:winui="using:Microsoft.UI.Xaml.Controls",和控件

<UserControl
    x:Class="ClassLibrary1.MyUserControl1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:ClassLibrary1"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:winui="using:Microsoft.UI.Xaml.Controls"
    mc:Ignorable="d"
    d:DesignHeight="300"
    d:DesignWidth="400">
<StackPanel Background="LightCoral">
    <TextBlock>This is a simple custom UWP control</TextBlock>
    <Rectangle Fill="Blue" Height="100" Width="100"/>
    <TextBlock Text="{x:Bind XamlIslandMessage}" FontSize="50"></TextBlock>
    <winui:RatingControl />
</StackPanel>

 

打包应用

对于WinUI宿主,如果没有安装预发行版本,则必须在 MSIX 包中打包 WPF 应用

  1. 向解决方案中添加一个新的 Windows 应用程序打包项目。 创建项目时,针对“目标版本”和“最低版本”选择“Windows 10 版本 1903 (10.0;版本 18362)” 。

  2. 在打包项目中,右键单击“应用程序”节点,然后选择“添加引用” 。 在项目列表中,选择解决方案中的 WPF 项目,然后单击“确认” 。

  3. 编辑此 WPF 项目文件。 若要打包托管自定义 UWP 控件的 WPF 应用,目前需要完成以下更改。

    1. 在“解决方案资源管理器”中右键单击 WPF 项目节点,然后选择“卸载项目”。

    2. 右键单击 WPF 项目节点,选择“编辑”。

    3. 找到文件的最后一个 </PropertyGroup> 结束标记,紧随该标记之后添加以下 XML。

      XML
      <PropertyGroup>
        <AssetTargetFallback>uap10.0.18362</AssetTargetFallback>
      </PropertyGroup>
      
    4. 保存并关闭项目文件。

    5. 右键单击 WPF 项目节点,选择“重新加载项目”。

  4. 生成并运行打包项目。 确认 WPF 按预期运行,并且 UWP 自定义控件按预期方式显示。

 

posted @ 2020-07-19 11:46  yetsen  阅读(496)  评论(0编辑  收藏  举报