Использование XAML Islands для размещения элемента управления XAML UWP в приложении WPF на C#

Важно!

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

В этой теме показано, как создать приложение Windows Presentation Foundation (WPF) на C# (предназначенное для .NET Core 3.1), которое использует XAML Islands для размещения элемента управления XAML универсальной платформы Windows (UWP) (то есть элемента управления, предоставляемого пакетом Windows SDK). Мы покажем, как сделать это двумя разными способами:

  • В ней описано, как разместить элементы управления UWP InkCanvas и InkToolbar, используя заключенные в оболочку элементы управления в наборе средств сообщества Windows. Эти элементы управления заключают интерфейс и функциональные возможности небольшого набора полезных элементов управления UWP XAML в оболочку. Можно добавить эти заключенные в оболочку элементы управления напрямую в область проектирования вашего проекта WPF или Windows Forms, а затем использовать их как и любой другой элемент управления WPF или Windows Forms в конструкторе.

  • Здесь также показано, как разместить элемент управления UWP CalendarView с помощью элемента управления WindowsXamlHost из набора средств сообщества Windows. Так как в качестве заключенных в оболочку элементов управления доступен только небольшой набор элементов управления UWP XAML, вы можете использовать WindowsXamlHost для размещения любого элемента управления UWP XAML.

Процесс размещения элемента управления XAML UWP в приложении WPF аналогичен для приложения Windows Forms.

Важно!

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

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

  • Проект и исходный код для приложения WPF или Windows Forms.

  • Проект UWP, определяющий корневой класс Application, производный от XamlApplication. Класс Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication доступен в наборе средств сообщества Windows. Мы рекомендуем определить класс приложения, производного от XamlApplication, как отдельный проект приложения UWP, который входит в состав решения WPF или Windows Forms Visual Studio.

    Примечание.

    Делать объект, производный от XamlApplication, доступным для проекта WPF или Windows Forms, фактически не обязательно для размещения элемента управления XAML UWP. Но это необходимо для обнаружения, загрузки и размещения пользовательских элементов управления XAML UWP. Итак, для поддержки полного спектра сценариев XAML Islands рекомендуется всегда определять объект, производный от XamlApplication, в любом решении, в котором используется XAML Islands.

    Примечание.

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

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

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

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

  2. В Visual Studio создайте новый проект на C# на основе шаблона проекта Приложение WPF. Задайте Имя проекта равным MyWPFApp, чтобы вам не нужно было изменять шаги и исходный код, которые приведены в этой теме. Установите платформу равной .NET Core 3,1* и нажмите кнопку Создать.

Важно!

Не используйте шаблон проекта Приложение WPF (платформа .NET Framework).

Настройка проекта WPF

  1. Ниже приведены действия по включению ссылок на пакеты.

    1. В Visual Studio выберите элементы Сервис>Диспетчер пакетов NuGet>Параметры диспетчера пакетов.
    2. В правой части найдите параметрУправление пакетами>Формат управления пакетами по умолчанию и задайте для него значение PackageReference.
  2. Выполните описанные ниже действия, чтобы установить пакет NuGet Microsoft.Toolkit.Wpf.UI.Controls:

    1. Щелкните правой кнопкой мыши узел проекта MyWPFApp в обозревателе решений и выберите пункт Управление пакетами NuGet....

    2. На вкладке Обзор введите или вставьте в поле поиска Microsoft.Toolkit.Wpf.UI.Controls. Выберите последнюю стабильную версию и нажмите кнопку Установить. Этот пакет содержит все необходимые компоненты для использования заключенных в оболочку элементов управления UWP XAML для WPF (в том числе элементы управления InkCanvas, InkToolbar и WindowsXamlHost).

    Примечание.

    В приложениях Windows Forms ссылайтесь на Microsoft.Toolkit.Forms.UI.Controls вместо этого пакета.

  3. Большинство сценариев XAML Islands не поддерживаются в проектах, предназначенных для любого ЦП. Чтобы ориентироваться на конкретную архитектуру (например, x86 или x64), выполните следующие действия:

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

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

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

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

  2. Выберите шаблон проекта Пустое приложение (универсальное приложение Windows) на C#. Задайте Имя проекта равным MyUWPApp, чтобы вам не нужно было изменять шаги и исходный код, которые приведены в этой теме. Задайте в полях для выбора целевой и минимальной версии значение Windows 10, версия 1903 (сборка 18362) или более позднюю версию.

    Примечание.

    Не создавайте MyUWPApp во вложенной папке MyWPFApp. Если это сделать, MyWPFApp попытается создать разметку XAML UWP как для XAML WPF.

  3. В MyUWPApp установите пакет NuGet Microsoft.Toolkit.Win32.UI.XamlApplication (последняя стабильная версия). Процесс установки пакета NuGet был описан в предыдущем разделе.

  4. В MyUWPAppоткройте файл App.xaml и замените его содержимое следующим кодом XAML:

    <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 и замените его содержимое следующим кодом:

    namespace MyUWPApp
    {
        public sealed partial class App : Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication
        {
            public App()
            {
                this.Initialize();
            }
        }
    }
    
  6. Удалите файлы MainPage.xaml и MainPage.xaml.cs.

  7. Создайте проект MyUWPApp.

В MyWPFApp добавьте ссылку на проект MyUWPApp.

  1. Укажите совместимую версию платформы в файле проекта MyWPFApp следующим образом:

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

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

      <AssetTargetFallback>uap10.0.19041</AssetTargetFallback>
      
  2. В обозревателе решений щелкните правой кнопкой мыши MyWPFApp>Зависимости, выберите Добавить ссылку на проект... и добавьте ссылку на проект MyUWPApp.

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

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

  1. Щелкните правой кнопкой мыши узел проекта MyWPFApp, выберите Добавить>Новый элемент..., а затем щелкните Класс. В поле Имя укажите Program.cs и нажмите Добавить.

  2. Замените содержимое Program.cs следующим кодом XAML, а затем сохраните файл и выполните сборку проекта MyWPFApp:

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

  4. В разделе Приложение>Общие в раскрывающемся списке Автоматически запускаемый объект выберите MyWPFApp.Program (полное имя только что добавленного класса Program). Если вы не видите этот вариант, попробуйте закрыть и снова открыть Visual Studio.

    Примечание.

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

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

Использование заключенных в оболочку элементов управления для размещения InkCanvas и InkToolbar

Теперь, когда вы настроили в проекте XAML Islands для UWP, вы можете добавить в приложение заключенные в оболочку элементы управления UWP InkCanvas и InkToolbar.

  1. В MyWPFApp откройте файл MainWindow.xaml.

  2. В элемент Window в верхней части XAML-файла добавьте следующий атрибут. Этот атрибут ссылается на пространство имен XAML для заключенных в оболочку элементов управления XAML UWP класса InkCanvas и InkToolbar и сопоставляет его с пространством имен XML элементов управления.

    xmlns:controls="clr-namespace:Microsoft.Toolkit.Wpf.UI.Controls;assembly=Microsoft.Toolkit.Wpf.UI.Controls"
    
  3. В MainWindow.xaml измените существующий элемент Grid так, чтобы он выглядел как приведенный ниже XAML. Этот XAML добавляет в Grid элемент управления InkCanvas и InkToolbar (с префиксом пространства имен XML элементов управления, определенным на предыдущем шаге).

    <Grid Margin="10,50,10,10">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <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" />
    </Grid>
    

    Примечание.

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

  4. Сохраните MainWindow.xaml.

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

  5. В MyWPFAppоткройте MainWindow.xaml.cs.

  6. Добавьте следующую директиву пространства имен в начало файла:

    using Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT;
    
  7. Откройте конструктор MainWindow. Сразу после вызова метода InitializeComponent добавьте следующую строку кода:

    myInkCanvas.InkPresenter.InputDeviceTypes = CoreInputDeviceTypes.Mouse | CoreInputDeviceTypes.Pen;
    

    Вы можете настроить интерфейс рукописного ввода по умолчанию, используя объект InkPresenter. Код выше использует свойство InputDeviceTypes для поддержки мыши в качестве устройства рукописного ввода.

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

Размещение CalendarView с использованием размещаемого элемента управления

В этом разделе мы будем использовать элемент управления WindowsXamlHost для добавления CalendarView в приложение.

Примечание.

Элемент управления WindowsXamlHost предоставляется с пакетом Microsoft.Toolkit.Wpf.UI.XamlHost. Этот пакет входит в установленный ранее пакет Microsoft.Toolkit.Wpf.UI.Controls.

  1. В обозревателе решений откройте в проекте MyWPFApp файл MainWindow.xaml.

  2. В элемент Window в верхней части XAML-файла добавьте следующий атрибут. Этот атрибут ссылается на пространство имен XAML для элемента управления WindowsXamlHost и сопоставляет его с пространством имен XML xamlhost.

    xmlns:xamlhost="clr-namespace:Microsoft.Toolkit.Wpf.UI.XamlHost;assembly=Microsoft.Toolkit.Wpf.UI.XamlHost"
    
  3. В MainWindow.xaml измените существующий элемент Grid так, чтобы он выглядел как приведенный ниже XAML. Этот XAML добавляет в Grid элемент управления WindowsXamlHost (с префиксом пространства имен XML xamlhost, который вы определили на предыдущем шаге). Чтобы разместить элемент управления UWP CalendarView, этот код XAML задает для свойства InitialTypeName полное имя элемента управления. Этот код XAML также определяет обработчик событий для события ChildChanged, которое происходит при преобразовании размещенного элемента управления для просмотра.

    <Grid Margin="10,50,10,10">
        <xamlhost:WindowsXamlHost x:Name="myCalendar" InitialTypeName="Windows.UI.Xaml.Controls.CalendarView"
              Margin="10,10,10,10" Width="600" Height="300" ChildChanged="MyCalendar_ChildChanged" />
    </Grid>
    
  4. Сохраните MainWindow.xaml и откройте MainWindow.xaml.cs.

  5. Удалите следующую строку кода, добавленную в предыдущем разделе: myInkCanvas.InkPresenter.InputDeviceTypes = CoreInputDeviceTypes.Mouse | CoreInputDeviceTypes.Pen;.

  6. Добавьте следующую директиву пространства имен в начало файла:

    using Microsoft.Toolkit.Wpf.UI.XamlHost;
    
  7. Добавьте приведенный ниже метод обработчика событий ChildChanged в класс MainWindow. После преобразования размещенного элемента управления для просмотра этот обработчик событий запускается и создает простой обработчик событий для события SelectedDatesChanged элемента управления "Календарь".

    private void MyCalendar_ChildChanged(object sender, EventArgs e)
    {
        WindowsXamlHost windowsXamlHost = (WindowsXamlHost)sender;
    
        var 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());
                }
            };
        }
    }
    
  8. Сохраните, выполните сборку и запустите. Убедитесь, что в окне отображается элемент управления "Календарь", и при выборе даты отображается окно сообщения.

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

При необходимости вы можете упаковать приложение WPF в пакет MSIX для развертывания. MSIX — это современная и надежная технология упаковки приложений для Windows.

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

Примечание.

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

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

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

    Примечание.

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

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

    1. В обозревателе решений щелкните правой кнопкой мыши узел решения (не узел проекта) и выберите Свойства.
    2. Выберите Свойства конфигурации слева.
    3. Нажмите кнопку Диспетчер конфигураций....
    4. Убедитесь, что все перечисленные проекты имеют одно и то же значение в разделе Platform: x86 или x64.
  4. Щелкните правой кнопкой мыши узел проекта в только что добавленном проекте упаковки и выберите пункт Назначить в качестве автозагружаемого проекта.

  5. Выполните сборку и запустите проект упаковки. Убедитесь, что приложение WPF выполняется и элементы управления UWP отображаются надлежащим образом.

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