Posted on 16. November 2018

XAML Islands – Глубокое погружение – Часть 2

Добро пожаловать во 2-ю часть изучения XAML Islands. Данная тема была затронута в первом блог посте: как работает инфраструктура XAML Islands и как ее использовать, а также то, как Вы можете использовать привязку в элементах управления Island.

Во второй части кратко рассматривается, как использовать обертку NuGet пакетов и как размещать Ваши собственные элементы управления в Win32 приложениях.

Пакеты

Создание пользовательских пакетов для UWP элементов управления может быть трудоемкой задачей, и Вы, вероятно, не захотите с этим работать. Для простых вещей, таких как кнопки, этот процесс может быть достаточно легким, но разработка более сложных элементов управления может занять довольно много времени. Чтобы упростить Вам задачу, были сформированы некоторые из самых востребованных элементов управления! Текущая итерация предоставляет вам InkCanvas, InkToolbar, MapControl и MediaPlayerElement. Теперь, если Ваше WPF приложение работает под управлением Windows 10, Вы можете использовать простой и удобный UWP InkCanvas с InkToolbar панелью внутри Вашего WPF или WinForms приложения! Вы даже можете применять InkRecognizer для обнаружения фигур, букв и цифр на основе штрихов InkCanvas.

Сколько кода требуется для интеграции с InkCanvas? Совсем немного!

 

 

    
<Window
...
xmlns:uwpControls="clr-namespace:Microsoft.Toolkit.Wpf.UI.Controls;assembly=Microsoft.Toolkit.Wpf.UI.Controls">
 
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"></RowDefinition>
        <RowDefinition Height="*"><RowDefinition>
    </Grid.RowDefinitions>
    <uwpControls:InkToolbar TargetInkCanvas="{x:Reference Name=inkCanvas}"></uwpControls:InkToolbar>
    <uwpControls:InkCanvas Grid.Row="1" x:Name="inkCanvas"></uwpControls:InkCanvas>
</Grid>
   </Window>
    
    
    

 

В основном это просто Grid определение, поэтому были добавлены всего две строки кода. И это может предоставить вашим пользователям удивительный опыт, который обеспечивается XAML Islands и новыми UWP элементами управления.

Пользовательский контроль – Управляемый код

Все, о чем говорилось ранее, относится к элементам управления платформы. Но что, если Вы захотите упаковать Ваш собственный пользовательский UWP UserControl и загрузить его с помощью WindowsXamlHost? Будет ли это работать? Да! Когда XAML элементы управления создаются в контексте острова, то ресурсы обрабатываются рационально, а это означает, что ms-appx протокол просто работает, даже если Вы не запускаете Win32 процесс внутри упакованного APPX пакета. Корень ms-appx протокола отобразит его ход к исполняемому Вами пути.

На данный момент Вы не можете просто создать UWP библиотеку и ссылаться на нее в своем WPF или WinForms проекте, поэтому весь процесс использования настраиваемого элемента управления выполняется вручную. Когда Вы разрабатываете UWP приложение (например, C#), Вы компилируете, используя разновидность UWP .NET Core Framework, а не .NET Full Framework. Чтобы Ваш пользовательский элемент управления работал в WPF или WinForms приложении, основанном на .NET Full Framework, необходимо перекомпилировать артефакты UWP библиотеки с помощью набора инструментов .NET Full Framework, скопировав их в Ваш WPF / WinForms проект. Здесь Вы найдете документацию, посвященную данному вопросу, которая описывает все необходимые шаги. Помните, что Ваш WPF / WinForms проект по умолчанию не предназначен для какой-либо конкретной Windows 10 версии, поэтому Вам нужно вручную добавить ссылки на некоторые WinMD и DLL файлы. Информацию об этом Вы можете найти в разделе «Расширение Вашего настольного приложения для Windows 10», в котором описано, как использовать Windows 10 API-интерфейсы в Desktop Bridge Win32 приложении. Ссылаясь на WinMD и DLL, Вы также сможете создавать артефакты этой компиляции из UWP библиотеки в WPF / WinForms проекте (.NET Full Framework).

ПРИМЕЧАНИЕ. Существует совершенно другой процесс для нативного кода (C ++ / WinRT), подробности которого будут рассмотрены в другой статье.

Вы также не можете создавать эти артефакты, какими они есть. Вы должны сообщить системе, что нужно отключить отображение информации о типе и x:Bind диагностику. Это связано с тем, что сгенерированный код не будет совместим с .NET Framework. Его можно сделать рабочим, добавив следующие свойства в Ваш проект UWP библиотеки:

 

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

 

Вы можете просто вручную скопировать необходимые файлы в WPF / WinForms проект, но тогда у вас будет несколько его копий. После сборки процесс можно автоматизировать следующим образом, согласно этой документации. Однако, если Вы попытаетесь таким образом упаковать Ваше приложение в APPX пакет, это не сработает, т.к. файлы не будут скопированы. С целью улучшения процесса был создан специальный MSBuild фрагмент. Преимущество Microsoft Build фрагмента заключается в том, что он добавляет CSharp файлы, а также результаты компиляции из библиотеки, в нужное место. Все, что вам нужно сделать, – это скопировать этот скрипт.

ПРИМЕЧАНИЕ. Имейте в виду, что данный фрагмент будет в будущем обрабатываться с помощью Visual Studio, поэтому Вам придется удалять любое решение каждый раз, когда это это будет происходить.

 

 
<PropertyGroup>
  <IslandPath Condition="$(IslandPath) == ''">..\$(IslandLibrary)</IslandPath>
  <IslandDirectoryName>$([System.IO.Path]::GetFileName($(IslandPath.TrimEnd('\'))))</IslandDirectoryName>
</PropertyGroup>
<ItemGroup>
  <IslandLibraryCompile Include="$(IslandPath)\**\*.xaml.cs;$(IslandPath)\obj\$(Configuration)\**\*.g.cs;$(IslandPath)\obj\$(Configuration)\**\*.g.i.cs"></IsandLibraryCompile>
</ItemGroup>
<ItemGroup>
  <Compile Include="@(IslandLibraryCompile)">
    <LinkBase>$(IslandDirectoryName)\%(RecursiveDir)</LinkBase>
  </Compile>
</ItemGroup>
<ItemGroup>
  <IslandLibraryContent Include="$(IslandPath)\**\*.*" Exclude="$(IslandPath)\**\*.user;$(IslandPath)\**\*.csproj;$(IslandPath)\**\*.cs;$(IslandPath)\**\*.xaml;$(IslandPath)\**\obj\**;$(IslandPath)\**\bin\**"/>
  <IslandLibraryContent Include="$(IslandPath)\obj\$(Configuration)\**\*.xbf"/>
</ItemGroup>
<ItemGroup>
  <None Include="@(IslandLibraryContent)">
    <Link>$(IslandDirectoryName)\%(RecursiveDir)\%(Filename)%(Extension)</Link>
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  </None>
</ItemGroup>

Этот Microsoft Build фрагмент копирует файлы, основываясь на пути к IslandLibrary свойству, в проект, в котором он находится. IslandLibraryCompile компонент включает в себя:

  • Все .xaml.cs файлы, которые позволят Вам повторно использовать код вне Ваших пользовательских элементов управления.
  • Все сгенерированные .g.i.cs и .g.cs файлы. Все данные под префиксом «x:» на самом деле являются сгенерированным кодом, и именно в этом случае данный сгенерированный код и собирается. Таким образом, файлы являются частичными классами, которые на самом деле содержат поля всех x: имен внутри соответствующих им XAML файлов, а также они содержат код для соединения этих полей с их фактическими примерами. Они также ссылаются на .XAML файл, который будет загружаться при вызове InitializeComponentmethod метода, обычно в начале конструктора элемента управления. IslandLibraryContent контент включает в себя:
  • Все файлы содержимого Вашего проекта. Копируются все файлы, необходимые для запуска Вашего проекта, такие как PNG, JPG и т. д. Он скопирует их в нужные папки, такие как ms-appx:///will “just work”™. Есть другие способы сделать это, но именно этот вариант покроет основные потребности наиболее распространенных сценариев.
  • Все сгенерированные .xbf. XBF файлы расшифровываются как двоичный XAML формат, и это скомпилированная версия ваших .xaml файлов, они загружаются намного быстрее, чем XAML файлы (например, без синтаксического анализа XML). Даже если .g.i.cs файлы могут выглядеть так, как будто они пытаются загрузить .xaml файлы, для повышения производительности XAML инфраструктура всегда пытается сначала загрузить .XBF файлы. Только если она не сможет их найти, то попытается загрузить .xaml файлы. Этот MSBuild скрипт не копирует .xaml файлы, поскольку они не дают никаких преимуществ по сравнению с .XBF.
Чтобы обеспечить оптимальный опыт взаимодействия с разработчиками, необходимо также добавить зависимость проекта уровня решения от WPF / WinForms проекта к UWPLibrary проекту. Это означает, что каждый раз, когда Вы изменяете какой-либо из файлов UWP библиотеки, Вы можете просто создать WPF / WinForms проект, и новейшие артефакты будут находиться уже в правильном порядке компиляции проекта. Все эти шаги исчезнут в будущей версии Visual Studio, когда инструменты будут обновлены. Эти шаги описаны здесь.

С включенными в инфраструктуру сборки проекта файлами  и с добавленной зависимостью сборки, Ваш WindowsXamlHost должен работать нормально. При условии, что Вы установите полное имя Вашего пользовательского элемента управления для InitialTypeName. Вы можете ознакомиться с примером проекта здесь.

С помощью MSBuild фрагмента должны функционировать даже Ваши приложения, упакованные с помощью шаблона «Проект упаковки Windows приложений». Более детальную информацию Вы можете прочесть в этой статье

Ограничения в Октябре 2018

Этот выпуск находится на рассмотрении, поэтому код, который Вы видите здесь, не является готовым к использованию. Например:
  • Wrapped Controls правильно реагирует на изменения в DPI и масштабе.
  • Инструменты доступности, которые легко работают с приложением и размещенными элементами управления.
  • Inline Inking, @Places и @People для элементов управления вводa.
Для полного ознакомления, ознакомьтесь с документами.
Что дальше?

Только что выпущенная версия не является окончательной стабильной версией. Команда Microsoft все еще активно работает над улучшением XAML Islands. Поработайте с продуктом и оставьте отзыв в разделе User Voice или по адресу XamlIslandsFeedback@microsoft.com, но в настоящее время Microsoft не рекомендует его для производственного использования.

Источник



Exception: Object reference not set to an instance of an object.
Comments are closed