[WPF]淺析資源引用(pack URI)

来源:https://www.cnblogs.com/czwy/archive/2023/11/07/17815776.html
-Advertisement-
Play Games

一:背景 1. 講故事 這段時間分析了幾個和網路故障有關的.NET程式之後,真的越來越體會到電腦基礎課的重要,比如 電腦網路 課,如果沒有對 tcpip協議 的深刻理解,解決這些問題真的很難,因為你只能在高層做黑盒測試,你無法看到 tcp 層面的握手和psh通訊。 這篇我們通過兩個小例子來理解一 ...


WPF中我們引用資源時常常提到一個概念:pack URI,這是WPF標識和引用資源最常見的方式,但不是唯一的方式。本文將介紹WPF中引用資源的幾種方式,並回顧一下pack URI標識引用在不同位置的資源文件的寫法。

WPF中引用資源的幾種方式

WPF中使用URI標識和載入位於各種位置的文件,包括當前程式集資源文件、其他程式集資源文件、本地磁碟文件、網路共用文件、web站點文件。

程式集資源文件

程式集資源文件是最常見的一種情況。這裡程式集資源指的是資源文件屬性的生成操作(Build Action)為Resource的文件,而非嵌入的資源(Emmbedded Resource)。程式集中的資源文件通常使用相對URI來引用,例如:

<ImageBrush x:Key="imgbrush" ImageSource="images/111.jpg"/>   //本地程式集中資源引用的寫法
<ImageBrush x:Key="imgbrush" ImageSource="/ResourceDll;component/images/111.jpg"/>   //引用的程式集中資源引用的寫法

也可以使用絕對Pack URI語法,例如

<ImageBrush x:Key="imgbrush" ImageSource="pack://application:,,,/images/111.jpg"/>     //本地程式集中資源引用的寫法
<ImageBrush x:Key="imgbrush" ImageSource="pack://application:,,,/ResourceDll;component/images/111.jpg"/>   //引用的程式集中資源引用的寫法

本地磁碟文件

直接引用本地磁碟文件的方式不常見。這種方式引用本地文件會占用文件,本地文件無法修改或者刪除,因此不推薦此方式。這裡只是舉例講解。

<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夾\\123.jpg"/> 

網路共用文件

網路共用文件和本地磁碟文件類似,會占用文件。可以使用UNC或者URI的方式引用。

<ImageBrush x:Key="imgbrush" ImageSource="\\192.168.0.1\tmp\新建文件夾\123.jpg"/>    UNC方式引用
<ImageBrush x:Key="imgbrush" ImageSource="file://192.168.0.1\tmp\新建文件夾\123.jpg"/>    URI方式引用

web站點文件

少數場景下會在WPF中使用web站點資源,比如用戶頭像。web站點資源主要以http/https協議的url載入,url作為URI的子集,因此可以直接引用。實際開發中不建議直接引用url,因為請求網路資源需要時間,這可能導致UI短暫卡頓。建議開啟線程把網路資源讀到記憶體中使用。

<ImageBrush x:Key="imgbrush" ImageSource="https://pic.cnblogs.com/default-avatar.png"/>

上述示例中都是在XAML中聲明式的語法引用資源,本質還是使用Uri類,因此在後臺代碼中使用Uri類就行。

// 絕對URI (預設)
Uri absoluteUri = new Uri("pack://application:,,,/images/111.jpg", UriKind.Absolute);
// 相對URI
Uri relativeUri = new Uri("images/111.jpg", UriKind.Relative);

Pack URI方案

pack URI的語法看起來很奇怪,它是來自開放式打包約定 (OPC)規範中XPS(XML Paper Specification)標準,有使用openxml解析Word/PPT文件經驗的朋友可能熟悉這個規範。OPC 規範利用RFC 2396(統一資源標識符 (URI):一般語法)的擴展性來定義pack URI方案。

URI所指定的方案(schemes)由其首碼定義;httpftptelnetfile 是比較常見的協議方案(schemes)。pack URI使用“pack”作為它的方案(schemes),並且包含兩個組件:授權和路徑。 pack URI的格式為:pack://authority/path。authority指定包含部件的包的類型,而path 指定部件在包內的位置。前邊示例代碼中application:,,,就是授權(authority),/images/111.jpg或者/ResourceDll;component/images/111.jpg就是路徑(path)。這裡也可以理解為嵌套在方案(schemes)為pack://的uri中的uri。由於是嵌套在內部的uri,授權(authority)原本應是application:///中的斜杠轉義為逗號。路徑中必須對保留字元(如“%”和“?”)進行轉義。詳細信息可參閱開放式打包約定 (OPC)規範

標準的URI協議方案有30種左右,由隸屬於國際互聯網資源管理的非營利社團 ICANN(Internet Corporation for Assigned Names and Numbers,互聯網名稱與數字地址分配機構)的 IANA(Internet Assigned Numbers Authority,互聯網號碼分配局)管理頒佈。詳細協議方案參見:http://www.iana.org/assignments/uri-schemes

在WPF中,用程式(包)可以包含一個或多個文件(部件),包括:

  • 當前程式集內的資源文件
  • 引用的程式集內的資源文件
  • 內容文件
  • 源站點文件

為了訪問這些類型的文件,WPF 支持兩種授權:application:///siteoforigin:///。 application:/// 授權標識在編譯時已知的應用程式數據文件,包括資源文件和內容文件。 siteoforigin:/// 授權標識源站點文件。 下圖顯示了每種授權的範圍。

iamge

pack URI語法示例

前邊提到pack URI由授權和路徑組成,當前程式集、引用的程式集內的資源文件,以及內容文件的授權都是application:///,源站點文件的授權是siteoforigin:///(用於XAML瀏覽器應用程式)。

當前程式集資源文件

當前程式集資源文件的路徑是資源文件相對程式集項目文件夾根目錄的路徑。需要註意的是這裡所說的相對於程式集項目文件夾根目錄表達的是從哪裡開始作為根目錄進行定址,當使用pack://這樣絕對URI表示時,路徑應該用根目錄符號/開始。下圖中111.jpg位於項目的根目錄,它的pack URI就是:

pack://application:,,,/111.jpg

BlindsShader.ps位於子目錄中,它的pack URI就是:

pack://application:,,,/Shader/ShaderSource/BlindsShader.ps

image

引用程式集資源文件

當需要引用另一個程式集中的資源文件時,路徑需要指明程式集的名稱。路徑需符合以下的格式:

pack://application:,,,AssemblyShortName{;Version}{;PublicKey};component/ResourceName
  • AssemblyShortName是引用的程式集的短名稱,是必選項
  • Version是引用的程式集的版本。此部分在載入兩個或多個具有相同短名稱的引用程式集時使用,是可選項。
  • PublicKey是引用的程式集的簽名公鑰。此部分在載入兩個或多個具有相同短名稱的引用程式集時使用,是可選項。
  • component指定所引用的程式集是從本地程式集引用的,此處是固定寫法
  • ResourceName是資源文件的名稱,包括其相對於所引用程式集的項目文件夾根目錄的路徑。

內容文件

前邊提到的資源文件都是生成操作(Build Action)為Resource的文件,是會編譯到程式集中。內容文件是生成操作(Build Action)為內容(Content)的文件,並不會編譯到程式集中,通常是將文件屬性中複製到輸出目錄(CopyToOutputDirectory)選為始終複製(Always)或者如果較新則複製(PreserveNewest),將文件保存到程式運行目錄中。內容文件主要可以解決以下問題:

  • 改變資源文件時,需要重新編譯應用程式;
  • 資源文件比較大,導致編譯的程式集也比較大;
  • WPF聲音文類不支持程式集資源,無法從資源流中析取音頻文件並播放。

內容文件本質上也是本地磁碟文件,但生成項目時,會將 AssemblyAssociatedContentFileAttribute 屬性編譯到每個內容文件的程式集的元數據內,AssemblyAssociatedContentFileAttribute 的值表示內容文件相對於其在項目中的位置的路徑[^2],可以採用pack URI的方式載入。內容文件的路徑是其相對於應用程式的主可執行程式集的文件系統位置的路徑。其格式如下:

pack://application:,,,/ContentFile.wav

源站點文件

源站點文件主要針對XAML瀏覽器應用程式(XBAP)設計,編譯XAML瀏覽器應用程式(XBAP)將資源文件分離出程式集,減少文件大小,在需要請求下周源站點文件時,才下載它們到客戶端電腦[^2]。現在基本不適用該技術,本文不再詳細介紹,感興趣可以查看文末參考資料。

參考

[^1] https://learn.microsoft.com/zh-cn/dotnet/desktop/wpf/app-development/pack-uris-in-wpf?view=netframeworkdesktop-4.8
[^2] https://learn.microsoft.com/zh-cn/dotnet/desktop/wpf/app-development/wpf-application-resource-content-and-data-files?view=netframeworkdesktop-4.8


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 準備 我是小C同學編寫得一個java文件,如何實現我的功能呢?需要去JVM(Java Virtual Machine)這個地方旅行。 變身 我高高興興的來到JVM,想要開始JVM之旅,它確說:“現在的我還不能進去,需要做一次轉換,生成class文件才行”。為什麼這樣呢? JVM不能直接載入java文 ...
  • 配置文件yml # phantomjs的位置地址 phantomjs: binPath: windows: binPath-win linux: binPath-linux jsPath: windows: jsPath-win linux: jsPath-linux imagePath: wind ...
  • 定時任務簡介 定時任務是指按照預定的時間間隔或特定時間點自動執行的計劃任務或操作。這些任務通常用於自動化重覆性的工作,以減輕人工操作的負擔,提高效率。在電腦編程和應用程式開發中,定時任務是一種常見的編程模式,用於周期性地執行某些操作、處理數據或觸發事件。 以下是一些關於定時任務的重要概念: 時間間 ...
  • 插值運算是一種數據處理方法,主要用來填補數據之間的空白或缺失值。因為在實際應用中,數據往往不是完整的,而是存在著空白或缺失值,這些空白或缺失值可能是由於數據採集困難、數據丟失或數據處理錯誤等原因造成的。如果直接使用這些空白或缺失值進行分析和預測,將會對結果造成很大的影響。 插值運算可以用來填補這些空 ...
  • 是極致魅惑、灑脫自由的Java heap space?是知性柔情、溫婉大氣的GC overhead limit exceeded?是純真無邪、活潑可愛的Metaspace?如果以上不是你的菜,那還有……刁蠻任性,無跡可尋的CodeCache!性感火辣、心思細膩的Direct Memory高貴冷艷,獨... ...
  • JMM 請你談談對Volatile的理解 Volatile是java虛擬機提供的輕量級的同步機制 1、保證可見性 2、不保證原子性 3、禁止指令重排 什麼是JMM JVM->java虛擬機 JMM->java記憶體模型,不存在的東西,概念!約定 關於JMM的一些同步的約定: 線程解鎖前,必須把共用變數 ...
  • Go 介面-契約介紹 目錄Go 介面-契約介紹一、介面基本介紹1.1 介面類型介紹1.2 為什麼要使用介面1.3 面向介面編程1.4 介面的定義二、空介面2.1 空介面的定義2.2 空介面的應用2.2.1 空介面作為函數的參數2.2.2 空介面作為map的值2.3 介面類型變數2.4 類型斷言三、盡 ...
  • 實踐環境 Python 3.6.2 confluent-kafka 2.2.0 confluent-kafka簡介 Confluent在GitHub上開發和維護的confluent-kafka-python,Apache Kafka®的一個python客戶端,提供了一個與所有brokers>=v0. ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...