Поделиться через


Размещение пользовательского элемента управления WinRT XAML в приложении WPF с помощью XAML Islands

Внимание

В этом разделе используются или упоминаются типы из репозитория CommunityToolkit/Microsoft.Toolkit.Win32 GitHub. Дополнительные сведения о поддержке XAML Islands см . в уведомлении о xaml Islands в этом репозитории.

В этой статье содержатся сведения об использовании элемента управления WindowsXamlHost в наборе средств сообщества Windows для размещения пользовательского элемента управления WinRT XAML в приложении WPF, предназначенном для .NET Core 3.1. Настраиваемые элементы управления содержат несколько основных элементов управления WinRT XAML из пакета Windows SDK. Кроме того, они связывают свойство в одном из элементов управления WinRT XAML со строкой приложения WPF. В этой статье также показано, как разместить элемент управления WinRT XAML из библиотеки WinUI.

Хотя в этой статье показано, как выполнить эти действия в приложении WPF, для приложения Windows Forms процесс является аналогичным. Общие сведения о размещении элементов управления WinRT XAML в приложениях WPF и Windows Forms см. в этой статье.

Примечание.

Использование XAML Islands для размещения элементов управления WinRT XAML в приложениях WPF и Windows Forms сейчас поддерживают только приложения, предназначенные для .NET Core 3.x. XAML Islands пока не поддерживают приложения, предназначенные для .NET, или предложения для любой версии .NET Framework.

Необходимые компоненты

Чтобы разместить пользовательский элемент управления WinRT XAML в приложении WPF (или Windows Forms), вам потребуются указанные ниже компоненты в решении. Эта статья содержит инструкции по созданию каждого из этих компонентов.

  • Код проекта и исходный код приложения. Использование элемента управления WindowsXamlHost для размещения настраиваемых элементов управления WinRT XAML поддерживается только в приложениях, предназначенных для .NET Core версии 3.x.

  • Пользовательский элемент управления WinRT XAML Для настраиваемого элемента управления, который необходимо разместить, необходим исходный код, чтобы скомпилировать его в приложение. Как правило, настраиваемый элемент управления определяется в проекте библиотеки классов UWP, на которую вы ссылаетесь в решении с проектом WPF или Windows Forms.

  • Проект приложения UWP, определяющий корневой класс Application, производный от XamlApplication. В проекте WPF или Windows Forms должен быть доступ к экземпляру класса Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication, предоставленному в наборе средств сообщества Windows, чтобы он мог обнаруживать и загружать настраиваемые элементы управления UWP XAML. Для этого рекомендуется определить объект в отдельном проекте приложения UWP, который является частью решения приложения WPF или Windows Forms.

    Примечание.

    Решение может содержать только один проект, определяющий объект XamlApplication. Все пользовательские элементы управления WinRT XAML в приложении используют один и тот же объект XamlApplication. Проект, определяющий объект XamlApplication, должен содержать ссылки на все другие библиотеки и проекты WinRT, которые используются для размещения элементов управления в XAML Island.

Создание проекта WPF

Перед началом работы выполните следующие инструкции, чтобы создать проект WPF и настроить его для размещения XAML Islands. Если у вас есть проект WPF, вы можете адаптировать под него эти шаги и примеры кода.

Примечание.

Если у вас есть проект, предназначенный для .NET Framework, его необходимо перенести на .NET Core 3.1. Дополнительные сведения см. в этой записи блога.

  1. Если вы еще не сделали этого, установите последнюю версию пакета SDK для .NET CoreCore 3.1.

  2. В Visual Studio 2019 создайте проект приложения WPF (.NET Core).

  3. Убедитесь, что включены следующие ссылки на пакеты:

    1. В Visual Studio, выберите Инструменты -> Диспетчер пакетов NuGet -> Параметры диспетчера пакетов.
    2. Убедитесь, что для формата управления пакетами по умолчанию установлено значение PackageReference.
  4. В обозревателе решений щелкните правой кнопкой мыши проект WPF и выберите пункт Manage NuGet Packages (Управление пакетами NuGet).

  5. Откройте вкладку Обзор, найдите пакет Microsoft.Toolkit.Wpf.UI.XamlHost и установите последнюю стабильную версию этого пакета. Этот пакет содержит все необходимые компоненты для размещения элемента управления WinRT XAML, в том числе другие связанные пакеты NuGet, с помощью элемента управления WindowsXamlHost.

    Примечание.

    В приложениях Windows Forms необходимо использовать пакет Microsoft.Toolkit.Forms.UI.XamlHost.

  6. Настройте решение для конкретной платформы, например x86 или x64. Настраиваемые элементы управления WinRT XAML не поддерживаются в проектах, предназначенных для любого ЦП.

    1. В обозревателе решений, щелкните правой кнопкой мыши по узлу решения и выберите Свойства ->Свойства конфигурации ->Configuration Manager.
    2. В списке Active solution platform (Активная платформа решения) выберите пункт Создать.
    3. В диалоговом окне Создание платформы решения выберите x64 или x86 и нажмите кнопку ОК.
    4. Закройте открытые диалоговые окна.

Определение класса XamlApplication в проекте приложения UWP

Далее добавьте проект приложения UWP в решение и измените стандартный класс App в этом проекте, чтобы он был производным от класса Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication, предоставленного в наборе средств сообщества Windows. Этот класс поддерживает интерфейс IXamlMetadataProvider, который позволяет приложению обнаруживать и загружать метаданные для настраиваемых элементов управления UWP XAML в сборках в текущем каталоге приложения во время выполнения. Этот класс также инициализирует платформу UWP XAML для текущего потока.

  1. В обозревателе решений, щелкните правой кнопкой мыши по узлу решения и выберите Добавить ->Новый проект.

  2. Добавьте проект Пустое приложение (универсальное приложение Windows) в свое решение. Убедитесь, что в качестве целевой и самой ранней версии используется Windows 10 версии 1903 (сборка 18362) или более позднего выпуска.

  3. В проекте приложения UWP установите пакет NuGet Microsoft.Toolkit.Win32.UI.XamlApplication (последняя стабильная версия).

  4. Откройте файл App.xaml и замените его содержимое приведенным ниже кодом XAML. Замените MyUWPApp пространством имен проекта приложения UWP.

    <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>
    
  5. Откройте файл App.xaml.cs и замените его содержимое приведенным ниже кодом. Замените MyUWPApp пространством имен проекта приложения UWP.

    namespace MyUWPApp
    {
        public sealed partial class App : Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication
        {
            public App()
            {
                this.Initialize();
            }
        }
    }
    
  6. Удалите файл MainPage.xaml из проекта приложения UWP.

  7. Очистите проект приложения UWP, а затем выполните его сборку.

Добавление ссылки на проект приложения UWP в проекте WPF

  1. Укажите совместимую версию платформы в файле проекта WPF.

    1. В обозревателе решений дважды щелкните узел проекта WPF, чтобы открыть файл проекта в редакторе.

    2. В первый элемент PropertyGroup добавьте следующий дочерний элемент. При необходимости измените часть значения 19041, чтобы оно соответствовало целевой и самой ранней версиям сборки ОС проекта UWP.

      <AssetTargetFallback>uap10.0.19041</AssetTargetFallback>
      

      Когда все будет готово, элемент PropertyGroup должен выглядеть примерно так.

      <PropertyGroup>
          <OutputType>WinExe</OutputType>
          <TargetFramework>netcoreapp3.1</TargetFramework>
          <UseWPF>true</UseWPF>
          <Platforms>AnyCPU;x64</Platforms>
          <AssetTargetFallback>uap10.0.19041</AssetTargetFallback>
      </PropertyGroup>
      
  2. В обозревателе решений щелкните правой кнопкой мыши узел Зависимости в проекте WPF и добавьте ссылку на проект приложения UWP.

Создание экземпляра объекта XamlApplication в точке входа приложения WPF

Далее добавьте код к точке входа приложения WPF, чтобы создать экземпляр класса App, определенного в проекте UWP (этот класс является производным от XamlApplication).

  1. В своем WPF проекте щелкните правой кнопкой мыши по узлу проекта, выберите Добавить ->Новый элемент, затем выберите Класс. Назовите класс Program и щелкните Добавить.

  2. Замените созданный класс Program кодом ниже, а затем сохраните файл. Замените MyUWPApp пространством имен проекта приложения UWP, а MyWPFApp — пространством имен проекта приложения WPF.

    public class Program
    {
        [System.STAThreadAttribute()]
        public static void Main()
        {
            using (new MyUWPApp.App())
            {
                MyWPFApp.App app = new MyWPFApp.App();
                app.InitializeComponent();
                app.Run();
            }
        }
    }
    
  3. Щелкните правой кнопкой мыши узел проекта и выберите пункт Свойства.

  4. На вкладке Приложение в диалоговом окне "Свойства" щелкните раскрывающийся список Объект запуска и выберите полное имя класса Program, добавленного на предыдущем шаге.

    Примечание.

    По умолчанию проекты WPF определяют функцию точки входа Main в созданном файле кода, который нельзя изменить. На этом шаге точка входа проекта изменяется на метод Main нового класса Program, что позволяет добавить код, который как можно раньше выполняется в процессе запуска приложения.

  5. Сохраните изменения в свойствах проекта.

Создание пользовательского элемента управления WinRT XAML

Чтобы разместить пользовательский элемент управления WinRT XAML в приложении WPF, необходим исходный код элемента управления, чтобы скомпилировать его в приложение. Обычно, чтобы облегчить перенос, настраиваемые элементы управления определяются в проекте библиотеки классов UWP.

Проходя этот раздел, вы определите простой пользовательский элемент управления в новом проекте библиотеки классов. Вы также можете определить пользовательский элемент управления в проекте приложения UWP, созданном при прохождении предыдущего раздела. Но для демонстрации эти действия выполняются в отдельном проекте библиотеки классов, так как это типичный способ внедрения настраиваемых элементов управления, чтобы обеспечить возможность переноса.

Если у вас уже есть настраиваемый элемент управления, его можно использовать вместо элемента управления, показанного здесь. Но вам все равно необходимо настроить проект, содержащий элемент управления, как показано в этих шагах.

  1. В обозревателе решений, щелкните правой кнопкой мыши по узлу решения и выберите Добавить ->Новый проект.

  2. Добавьте проект библиотеки классов (универсальная платформа Windows) в свое решение. Убедитесь, что для целевой и самой ранней версии установлены те же значения, что и для целевой и минимальной сборки ОС проекта UWP.

  3. Щелкните правой кнопкой мыши файл проекта и выберите команду Выгрузить проект. Снова щелкните правой кнопкой мыши файл проекта и выберите команду Изменить.

  4. Перед закрывающим элементом </Project> добавьте указанный ниже XML-код, чтобы отключить несколько свойств, а затем сохраните файл проекта. Эти свойства должны быть включены для размещения пользовательского элемента управления в приложении WPF (или Windows Forms).

    <PropertyGroup>
      <EnableTypeInfoReflection>false</EnableTypeInfoReflection>
      <EnableXBindDiagnostics>false</EnableXBindDiagnostics>
    </PropertyGroup>
    
  5. Щелкните правой кнопкой мыши файл проекта и выберите команду Перезагрузить проект.

  6. Удалите стандартный файл Class1.cs и добавьте новый пользовательский элемент управления в проект.

  7. В файле XAML для пользовательского элемента управления добавьте следующий объект StackPanel в качестве дочернего элемента Grid по умолчанию. В этом примере добавляется элемент управления TextBlock, а затем атрибут Text этого элемента управления привязывается к полю XamlIslandMessage.

    <StackPanel Background="LightCoral">
        <TextBlock>This is a simple custom WinRT XAML control</TextBlock>
        <Rectangle Fill="Blue" Height="100" Width="100"/>
        <TextBlock Text="{x:Bind XamlIslandMessage}" FontSize="50"></TextBlock>
    </StackPanel>
    
  8. В файле кода программной части пользовательского интерфейса добавьте поле XamlIslandMessage к классу пользовательского элемента управления, как показано ниже.

    public sealed partial class MyUserControl : UserControl
    {
        public string XamlIslandMessage { get; set; }
    
        public MyUserControl()
        {
            this.InitializeComponent();
        }
    }
    
  9. Выполните сборку проекта библиотеки классов UWP.

  10. В проекте WPF щелкните правой кнопкой мыши узел Зависимости и добавьте ссылку на проект библиотеки классов UWP.

  11. В ранее настроенном проекте приложения UWP щелкните правой кнопкой мыши узел Ссылки и добавьте ссылку на проект библиотеки классов UWP.

  12. Перестройте все решение и убедитесь, что все проекты успешно построены.

Размещение пользовательского элемента управления WinRT XAML в приложении WPF

  1. В обозревателе решений разверните проект WPF и откройте файл MainWindow.xaml или другое окно, где вам необходимо разместить настраиваемый элемент управления.

  2. В файле XAML добавьте следующее объявление пространства имен в элемент <Window>.

    xmlns:xaml="clr-namespace:Microsoft.Toolkit.Wpf.UI.XamlHost;assembly=Microsoft.Toolkit.Wpf.UI.XamlHost"
    
  3. В том же файле добавьте указанный ниже элемент управления в элемент <Grid>. Измените атрибут InitialTypeName на полное имя пользовательского элемента управления в проекте библиотеки классов UWP.

    <xaml:WindowsXamlHost InitialTypeName="UWPClassLibrary.MyUserControl" ChildChanged="WindowsXamlHost_ChildChanged" />
    
  4. Откройте файл кода программной части и добавьте указанный ниже код в класс Window. Этот код определяет обработчик событий ChildChanged, который присваивает значение поля XamlIslandMessage настраиваемого элемента управления UWP в качестве значения поля WPFMessage в приложении WPF. Измените UWPClassLibrary.MyUserControl на полное имя пользовательского элемента управления в проекте библиотеки классов UWP.

    private void WindowsXamlHost_ChildChanged(object sender, EventArgs e)
    {
        // Hook up x:Bind source.
        global::Microsoft.Toolkit.Wpf.UI.XamlHost.WindowsXamlHost windowsXamlHost =
            sender as global::Microsoft.Toolkit.Wpf.UI.XamlHost.WindowsXamlHost;
        global::UWPClassLibrary.MyUserControl userControl =
            windowsXamlHost.GetUwpInternalObject() as global::UWPClassLibrary.MyUserControl;
    
        if (userControl != null)
        {
            userControl.XamlIslandMessage = this.WPFMessage;
        }
    }
    
    public string WPFMessage
    {
        get
        {
            return "Binding from WPF to UWP XAML";
        }
    }
    
  5. Выполните сборку и запустите приложение, а затем убедитесь, что пользовательский элемент управления UWP отображается должным образом.

Добавление элемента управления из библиотеки WinUI версии 2 в пользовательский элемент управления

В большинстве случаев элементы управления WinRT XAML выпущены в составе ОС Windows. Разработчики могут использовать их через Windows SDK. В качестве альтернативного варианта можно использовать библиотеку WinUI. Здесь обновленные версии элементов управления WinRT XAML из пакета Windows SDK распределены в пакете NuGet, который не связан с выпусками пакета Windows SDK. Эта библиотека также содержит новые элементы управления, которые не входят в состав пакета Windows SDK и платформы UWP по умолчанию.

В этом разделе показано, как добавить элемент управления WinRT XAML из библиотеки WinUI версии 2 в пользовательский элемент управления.

Примечание.

Сейчас XAML Islands поддерживают только размещение элементов управления из библиотеки WinUI версии 2. Поддержка размещения элементов управления из библиотеки WinUI 3 будет реализована в более позднем выпуске.

  1. В проекте приложения UWP установите последнюю предварительную или окончательную версию пакета NuGet Microsoft.UI.Xaml.

    Примечание.

    Если классическое приложение упаковано в пакет MSIX, можно использовать последнюю предварительную или окончательную версию пакета NuGet Microsoft.UI.Xaml. Если классическое приложение не упаковано с помощью MSIX, необходимо установить последнюю предварительную версию пакета NuGet Microsoft.UI.Xaml.

  2. В файле App.xaml этого проекта добавьте следующий дочерний элемент в элемент <xaml:XamlApplication>.

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

    После добавления этого элемента содержимое файла должно выглядеть следующим образом:

    <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">
        <Application.Resources>
            <XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
        </Application.Resources>
    </xaml:XamlApplication>
    
  3. В проекте библиотеки классов UWP установите последнюю версию пакета NuGet Microsoft.UI.Xaml (той же версии, которая установлена в проекте приложения UWP).

  4. В том же проекте откройте файл XAML пользовательского элемента управления и добавьте следующее объявление пространства имен в элемент <UserControl>.

    xmlns:winui="using:Microsoft.UI.Xaml.Controls"
    
  5. В том же файле добавьте элемент <winui:RatingControl /> в качестве дочернего элемента <StackPanel>. Этот элемент добавляет экземпляр класса RatingControl из библиотеки WinUI. После добавления этого элемента <StackPanel> должен выглядеть следующим образом.

    <StackPanel Background="LightCoral">
        <TextBlock>This is a simple custom WinRT XAML control</TextBlock>
        <Rectangle Fill="Blue" Height="100" Width="100"/>
        <TextBlock Text="{x:Bind XamlIslandMessage}" FontSize="50"></TextBlock>
        <winui:RatingControl />
    </StackPanel>
    
  6. Выполните сборку и запустите приложение, а затем убедитесь, что новый элемент управления для оценки отображается должным образом.

Создание пакета приложения

При необходимости вы можете упаковать приложение WPF в пакет MSIX для развертывания. MSIX — это современная технология упаковки приложений для Windows. В ее основе лежат технологии установки MSI, APPX, App-V и ClickOnce.

В приведенных ниже инструкциях рассказывается, как упаковать все компоненты решения в пакет MSIX с помощью проекта упаковки приложения Windows в Visual Studio 2019. Эти действия необходимы только в том случае, если нужно упаковать приложение WPF в пакет MSIX.

Примечание.

Если вы решили не упаковывать приложение в пакет MSIX для развертывания, на компьютерах с запущенными приложениями должна быть установлена среда выполнения Visual C++.

  1. Добавьте новый проект упаковки приложений Windows в свое решение. При создании проекта выберите те же целевую и минимальную версии, что и для проекта UWP.

  2. В проекте упаковки щелкните правой кнопкой мыши узел Приложения и выберите команду Добавить ссылку. В списке проектов выберите проект WPF в решении и нажмите кнопку ОК.

    Примечание.

    Если вы хотите опубликовать приложение в Microsoft Store, необходимо добавить в проект упаковки ссылку на проект UWP.

  3. Настройте решение для конкретной платформы, например x86 или x64. Это необходимо для выполнения сборки приложения WPF в пакет MSIX с помощью проекта упаковки приложений Windows.

    1. В обозревателе решений, щелкните правой кнопкой мыши по узлу решения и выберите Свойства ->Свойства конфигурации ->Configuration Manager.
    2. В списке Active solution platform (Активная платформа решения) выберите пункт x64 или x86.
    3. В строке проекта WPF в столбце Платформа щелкните Создать.
    4. В диалоговом окне Создание платформы решения выберите x64 или x86 (ту же платформу, которую вы выбрали в списке Active solution platform (Активная платформа решения)) и нажмите кнопку ОК.
    5. Закройте открытые диалоговые окна.
  4. Выполните сборку и запустите проект упаковки. Убедитесь, что WPF выполняется и настраиваемый элемент управления UWP отображается должным образом.

  5. Сведения о распространении и развертывании пакета см. в статье Управление развертыванием MSIX.

Устранение ошибки"Не удалось найти ресурс" при размещении элемента управления WinUI

Если вы размещаете пользовательский элемент управления, содержащий элемент управления из библиотеки WinUI, может возникнуть проблема, из-за которой элемент управления не удается загрузить в упакованное приложение, а при отладке кода отображается следующая ошибка.

Не удалось разместить элемент управления библиотекой WinUI

Для решения этой ошибки, скопируйте файл App.xbf из папки сборки выходных файлов проекта WPF в папку сборки выходных файлов проекта упаковки \AppX\<WPF project>.

Например, если проект WPF имеет имя WPFXamlIslandsApp и предназначен для платформы x86, скопируйте App.xbf из \WPFXamlIslandsApp\bin\x86\Release\netcoreapp3.1 в \WPFXamlIslandsApp.Pack\bin\x86\Release\AppX\WPFXamlIslandsAPP.