使用 Uno Islands 在現有 WPF 裡面嵌入 Uno 框架

来源:https://www.cnblogs.com/lindexi/archive/2022/09/29/16734405.html
-Advertisement-
Play Games

[演算法2-數組與字元串的查找與匹配] (.NET源碼學習) 關鍵詞:1. 數組查找(演算法) 2. 字元串查找(演算法) 3. C#中的String(源碼) 4. 特性Attribute 與內在屬性(源碼) 5. 字元串的比較(底層原理) 6. C#中的StringComparsion(源碼) 7. 字 ...


隨著 2022 9 月份 Uno 發佈了 4.5 版本,現有的 WPF 應用多了一個新的開發模式,那就是通過 Uno Islands 技術,在現有的 WPF 應用裡面嵌入 Uno 應用。通過此方式可以輔助在現有的 WPF 項目裡面,部分功能遷入 Uno 項目,或者是某些新開發功能通過 Uno 實現,從而利用 Uno 跨平臺的能力,逐個功能點支持跨平臺功能。逐個小功能接入的方式,讓開發者不需要為一次性遷移一個龐大的項目而煩惱

本文將嘗試寫一個非常簡單的例子用來嘗試在一個空的 WPF 項目上,接入 Uno Islands 技術,核心代碼完全來自 Uno 官方,詳細請看 Uno Islands 官方文檔

在開始之前,先介紹一下 Uno 項目是什麼。這是一個支持用 C#+XAML 實現跨平臺的 UI 框架,直接對標就是 MAUI 框架。只是 UNO 的主力開發不是微軟官方,而是第三方開發者,而且還是特別特別捲的第三方開發者,總體開發進度預計是 MAUI 的 5-10 倍。在 MAUI 還沒正式發佈,還在進入預覽版的時候,這時 UNO 早已發佈商業可用版本。在 MAUI 還在打磨的時候,這時 UNO 開始不斷發佈各種新迭代功能了。說不定後續 UNO 還有被某軟收購的可能

總的來說,我認為 UNO 還是比較能打的。而且更加有趣的是 UNO 和 MAUI 之間不是打架的關係,很多開發者都在這兩個框架之間跑動。同樣的 bug 要修兩次,那才有趣

至於好不好用,我推薦大家試試看咯

回到主題,在今年 9 月份新加入的 Uno Islands 技術,讓我開始準備在實際的大應用上部分功能接入 Uno 框架。通過 Uno Islands 技術,可以在 WPF 裡面劃某個矩形範圍,讓這個範圍內的內容使用 Uno 框架進行繪製和交互。為了方便演示,接下來新建一個空白的 WPF 項目,在這個空白的 WPF 項目裡面,在主視窗同時放一個 WPF 的控制項和一個用來承載 Uno 框架的 UnoXamlHost 控制項,以及新建一個共用項目,在共用項目裡面存放 Uno 框架所需的代碼和編寫簡單的 UI 界面

新建一個空白的 WPF 項目,採用 dotnet 6 框架,編輯 csproj 項目文件,加上必要的引用

  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net6.0-windows</TargetFramework>
    <Nullable>enable</Nullable>
    <UseWPF>true</UseWPF>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="5.0.0" />
    <PackageReference Include="Uno.WinUI.Skia.Wpf" Version="4.5.9" />
    <PackageReference Include="Uno.WinUI.RemoteControl" Version="4.5.0-dev.453" Condition="'$(Configuration)'=='Debug'" />
    <PackageReference Include="Uno.UI.Adapter.Microsoft.Extensions.Logging" Version="4.5.0-dev.453" />
    <PackageReference Include="Uno.WinUI.XamlHost" Version="4.5.0-dev.453" />
    <PackageReference Include="Uno.WinUI.XamlHost.Skia.Wpf" Version="4.5.0-dev.453" />
  </ItemGroup>

接著新建一個叫 TestUnoIslands 的共用項目,這個共用項目裡面的文件內容和代碼,推薦是從我的測試代碼裡面抄襲: https://github.com/lindexi/lindexi_gd/tree/7ddbfed126c37ec07d5d0d94468f5d0551e122f9/TestUnoIslands/TestUnoIslands

從我的測試代碼倉庫裡面拷貝代碼文件的方式可以快速拷貝出一個使用 Uno 框架的項目,這些代碼邏輯和官方的例子 代碼接近相同。從官方代碼倉庫裡面拷貝例子也不錯: https://github.com/unoplatform/Uno.Samples/tree/master/UI/UnoIslandsSampleApp/UnoIslandsSampleApp.Shared

這裡的共用項目可以認為是一個現有的使用 Uno 框架的項目,接下來就是在剛纔創建的 WPF 項目裡面,嵌入這個 Uno 項目的內容

在剛纔新建的 WPF 項目裡面,添加共用項目的引用,引用剛纔創建的共用項目,接著為瞭解決 Uno 的字體問題,在 WPF 項目裡面添加 uno-fluentui-assets.ttf 字體,這個字體文件可以從 github 這裡下載: https://github.com/lindexi/lindexi_gd/blob/7ddbfed126c37ec07d5d0d94468f5d0551e122f9/TestUnoIslands/TestUnoIslands.Wpf/Assets/Fonts/uno-fluentui-assets.ttf

添加的 ttf 字體文件放入到 Assets\Fonts 文件夾內,同時編輯 WPF 項目的 csproj 文件,添加這個 ttf 文件的引用

  <ItemGroup>
    <Content Include="Assets\Fonts\uno-fluentui-assets.ttf" />
  </ItemGroup>

再編輯 WPF 項目的 csproj 文件,設置對共用項目里的 XAML 文件的引用

  <ItemGroup>
    <UpToDateCheckInput Include="..\TestUnoIslands\**\*.xaml" />
  </ItemGroup>

編輯完成之後的 csproj 項目文件的內容如下

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

  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net6.0-windows</TargetFramework>
    <Nullable>enable</Nullable>
    <UseWPF>true</UseWPF>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="5.0.0" />
    <PackageReference Include="Uno.WinUI.Skia.Wpf" Version="4.5.9" />
    <PackageReference Include="Uno.WinUI.RemoteControl" Version="4.5.0-dev.453" Condition="'$(Configuration)'=='Debug'" />
    <PackageReference Include="Uno.UI.Adapter.Microsoft.Extensions.Logging" Version="4.5.0-dev.453" />
    <PackageReference Include="Uno.WinUI.XamlHost" Version="4.5.0-dev.453" />
    <PackageReference Include="Uno.WinUI.XamlHost.Skia.Wpf" Version="4.5.0-dev.453" />
  </ItemGroup>
  <ItemGroup>
    <UpToDateCheckInput Include="..\TestUnoIslands\**\*.xaml" />
  </ItemGroup>
  <ItemGroup>
    <Content Include="Assets\Fonts\uno-fluentui-assets.ttf" />
  </ItemGroup>
  <Import Project="..\TestUnoIslands\TestUnoIslands.projitems" Label="Shared" />

</Project>

接下來打開 WPF 項目的主視窗用來添加對 Uno 項目的引用。開始之前,在 XAML 加上命名空間

xmlns:xamlHost="clr-namespace:Uno.UI.XamlHost.Skia.Wpf;assembly=Uno.UI.XamlHost.Skia.Wpf"

這是一句話的命名空間引用,官方的文檔裡面為了格式化,在文檔裡面換了行

通過添加 Uno Island 即可進行對 Uno 項目的嵌入,添加的代碼如下

<xamlHost:UnoXamlHost InitialTypeName="UnoIslandsSampleApp.MainPage" />

使用上和 WinUI 提供的 Xaml Island 幾乎相同。如此即可完成嵌入

完全的 XAML 代碼如下

<Window x:Class="TestUnoIslands.Wpf.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:TestUnoIslands.Wpf"
        mc:Ignorable="d"
        xmlns:xamlHost="clr-namespace:Uno.UI.XamlHost.Skia.Wpf;assembly=Uno.UI.XamlHost.Skia.Wpf"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Grid Margin="20">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="*" />
            </Grid.RowDefinitions>
            <Button x:Name="Button" Click="Button_OnClick">Hello from WPF!</Button>
            <xamlHost:UnoXamlHost Grid.Row="1" 
                                  InitialTypeName="UnoIslandsSampleApp.MainPage" />
        </Grid>
    </Grid>
</Window>

嘗試運行項目,可以看到在一個 WPF 項目裡面嵌入了 Uno 的頁面

依然的,這個 Uno Islands 技術存在和 WinFormsHost 技術相同的問題,在此矩形範圍內,只允許一個 UI 框架工作。被嵌入 Uno 的範圍內,不能再次疊加上 WPF 的控制項。但我認為這個問題其實也不大,說不定我想不開,或者是某位大佬行行好,就幫他實現了一個可以作為元素插入的功能哈

本文的代碼放在githubgitee 歡迎訪問

可以通過如下方式獲取本文的源代碼,先創建一個空文件夾,接著使用命令行 cd 命令進入此空文件夾,在命令行裡面輸入以下代碼,即可獲取到本文的代碼

git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin 7ddbfed126c37ec07d5d0d94468f5d0551e122f9

以上使用的是 gitee 的源,如果 gitee 不能訪問,請替換為 github 的源。請在命令行繼續輸入以下代碼

git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git
git pull origin 7ddbfed126c37ec07d5d0d94468f5d0551e122f9

獲取代碼之後,進入 TestUnoIslands 文件夾

博客園博客只做備份,博客發佈就不再更新,如果想看最新博客,請到 https://blog.lindexi.com/

知識共用許可協議
本作品採用知識共用署名-非商業性使用-相同方式共用 4.0 國際許可協議進行許可。歡迎轉載、使用、重新發佈,但務必保留文章署名[林德熙](http://blog.csdn.net/lindexi_gd)(包含鏈接:http://blog.csdn.net/lindexi_gd ),不得用於商業目的,基於本文修改後的作品務必以相同的許可發佈。如有任何疑問,請與我[聯繫](mailto:[email protected])。
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Python常用的英語單詞就那麼幾個,多打就熟悉了 說來好笑,我壓根就沒記英語單詞… 真的就是純靠多打多練, 畢竟打多了之後肌肉記憶就在那裡了 下麵就給大家帶來常用python清單彙總~ 一、互動式環境與print輸出(https://jq.qq.com/?_wv=1027&k=2Q3YTfym) ...
  • 一、線程的概念線程是CPU分配資源的基本單位。當一程式開始運行,這個程式就變成了一個進程,而一個進程相當於一個或者多個線程。當沒有多線程編程時,一個進程相當於一個主線程;當有多線程編程時,一個進程包含多個線程(含主線程)。使用線程可以實現程式大的開發。 多個線程可以在同一個程式中運行,並且每一個線程 ...
  • 一、整型數據類型 1、整型數據類型名稱及關鍵詞 2、為什麼要定義不同的整型類型? 因為不同的數據類型所占用的記憶體大小是不同的,他們可表示的數據範圍也是不同的。那麼char,short,int,long,long long,分別占用幾個位元組?具體的數值範圍又是多少?C語言並未規定數據類型的大小範圍,具 ...
  • 在上一篇文章`《驅動開發:內核字元串轉換方法》`中簡單介紹了內核是如何使用字元串以及字元串之間的轉換方法,本章將繼續探索字元串的拷貝與比較,與應用層不同內核字元串拷貝與比較也需要使用內核專用的API函數,字元串的拷貝往往伴隨有內核記憶體分配,我們將首先簡單介紹內核如何分配堆空間,然後再以此為契機簡介字... ...
  • 一、什麼是AOP AOP為Aspect Oriented Programming的縮寫,意為:面向切麵編程,通過預編譯方式和運行期間動態代理實現程式功能的統一維護的一種技術。AOP是OOP的延續,是軟體開發中的一個熱點,也是Spring框架中的一個重要內容,是函數式編程的一種衍生範型。利用AOP可以 ...
  • 我們可以通過使用Win32Api來製作一些強大的功能,本文將通過示例代碼來介紹使用Win32Api來之做桌面視窗停靠功能; 效果圖: 一.通過Nuget 引入 Vanara.PInvoke.Shell32 和 PInvoke.User32 這兩個庫。 二.功能列表 1.Berth 函數,將視窗停靠在 ...
  • 分散式唯一ID,顧名思義,是指在全世界任何一臺電腦上都不會重覆的唯一Id。 在單機/單伺服器/單資料庫的小型應用中,不需要用到這類東西。但在高併發、海量數據、大型分散式應用中,這類卻是構建整個系統的最核心一環。 設想一下如下場景: 在某個大型電商系統A中,“訂單”這類大數據(比如,每天產生1500 ...
  • ALglib 是一個跨平臺的數值分析和數據處理庫。它支持多種編程語言(C + + 、 C # 、 Delphi)和多種操作系統(Windows 和 POSIX,包括 Linux)。 ALglib 功能包括: 數據分析(分類/回歸,統計學) 優化和非線性解法 插值和線性/非線性最小二乘擬合 線性代數( ...
一周排行
    -Advertisement-
    Play Games
  • 前言 當別人做大數據用Java、Python的時候,我使用.NET做大數據、數據挖掘,這確實是值得一說的事。 寫的並不全面,但都是實際工作中的內容。 .NET在大數據項目中,可以做什麼? 寫腳本(使用控制台程式+頂級語句) 寫工具(使用Winform) 寫介面、寫服務 使用C#寫代碼的優點是什麼? ...
  • 前言 本文寫給想學C#的朋友,目的是以儘快的速度入門 C#好學嗎? 對於這個問題,我以前的回答是:好學!但仔細想想,不是這麼回事,對於新手來說,C#沒有那麼好學。 反而學Java還要容易一些,學Java Web就行了,就是SpringBoot那一套。 但是C#方向比較多,你是學控制台程式、WebAP ...
  • 某一日晚上上線,測試同學在回歸項目黃金流程時,有一個工單項目介面報JSF序列化錯誤,馬上升級對應的client包版本,編譯部署後錯誤消失。 線上問題是解決了,但是作為程式員要瞭解問題發生的原因和本質。但這都是為什麼呢? ...
  • 本文介紹基於Python語言中TensorFlow的Keras介面,實現深度神經網路回歸的方法。 1 寫在前面 前期一篇文章Python TensorFlow深度學習回歸代碼:DNNRegressor詳細介紹了基於TensorFlow tf.estimator介面的深度學習網路;而在TensorFl ...
  • 前段時間因業務需要完成了一個工作流組件的編碼工作。藉著這個機會跟大家分享一下整個創作過程,希望大家喜歡,組件暫且命名為"easyFlowable"。 接下來的文章我將從什麼是工作流、為什麼要自研這個工作流組件、架構設計三個維度跟大家來做個整體介紹。 ...
  • 1 簡介 我們之前使用了dapr的本地托管模式,但在生產中我們一般使用Kubernetes托管,本文介紹如何在GKE(GCP Kubernetes)安裝dapr。 相關文章: dapr本地托管的服務調用體驗與Java SDK的Spring Boot整合 dapr入門與本地托管模式嘗試 2 安裝GKE ...
  • 摘要:在jvm中有很多的參數可以進行設置,這樣可以讓jvm在各種環境中都能夠高效的運行。絕大部分的參數保持預設即可。 本文分享自華為雲社區《為什麼需要對jvm進行優化,jvm運行參數之標準參數》,作者:共飲一杯無。 我們為什麼要對jvm做優化? 在本地開發環境中我們很少會遇到需要對jvm進行優化的需 ...
  • 背景 我們的業務共使用11台(阿裡雲)伺服器,使用SpringcloudAlibaba構建微服務集群,共計60個微服務,全部註冊在同一個Nacos集群 流量轉發路徑: nginx->spring-gateway->業務微服務 使用的版本如下: spring-boot.version:2.2.5.RE ...
  • 基於php+webuploader的大文件分片上傳,帶進度條,支持斷點續傳(刷新、關閉頁面、重新上傳、網路中斷等情況)。文件上傳前先檢測該文件是否已上傳,如果已上傳提示“文件已存在”,如果未上傳則直接上傳。視頻上傳時會根據設定的參數(分片大小、分片數量)進行上傳,上傳過程中會在目標文件夾中生成一個臨 ...
  • 基於php大文件分片上傳至七牛雲,使用的是七牛雲js-sdk V2版本,引入js文件,配置簡單,可以暫停,暫停後支持斷點續傳(刷新、關閉頁面、重新上傳、網路中斷等情況),可以配置分片大小和分片數量,官方文檔https://developer.qiniu.com/kodo/6889/javascrip ...