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 裡面有使用到! 請看一下圖片
參考自 ( 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 的新技術拉~