Windows 10 UWP 40 of N: XAML Island 讓Win32可以加入 UWP XAML Control的混合操作! Part 2

  • 552
  • 0
  • UAP
  • 2021-04-30

XAML Island 掛載 UWP Control的技術!讓傳統桌上型程式也能使用 UWP 控制項~ 更加配合系統Style

接續

 呈上篇說到關於 Xaml island 以及對於 WinUI 的部分來說明一下一些相關資訊。

如果要動態產生 Xaml island 的部分只需要用以下的Sample就可以!

private void CreateXamlIslandControl()
		{
			Windows.UI.Xaml.Hosting.WindowsXamlManager.InitializeForCurrentThread();
			var targetType = typeof(Windows.UI.Xaml.Controls.Button);
			var instance = Microsoft.Toolkit.Win32.UI.XamlHost.UWPTypeFactory.CreateXamlContentByType(targetType.FullName);
			if (instance is Windows.UI.Xaml.Controls.Button btn)
			{
				btn.Content = "Im the UWP Button";
				var binding = new Windows.UI.Xaml.Data.Binding()
				{
					Path = new Windows.UI.Xaml.PropertyPath("ExecuteButton"),
					Mode = Windows.UI.Xaml.Data.BindingMode.OneWay,
					Source = DataContext
				};
				btn.SetBinding(Windows.UI.Xaml.Controls.Button.CommandProperty, binding);
				var hostControl = new Microsoft.Toolkit.Wpf.UI.XamlHost.WindowsXamlHost();
				hostControl.Child = btn;
				LayoutRoot.Children.Add(hostControl);
				Grid.SetRow(hostControl, 1);
				Grid.SetColumn(hostControl, 1);
			}
		}

透過 UWPTypeFactory 就可以產生出UWP Control! 當然還是需要 WindowsXamlHost來做為載體才能放在其他Win32的UI框架上。

而如果先產生 WindowsXamlHost 再產生UWP的控制項的話就可以調整成一下程式碼

private void CreateXamlIslandControl1()
		{
			var hostControl = new Microsoft.Toolkit.Wpf.UI.XamlHost.WindowsXamlHost();
			var targetType = typeof(Windows.UI.Xaml.Controls.Button);
			var instance = Microsoft.Toolkit.Win32.UI.XamlHost.UWPTypeFactory.CreateXamlContentByType(targetType.FullName);
			if (instance is Windows.UI.Xaml.Controls.Button btn)
			{
				btn.Content = "Im the UWP Button";
				var binding = new Windows.UI.Xaml.Data.Binding()
				{
					Path = new Windows.UI.Xaml.PropertyPath("ExecuteButton"),
					Mode = Windows.UI.Xaml.Data.BindingMode.OneWay,
					Source = DataContext
				};
				btn.SetBinding(Windows.UI.Xaml.Controls.Button.CommandProperty, binding);
				hostControl.Child = btn;
				LayoutRoot.Children.Add(hostControl);
				Grid.SetRow(hostControl, 1);
				Grid.SetColumn(hostControl, 1);
			}
		}

執行畫面如下

這邊可以看到一個是直接使用 XAML做初始化,另外一個是用WPF的Click去產生另外一個 UWP 的 button

 

後記

今年年初有個線上的會議( .NET Conf : Focus on Windows ) 大家可以進去補充一下相關資訊,裡面提及了很多正在實作的Project!以及很多已經可以玩得玩具。 後期由於社群的努力讓 WinUI 出現讓很多第三方的控制項可以進到 WinUI 而在WinUI 2.0的時候正好跟著 Xaml island 讓傳統的桌面應用程式也能夠支援 UWP 的 Control。然後再到 WinUI 3.0 就是準備要把對於 WinUI 2.X 的版本是相依在 UWP 的部分進行抽離,最重要的部分就是把 Windows.Xaml.UI 的命名空間變成 Microsoft.Xaml.UI 依此類推... 

對於XAML Island 目前 在 WinUI 2.5 裡面有使用到! 請看一下圖片

WinUI 2.x platform support

參考自 ( https://docs.microsoft.com/en-us/windows/apps/winui/ )

但是到了 WinUI 3.0 將不在使用 Xaml Island 因為已經把 UWP 那些控制像拆解出來不在相依UWP。 

關於 WinUI 的部分可以參考官方連結

 

2020 11 月的時候微軟發布了 .NET 5 算是把 Mono, .NET Framework, .NET Core 整併起來的第一步! 讓我們來試看看 .NET 5 配合 Xaml island ,基本上只需要加入TFM ( TargetFramework ) 就可以針對多目標進行編譯!

<Project Sdk="Microsoft.NET.Sdk">

	<PropertyGroup>
		<TargetFrameworks>net5.0-windows10.0.18362.0;netcoreapp3.1</TargetFrameworks>
		<LangVersion>latest</LangVersion>
		<UseWPF>true</UseWPF>
		<!--<UseWinForms>true</UseWinForms>-->
		<OutputType>WinExe</OutputType>
	</PropertyGroup>

	<Choose>
		<When Condition=" '$(TargetFramework)' == 'netcoreapp3.1' ">
			<ItemGroup>
				<PackageReference Include="Microsoft.Windows.Sdk.Contracts" Version="10.0.18362.2005" />
			</ItemGroup>
			<PropertyGroup >
				<ApplicationManifest>app.manifest</ApplicationManifest>
			</PropertyGroup>
		</When>
		<When Condition=" $(TargetFramework.StartsWith('net5.0-windows10')) ">
			<ItemGroup>
				<PackageReference Include="Microsoft.Windows.CsWinRT" Version="1.1.3" />
			</ItemGroup>
		</When>
	</Choose>

	<ItemGroup>
		<PackageReference Include="Microsoft.Toolkit.Wpf.UI.Controls" Version="6.1.2" />
		<PackageReference Include="Microsoft.Toolkit.Wpf.UI.XamlHost" Version="6.1.2" />
	</ItemGroup>

</Project>

但是..... 出現了不少的錯誤! 經過爬了一下 Github 發現在這篇 ( Microsoft.Toolkit.Wpf.UI.Controls incompatible with .Net 5.0 · Issue #296 · windows-toolkit/Microsoft.Toolkit.Win32 · GitHub

看來目前 .NET 5 對於 WinRT projections 沒有支援,所以要等到 WinUI 3 了,這樣就可以脫鉤 Xaml island。 

 

XAML island 相關限制可以參考此連結 ( Host WinRT XAML controls in desktop apps - Windows applications | Microsoft Docs

 

***以上Code以及說明都有可能隨著Windows 10 的版本以及Visual Studio 版本有所調整!***

參考資料 Microsoft Docs,Windows Blogs for developer

下次再分享Windows 10 的新技術拉~