欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
使用 Visual Basic 9.0 和 WPF 創(chuàng )建動(dòng)態(tài)地圖
本文討論: WPF 依賴(lài)屬性 使用 LINQ 查詢(xún) XML 繪制地圖 實(shí)現地圖數據可視化
本文使用了以下技術(shù):
WPF, Visual Basic 9.0, LINQ
目錄
WPF 數據綁定
應用程序對象模型
Map 類(lèi)
導入地圖數據
地圖數據格式
導入數據
繪制地圖
實(shí)現人口數據可視化
結論
一直對繪制地圖有些著(zhù)迷。同時(shí)我認為 Visual Studio® 2008 和 Visual Basic® 9.0 實(shí)在令人驚奇。因此,當我有機會(huì )體驗 Visual Studio 并撰寫(xiě)相關(guān)文章時(shí),我認為絕佳的主題是關(guān)于使用 Visual Basic 來(lái)繪制地圖的教程。這不僅能夠讓我有機會(huì )得以展示一些非??岬?Visual Basic 功能,而且還能為您提供一個(gè)可運行的示例,您可以此為基礎,向自己的程序添加相似功能。
 
我的杰作如圖 1 所示,該圖顯示了利用熱圖來(lái)直觀(guān)展示美國人口的應用程序屏幕快照。該應用程序的構建充分利用了 Windows® Presentation Foundation (WPF) 數據綁定基礎結構,這讓我能夠有效地將應用程序的域特定邏輯和用戶(hù)界面可視化分離開(kāi)來(lái)。
圖 1 人口地圖應用程序 (單擊該圖像獲得較小視圖)
圖 1 人口地圖應用程序 (單擊該圖像獲得較大視圖)
下一部分中,我會(huì )先簡(jiǎn)單介紹一些初步的 WPF 數據綁定主題,然后我會(huì )用本文的剩余篇幅詳細說(shuō)明如何編寫(xiě)該應用程序。我會(huì )先介紹應用程序的 Visual Basic 對象模型,然后討論如何使用 Visual Basic 9.0 中創(chuàng )新性的新 XML 功能和 LINQ 來(lái)實(shí)現數據處理邏輯。最后我將展示如何使用 WPF 有效地實(shí)現應用程序數據可視化。
WPF 數據綁定
WPF 數據綁定基礎結構基于依賴(lài)對象和依賴(lài)屬性概念。依賴(lài)對象提供對更改通知及動(dòng)態(tài)提取和檢索屬性值功能的支持。依賴(lài)屬性則是與依賴(lài)對象關(guān)聯(lián)的屬性。兩者共同構成了 WPF 眾多方面(包括數據綁定、動(dòng)畫(huà)和樣式)背后的核心基礎結構。
依賴(lài)對象由從 DependencyObject 類(lèi)派生的類(lèi)型的實(shí)例來(lái)表示。同樣,依賴(lài)屬性由已注冊到 WPF 屬性系統的 DependencyProperty 實(shí)例來(lái)表示。
用于應用程序數據模型時(shí),依賴(lài)屬性可大大簡(jiǎn)化代碼。它們允許直接實(shí)現許多任務(wù),而無(wú)需程序員顯式操作控件。通過(guò) WPF 聲明性數據綁定和樣式機制,更改會(huì )自動(dòng)傳播到用戶(hù)界面,而無(wú)需自定義邏輯。
這使得 WPF 用戶(hù)界面底層的代碼更易于閱讀、編寫(xiě)和維護。它還倡導各層之間更好的分離,從而提升到更簡(jiǎn)明的應用程序體系結構。最后(也是最重要的),它可讓您充分利用諸如 Expression BlendTM 之類(lèi)的工具,以可視化方式(注重樣式元素而非應用程序邏輯)來(lái)設計用戶(hù)界面。
如需使用依賴(lài)屬性的簡(jiǎn)單示例,請參見(jiàn)圖 2。其中我展示了一部分 MapRegion 類(lèi)定義。MapRegion 繼承自 DependencyObject。其主要用途是表示地圖內的地理區域。它聲明了兩個(gè)依賴(lài)屬性:RegionName 和 IsSelected。依賴(lài)屬性通過(guò)調用 DependencyProperty 類(lèi)上的共享 Register 方法進(jìn)行聲明,提供了屬性名稱(chēng)、其類(lèi)型和包含該屬性的類(lèi)的類(lèi)型(此例中為 MapRegion)。之后,返回的依賴(lài)屬性會(huì )分配給類(lèi)上聲明的公共、共享、只讀字段。這一過(guò)程主要是為了遵循 WPF 約定,將依賴(lài)屬性的元數據公開(kāi)為定義它們的類(lèi)上的共享字段。
然后,依賴(lài)屬性通過(guò)包裝屬性(調用 DependencyObject 類(lèi)中定義的 GetValue 和 SetValue 方法)向代碼公開(kāi),將適當的 DependencyProperty 對象提供為參數。這使得 MapRegion 類(lèi)的使用者能夠像訪(fǎng)問(wèn)其他任何普通的實(shí)例屬性一樣訪(fǎng)問(wèn)依賴(lài)屬性,同時(shí)充分利用 WPF 中豐富的依賴(lài)屬性系統。
值得一提的是,實(shí)際的屬性數據并沒(méi)有直接存儲為 MapRegion 類(lèi)中的字段。實(shí)際上,WPF 會(huì )管理依賴(lài)對象相關(guān)聯(lián)的每個(gè)依賴(lài)屬性的存儲,這樣通過(guò)調用 SetValue 和 GetValue 便可隨時(shí)使用它們。
還應注意的是,依賴(lài)屬性只能向依賴(lài)對象注冊一次。如果嘗試使用同一類(lèi)型的相同名稱(chēng)注冊?xún)蓚€(gè)依賴(lài)屬性,則會(huì )引發(fā)異常。
在我的示例中,我通過(guò)使用調用 DependencyProperty.Register 的顯式初始化表達式,來(lái)聲明共享的只讀字段,從而確保每個(gè)依賴(lài)屬性只注冊一次。這會(huì )導致注冊過(guò)程作為 MapRegion 類(lèi)靜態(tài)構造函數的一部分來(lái)執行,而公共語(yǔ)言運行庫 (CLR) 確保會(huì )運行一次(在執行引用 MapRegion 類(lèi)的代碼之前)。
圖 3 所示的 XAML 代碼顯示了依賴(lài)屬性如何用于將域模型的更改自動(dòng)傳播到應用程序用戶(hù)界面的示例。它定義了一個(gè)樣式,當應用于 Polygon 控件后,在其關(guān)聯(lián)的 MapRegion 將 IsSelected 屬性設為 true 時(shí),會(huì )使多邊形呈現為橙色粗邊框,否則為黑色細邊框。這讓驅動(dòng)應用程序的代碼能夠輕松地將區域標記為選定,并讓用戶(hù)界面相應作出響應。
應用程序對象模型
WPF 數據綁定是相當出色的,因此我著(zhù)手將它盡可能地用于我的應用程序。我的目的是能夠編寫(xiě)清晰、簡(jiǎn)潔和域特定的代碼來(lái)驅動(dòng)應用程序,并能夠使用 Expression Blend 來(lái)設計其界面。
為實(shí)現這一點(diǎn),我創(chuàng )建了可充分利用 WPF 依賴(lài)屬性系統的對象模型來(lái)表示地圖信息。該模型由三個(gè)主要類(lèi)組成 — Maps、MapRegion 和 MapPolygon — 全部從 DependencyObject 派生而來(lái)。Map 類(lèi)是對象模型的根,用于表示包含區域列表的地圖。MapRegion 類(lèi)則表示地圖上的區域或地理實(shí)體。它包含一個(gè)多邊形列表,每個(gè)多邊形均描述定義區域的連續地理范圍之一的邊界。MapPolygon 類(lèi)表示區域內的多邊形,包含了描述其頂點(diǎn)的 Point 對象集合。
Map 類(lèi)有五個(gè)依賴(lài)屬性:BoundingBox、ScaleX、ScaleY、TranslateX 和 TranslateY。BoundingBox 屬性是 Rect 類(lèi)的實(shí)例,存儲了包含地圖上所有區域的最小矩形范圍。ScaleX、ScaleY、TranslateX 和 TranslateY 屬性是為支持地圖上的縮放和平移而定義的。這些屬性至關(guān)重要,因為地圖上各點(diǎn)的坐標表示從赤道和本初子午線(xiàn)的交叉點(diǎn)開(kāi)始的偏移量(以千米為單位)。另一方面,WPF 使用不同的坐標系統,按從窗口左上角開(kāi)始的偏移量進(jìn)行定義,以邏輯像素為單位(一個(gè)邏輯像素等于 1/96 英寸)。
因此,ScaleX、ScaleY、TranslateX 和 TranslateY 屬性用于執行下列操作:
縮放地圖以便適應窗口大小。 垂直翻動(dòng)地圖,以便它不會(huì )繪制成上下顛倒。(在世界視圖中,Y 坐標會(huì )隨著(zhù)您向北行進(jìn)而增加;而在 WPF 視圖中,Y 坐標會(huì )隨著(zhù)您向窗口底部移動(dòng)而增加。) 移動(dòng)地圖以便其左上角對應于顯示地圖的控件的左上角。
 
您還可以使用這些屬性來(lái)實(shí)現用戶(hù)界面內的縮放和平移功能。例如,將 ScaleX 值和 ScaleY 值乘以 1.5 會(huì )使地圖放大到 150%,將其 TranslateX 屬性加 50 則會(huì )使地圖視圖向西移動(dòng) 50 千米。值得注意的是,更改這些值不會(huì )改變地圖中的坐標。實(shí)際上,這些值是用于向用戶(hù)界面傳達顯示地圖所需的操作。
Map 類(lèi)通過(guò) Regions 屬性公開(kāi)其區域集合。但是,Regions 與類(lèi)上的其他屬性不同,它不是依賴(lài)屬性,而是類(lèi)型為 ObservableCollection(of MapRegion) 的只讀屬性。它沒(méi)有被聲明為依賴(lài)屬性,那是因為我不需要能夠一次分配整個(gè)集合。然而,該集合本身是可變的,并且可使用 ObservableCollection 類(lèi)的 Add 和 Remove 方法在地圖上添加或刪除區域。同時(shí),由于該集合公開(kāi)為 ObservableCollection,因此它仍參與 WPF 數據綁定系統。例如,如果 ListBox 與 ObservableCollection 進(jìn)行了數據綁定,則向該集合添加新的項目便會(huì )導致該新項出現在 ListBox 中。同樣,從集合刪除項目也會(huì )導致從 ListBox 中刪除它。
Map 類(lèi)
MapRegion 類(lèi)定義了兩個(gè)依賴(lài)屬性:BoundingBox 和 RegionName。BoundingBox 屬性定義包含區域的矩形范圍,RegionName 則存儲區域名稱(chēng)。該類(lèi)還定義了兩個(gè)集合屬性:Polygons 和 FipsCodes。Polygons 集合存儲定義區域的多邊形,FipsCodes 則存儲與區域相關(guān)的一組數字 FIPS(聯(lián)邦信息處理標準)代碼。該類(lèi)使用 FIPS 代碼,因為在應用程序中使用的多邊形數據是從美國人口普查局下載的,它使用 FIPS 代碼來(lái)唯一標識美國的地理實(shí)體。您可以從itl.nist.gov/fipspubs/by-num.htm 下載關(guān)于聯(lián)邦信息處理標準的詳細信息。此外,還可以從census.gov/geo/www/cob 訪(fǎng)問(wèn)關(guān)于美國人口普查局的公共域 TIGER 地理數據庫的技術(shù)信息。
MapPolygon 類(lèi)定義了兩個(gè)屬性。第一個(gè)是名為 Region 的只讀依賴(lài)屬性,存儲對包含多邊形的區域的引用。第二個(gè)是名為 Points 的集合屬性,存儲定義多邊形頂點(diǎn)的一組 Point 結構。在圖 4 中可以看到該類(lèi)的完整源代碼。
Region 屬性作為只讀依賴(lài)屬性公開(kāi)。這使得 WPF 屬性系統能夠檢測對屬性值的更改,但不允許 WPF 修改該屬性值。只讀依賴(lài)屬性是通過(guò)調用 DependencyProperty 類(lèi)的 RegisterReadOnly 方法來(lái)聲明的。與 Register 方法不同,RegisterReadOnly 會(huì )返回 DependencyPropertyKey 實(shí)例而不是返回 DependencyProperty。
依賴(lài)屬性鍵是可實(shí)現對只讀依賴(lài)屬性進(jìn)行修改的對象。這些對于實(shí)現類(lèi)(需要內部更新屬性值,并由其他類(lèi)型檢測到更改,但不允許對值進(jìn)行外部修改)非常有用。因此,DependencyPropertyKey 通常不會(huì )由定義它們的類(lèi)公開(kāi)。這便是 RegionPropertyKey 字段標記為私有的原因。之后,第二個(gè)共享字段 RegionProperty 會(huì )用于公開(kāi)提供它的只讀別名。
Region 屬性為只讀屬性,因為它設計為無(wú)法從外部進(jìn)行編輯。實(shí)際上,當在 MapRegion 類(lèi)的區域集合中添加或刪除多邊形時(shí),它會(huì )自動(dòng)設置和清除值。這是通過(guò)以下方式實(shí)現的:處理多邊形集合的 CollectionChangedEvent 并將適當的 Region 實(shí)例傳播到受影響的多邊形。
事件處理程序的實(shí)現如圖 5 所示。它通過(guò)調用存儲于處理程序 NotifyCollectionChangedEventArgs 參數中 NewItems 和 OldItems 集合上的 SetRegion 擴展方法來(lái)實(shí)現。之后該擴展方法會(huì )在目標集合中每一項上調用 MapPolygon 類(lèi)的 SetRegion 方法。該實(shí)例方法已標記為友元,以避免被調用。該擴展方法的實(shí)現如下所示:
<Extension()> _Sub SetRegion(ByVal x As IEnumerable(Of MapPolygon), _ByVal r As MapRegion)For Each item In xitem.SetRegion(r)NextEnd Sub
 
與 Map 和 MapRegion 類(lèi)上的集合屬性不同,MapPolygon 類(lèi)上的 Points 集合不是 ObservableCollection(of T)。而是使用了內置 WPF PointsCollection 類(lèi)。這與 WPF Polygon 控件用于存儲它所含一組頂點(diǎn)的類(lèi)型相同。通過(guò)在數據模型中使用此類(lèi),便可實(shí)現將 Polygon 控件與 MapPolygon 實(shí)例直接進(jìn)行數據綁定。
導入地圖數據
應用程序從存儲于磁盤(pán)上的 XML 文件加載其地圖數據。我通過(guò)從美國人口普查局下載的原始 ASCII 制圖邊界文件創(chuàng )建文件,其中說(shuō)明了美國每個(gè)州和縣(及等同范圍)的邊界。州邊界數據用于繪制美國地圖,縣邊界數據則用于實(shí)現地圖上人口數據可視化。然后我取得下載的數據,并將其轉換為 XML 文件以便處理。本文的下載提供了將文件轉換為 XML 的代碼??蓮?a target="_blank" >census.gov/geo/www/cob/bdy_files.html 下載原始數據文件。
使用 Visual Studio Create Schema 功能,我便能夠自動(dòng)生成描述 XML 文件內容的 XML 架構。這樣我便能夠使用新的 Visual Basic XML IntelliSense® 功能,它可依據項目中包括的任何架構文件顯示 XML 成員訪(fǎng)問(wèn)表達式(參見(jiàn)圖 6)。
圖 6 Visual Basic XML IntelliSense (單擊該圖像獲得較小視圖)
圖 6 Visual Basic XML IntelliSense (單擊該圖像獲得較大視圖)
地圖數據格式
描述 XML 地圖文件的架構定義了一種簡(jiǎn)單格式,其中包含一個(gè)根 File 標記,它隨之又包含一系列 Region 標記。每個(gè) Region 標記都包含一系列 FipsCode 和 Polygon 標記,每個(gè) Polygon 標記則包含一系列 Vertex 和 Island 標記。
Region 標記用于描述簡(jiǎn)單的區域。它定義了兩個(gè)必需的屬性:Type 和 Name。Type 屬性提供區域類(lèi)型的描述。就我的應用程序而言,我通常使用值 State 或 County。但是,在一般情況下,所有值均可用于 Type 屬性。Name 屬性則說(shuō)明區域的名稱(chēng)。
區域中定義的每個(gè) FipsCode 標記均說(shuō)明其中一個(gè) FIPS 代碼項。Region 內的最后一個(gè) FipsCode 標記定義了區域的數字 ID。其他 FipsCode 標記則遞歸描述區域各父項的數字 ID。
就我的應用程序而言,所有區域最多具有兩個(gè)相關(guān)的 FipsCode 值。特別是,描述州(或者州等同范圍)的區域通常具有一個(gè)項,描述與該州相關(guān)的 FIPS 代碼。描述縣(或縣等同范圍)的 Regions 通常具有兩個(gè)項,第一項表示包含縣的州 FIPS 代碼,第二項則表示縣本身的 FIPS 代碼。任何特定區域的數字 ID 通常都保證在其直接父項的范圍內唯一。
區域的每個(gè) Polygon 標記描述了區域內包含的單個(gè)多邊形。多邊形由一系列 Vertex 標記組成,每個(gè)標記描述了單個(gè)頂點(diǎn)。Vertex 標記定義了五個(gè)必需的屬性:Ordinal、Longitude、Latitude、X 和 Y。Ordinal 屬性定義了多邊形頂點(diǎn)的順序。其主要目的是,當頂點(diǎn)由不保留順序的查詢(xún)處理時(shí),能夠對頂點(diǎn)進(jìn)行正確排序。它目前尚未用于我的應用程序。Longitude 和 Latitude 屬性描述了頂點(diǎn)的經(jīng)度和緯度坐標。同樣,X 和 Y 屬性定義了投影到矩形空間的頂點(diǎn)坐標和應用程序用于繪制地圖的對象。
X 和 Y 屬性是通過(guò)圖 7 所示的簡(jiǎn)單投影來(lái)計算的。此投影不是特別準確,可能不適用于某些情形。在這些情況下,可以使用 Longitude 和 Latitude 而非存儲于文件中的 X 和 Y 值來(lái)直接計算新值。就我的應用程序而言,并不需要高度的地理精確度,這便已足夠。
圖 7 極其簡(jiǎn)單的地圖投影
多邊形內的 Island 標記定義了包含在其中但不屬于它所含區域的空洞。它包含了描述空洞邊界的 Vertex 標記的集合。我主要出于完整性目的將它們包含在數據文件中;但并沒(méi)有用于我的應用程序。這意味著(zhù)實(shí)現地圖數據可視化時(shí),地圖上會(huì )有極小的區域顯示稍有錯誤的值。對于我的應用程序而言,這不是個(gè)問(wèn)題,因此我便忽略而過(guò)了。
如果您的應用程序在這方面的準確性至關(guān)重要,或者是多邊形島很普遍的映射區域,則只需控制地圖的呈現順序便能輕松解決這一問(wèn)題。首先繪制包含島的多邊形,然后繪制上部的島,這樣便可以準確呈現多邊形島。在很多情況下,這可能需要額外的處理工作,以便確定重疊區域并構造出適當的順序。
導入數據
使用 LINQ 將地圖數據導入應用程序比較簡(jiǎn)單。執行這一操作的代碼如圖 8 所示。它定義了接受以下兩個(gè)參數的過(guò)程 LoadFile:file 和 list。file 參數是一個(gè)字符串,包含從磁盤(pán)加載 XML 文件的完整路徑。list 參數則是對 MapRegion 實(shí)例集合的引用。該過(guò)程會(huì )打開(kāi) XML 文件進(jìn)行處理,并將其定義的所有區域插入到提供的集合。
LoadFile 主體極其簡(jiǎn)單。此過(guò)程的工作方式如下:首先將提供的文件加載到 XDocument 實(shí)例,定義查詢(xún)以遍歷文檔并將其轉換為 MapRegion 實(shí)例集合,最后執行查詢(xún)并將其結果插入提供的輸出集合。
該查詢(xún)由多個(gè)不同的片斷組成。第一個(gè)片斷是 From 子句,使用 XML 成員訪(fǎng)問(wèn)表達式 doc.<File>.<Region>.<Polygon>.<Vertex> 來(lái)檢索文檔中所有的多邊形 Vertex 標記,作為查詢(xún)的基礎。值得注意的是,它并沒(méi)有使用 doc...<Vertex>,該表達式可以獲取文檔中所有的 Vertex 標記(包括 Island 標記內部所定義的)。實(shí)際上,它只包括 Polygon 標記內部直接定義的 Vertex 標記。查詢(xún)的第二部分是 Let 子句。此子句引入了兩個(gè)新變量,Polygon 和 Region,它們已分配給包含每個(gè)頂點(diǎn)的 Polygon 和 Region 標記。
查詢(xún)的第三部分是首個(gè) Group By 子句。它能夠輕松地將頂點(diǎn)列表按其包含的多邊形進(jìn)行分組,然后計算多邊形的邊界框。包含多邊形的區域也包含在分組鍵中,使它能夠用于未來(lái)的查詢(xún)。多邊形的邊界框是通過(guò)計算其頂點(diǎn) X 和 Y 屬性的最小和最大值來(lái)計算的。這通過(guò)調用自定義聚合函數 MinDBL 和 MaxDBL 來(lái)完成,兩者由兩個(gè)擴展方法所定義:
<Extension()> _Function MinDBL(Of T)(ByVal x As IEnumerable(Of T), _ByVal y As Func(Of T, String)) As DoubleReturn x.Min(Function(z) CDbl(y(z)))End Function<Extension()> _Function MaxDBL(Of T)(ByVal x As IEnumerable(Of T), _ByVal y As Func(Of T, String)) As DoubleReturn x.Max(Function(z) CDbl(y(z)))End Function
 
這些方法用于定義聚合函數,聚合函數首先將提供的參數轉換為 Double 類(lèi)型,再根據它計算最小或最大值。
Group By 子句之后是 Select 子句,可按結果將原始分組轉換為更好用的格式。特別是,它定義了一個(gè)子查詢(xún),使用 Group By 產(chǎn)生的分組,只從中投影出頂點(diǎn),然后使用 ToMapPolygon 擴展方法將產(chǎn)生的集合轉換為 MapPolygon 類(lèi)的實(shí)例:
<Extension()> _Function ToMapPolygon(ByVal items As IEnumerable(Of XElement)) As _MapPolygonDim ret As New MapPolygonret.Points.AddRange(From item In items Select item.ToPoint())Return retEnd Function<Extension()> _Function ToPoint(ByVal x As XElement) As PointReturn New Point(x.@X, x.@Y)End Function
 
它還會(huì )將原始 MinX、MinY、MaxX 和 MaxY 變量轉換為 Rect 類(lèi)的實(shí)例。
查詢(xún)的下一部分是它的第二個(gè) Group By 子句,可聚合先前根據 Region 選擇的結果,并計算包含所有區域多邊形的邊界框。邊界框是通過(guò) Enclose 自定義聚合函數計算的,該函數定義如圖 9 所示。查詢(xún)的最后一部分是最終的 Select 子句,可為從第二個(gè) Group By 返回的每個(gè)結果構造 MapRegion 實(shí)例。它通過(guò)兩個(gè)子查詢(xún)來(lái)完成這項工作,其中一個(gè)可投影出存儲于每個(gè) Group 成員中的多邊形實(shí)例,另一個(gè)則提取存儲于 Region 中的一組 FIPS 代碼。
繪制地圖
地圖加載到內存后,將它顯示在窗口中便輕而易舉。圖 10 中的 XAML 代碼顯示了完成此工作的簡(jiǎn)便方法。此處我定義了一個(gè)簡(jiǎn)單的 Canvas 控件,包含其 Render Transform 的兩種轉換,以及名為 MapViewer 的單個(gè) ItemsControl 作為其內容。這些轉換用于轉換地圖中區域的坐標,以便它們能正確顯示在畫(huà)布中。ItemsControl 用于以可視方式呈現地圖的內容。所有數據綁定都通過(guò)使用隱式數據環(huán)境來(lái)完成。就 MasterCanvas 控件而言,這通常設為 Map 類(lèi)的實(shí)例。
TranslateTransform 將其 TranslateX 和 TranslateY 屬性綁定到 Map 類(lèi)的等效屬性。通常,這些值在 Map 類(lèi)上設為 Map 邊界框左上角的反值。這具有移動(dòng)地圖內容的效果,以便其左上角與畫(huà)布的左上角相對應。同樣,ScaleTransform 將其 ScaleX 和 ScaleY 屬性綁定到 Map 類(lèi)上相關(guān)的屬性。在大多數情況下,它們設為畫(huà)布寬度與地圖寬度之正比,以及畫(huà)布高度與地圖高度之反比。
以下代碼顯示了 Map 類(lèi)中 ScaleTo 方法的實(shí)現:
Public Sub ScaleTo(ByVal size As Size)If BoundingBox.Width <> 0 AndAlso BoundingBox.Height <> 0 ThenScaleX = size.Width / BoundingBox.WidthScaleY = -size.Height / BoundingBox.HeightTranslateX = -BoundingBox.LeftTranslateY = -BoundingBox.BottomEnd IfEnd Sub
 
給定包含 MasterCanvas 高度和寬度的 Size 結構時(shí),該方法會(huì )轉換地圖,以便在畫(huà)布上完整顯示地圖。調用此方法是為了響應畫(huà)布的 SizeChanged 事件,以便畫(huà)布所含窗口重新調整大小時(shí),地圖能夠縮放以填充可用空間:
Private Sub WindowSizeChanged() Handles Me.SizeChangedIf m_Map IsNot Nothing Thenm_Map.ScaleTo(New Size(MasterCanvas.ActualWidth,MasterCanvas.ActualHeight))End IfEnd Sub
 
值得注意的是,所含 TransformGroup 內轉換的順序相當重要。特別是,TranslateTransformation 必須在 ScaleTransform 之前發(fā)生。這允許兩個(gè)轉換的參數可依據域模型(而非用戶(hù)界面)指定。如果先列出 ScaleTransform,則 TranslateTransform 的值可能需要以像素(而非千米)來(lái)指定,這需要顯式轉換。首先指定 TranslateTransform 可大大簡(jiǎn)化應用程序的對象模型。
ItemsControl 用于將地圖內容呈現到畫(huà)布上。它的行為類(lèi)似于 ListBox 控件。實(shí)際上,ItemsControl 是 ListBox 的基類(lèi),定義了大多數的數據綁定行為。但是,與 ListBox 不同的是,ItemsControl 不會(huì )將項目呈現為列表形式。這使得它更適用于呈現地圖,因為地圖顯然不應呈現為列表形式。
ItemsControl 將其 ItemsSource 屬性綁定到地圖的 Regions 集合,并使用 SimpleCanvasTemplate 和 RegionTemplate 資源來(lái)定義如何呈現所有內容。用于 ItemsControl 之 ItemsPanel 屬性的 SimpleCanvasTemplate 僅僅創(chuàng )建一個(gè)空 Canvas。它的目的是定義容器,用于承載由控件的 ItemTemplate 創(chuàng )建的每個(gè)項。使用畫(huà)布的主要原因是畫(huà)布允許顯式定位其內容。其他“容器控件”(如 StackPanel)會(huì )嘗試應用最終無(wú)法正確繪制地圖的自動(dòng)布局邏輯。
RegionTemplate 資源定義了用于地圖中每個(gè) Region 的可視化布局。其工作方式是為每個(gè)區域聲明一個(gè)嵌套 ItemsControl,并將其 ItemSource 綁定到區域的 Polygon 集合即可。與 MapViewer 一樣,RegionTemplate 中定義的嵌套 ItemsControl 使用畫(huà)布作為其 ItemsPanel(實(shí)際上它重用了 SimpleCanvasTemplate)。但是,與 MapViewer 不同的是,它使用 PolygonTemplate 資源來(lái)呈現其項目。
PolygonTemplate 資源定義了一個(gè)數據模板,可呈現給定 MapPolygon 類(lèi)的實(shí)例的 WPF 多邊形控件。它將每個(gè) Polygon 的 Points 集合綁定到 MapPolygon 實(shí)例的 Points 屬性。值得一提的是,Polygon 控件將其 Fill 屬性顯式設為 Transparent。這對于使 Polygon 能響應多個(gè)鼠標事件是不可或缺的。WPF 會(huì )區分設置了 Fill 屬性和沒(méi)有設置此屬性的多邊形。缺少 Fill 畫(huà)筆的多邊形被視為外殼多邊形,而顯式設置了 Fill 畫(huà)筆的多邊形則認為是已填充的多邊形。用于已填充多邊形的鼠標事件(如 MouseUp、MouseEnter 和 MouseLeave)會(huì )在鼠標位于多邊形的內部時(shí)激發(fā)。就外殼多邊形而言,圖形的內部并不視為其定義的一部分。在此情況下,將鼠標置于多邊形的內部不會(huì )激發(fā)任何鼠標事件。但是,通過(guò)將多邊形的填充內容設為透明便能夠與鼠標交互,而無(wú)需遮蔽地圖上繪制的其他數據。
多邊形模板的另一個(gè)有趣方面是,它使用了聲明性、基于觸發(fā)器的樣式來(lái)驅動(dòng)多邊形外觀(guān)。特別是,它引用了定義兩個(gè)截然不同的樣式來(lái)呈現多邊形的 RegionPolygonStyle 資源。區域中 IsSelected 值為 true 的多邊形通過(guò)橙色粗邊框來(lái)呈現,IsSelected 值為 false 的則通過(guò)黑色細邊框來(lái)呈現。以下事件處理代碼顯示了如何輕松地用樣式來(lái)實(shí)現非??岬挠脩?hù)界面功能,如輸入跟蹤:
Private Sub Polygon_MouseEnter(ByVal sender As Polygon, ByVal e As _System.Windows.Input.MouseEventArgs)CType(sender.DataContext, MapPolygon).Region.IsSelected = TrueEnd SubPrivate Sub Polygon_MouseLeave(ByVal sender As Polygon, ByVal e As _System.Windows.Input.MouseEventArgs)CType(sender.DataContext, MapPolygon).Region.IsSelected = FalseEnd Sub
 
圖 11 顯示了使用中的一個(gè)示例。
圖 11 使用鼠標事件觸發(fā)器突出顯示區域 (單擊該圖像獲得較小視圖)
圖 11 使用鼠標事件觸發(fā)器突出顯示區域 (單擊該圖像獲得較大視圖)
實(shí)現人口數據可視化
實(shí)現地圖上方的人口數據可視化相當簡(jiǎn)單。實(shí)現這一過(guò)程的 XAML 代碼如圖 12 所示。它通過(guò)將第二個(gè)名為 DataLayer 的 ItemsControl 添加到 MasterCanvas,從而修改用于繪制地圖的 XAML。由于 DataLayer 位于 MasterCanvas 內,因此其內容的轉換方式與 MapViewer 相同。這允許綁定到 DataLayer 的數據也能夠依據底層的域模型(而非用戶(hù)界面)進(jìn)行指定。
與 MapViewer 不同的是,DataLayer 并不旨在從 MasterCanvas 直接繼承其數據環(huán)境,而旨在將要可視化的數據顯式設置為其 ItemsSource。提供的數據應該是定義了 Color 和 Points 兩個(gè)屬性的對象集合。Color 屬性應為 Brush 類(lèi)型,并定義由 Points 描述的多邊形在地圖上應如何著(zhù)色。Points 屬性應為 PointsCollection 的實(shí)例,定義要著(zhù)色的多邊形的各頂點(diǎn)。以下是用于呈現 DataLayer 元素的 DataTemplate:
<DataTemplate x:Key="DataLayerTemplate"><Polygon Stroke="Transparent" Fill="{Binding Path=Color}" Points="{Binding Path=Points}" /></DataTemplate>
 
它的工作方式是創(chuàng )建多邊形并將其 Fill 和 Points 屬性綁定到底層元素上的適當屬性即可。
圖 13 所示的 LoadData 方法負責將主要的地圖數據加載到 Map 類(lèi)的實(shí)例,將其設為 MasterCanvas 的 DataContext,構造熱圖并將 DataLayer 綁定到此。
該方法特別有趣的部分是用于構建熱圖的查詢(xún)。它的工作方式是聯(lián)接地圖上顯示的一組州、從磁盤(pán)加載的一組縣以及 XML 人口數據。它將一組州與一組縣聯(lián)接,以便篩選出州中已定義但地圖上未顯示的縣。該聯(lián)接兩邊的鍵便是每個(gè)區域的首個(gè) FIPS 代碼。就 State 而言,這將對應于其數字 ID。就 County 而言,它對應于包含州數字 ID 的縣。XML 人口數據然后與結果聯(lián)接,以便將每個(gè)縣的人口值與定義該縣的 MapRegion 實(shí)例關(guān)聯(lián)起來(lái)。
聯(lián)接的結果會(huì )進(jìn)行篩選,以便包括 2006 年度的人口數據。這是十分有必要的,因為 XML 人口數據包含多個(gè)年度的數據,而此案例中,我只想在地圖上顯示一個(gè)特定年度。無(wú)法依據年度篩選將會(huì )導致在地圖為同一區域繪制出具有不同值的多個(gè)重疊多邊形。篩選的結果會(huì )與每個(gè)縣的 Polygons 集合交叉聯(lián)接。這可將縣集合有效擴展到多邊形集合。
查詢(xún)的最后一部分是 Select 語(yǔ)句,可從每個(gè)多邊形提取點(diǎn)集合,依據相關(guān)人口值計算應顯示的顏色,然后構造以該顏色呈現該區域的 SolidColorBrush。這些顏色值是使用 colorMapEntries 數組計算的,該數組定義了人口值和顏色之間的映射。實(shí)質(zhì)上,數組中的每一項都定義了一種顏色和相關(guān)的上限人口值。然后從人口所在的兩個(gè)顏色地圖項之間內插用于縣的特定顏色。
該內插通過(guò)圖 14 中定義的 Interpolate 擴展方法來(lái)實(shí)現。它的工作方式是在 colorMapEntries 數組中執行二分法搜索,查找人口值大于提供值的最小項。然后它取得該項和上一項,并用來(lái)內插適當的顏色值。工作方式是調用 ColorMapEntry 類(lèi)上定義的 Interpolate 實(shí)例方法。
結論
我的應用程序的最大優(yōu)點(diǎn)在于編寫(xiě)簡(jiǎn)單。特別是,我廣泛使用了 Expression Blend 來(lái)定義其界面,因此使得添加出色的視覺(jué)效果易如反掌。我還使用 XML 來(lái)存儲應用程序運行所需的所有數據,這使我能夠使用 Visual Basic 中的新集成 XML 功能以及 LINQ,輕松實(shí)現所有的數據操作邏輯。我還將界面設計為構建于 WPF 數據綁定基礎結構之上,因此創(chuàng )建了構建于豐富對象模型之上、清楚分離、結構合理的應用程序。
實(shí)質(zhì)上,通過(guò)使用 Visual Basic、WPF、Expression Blend 和 LINQ,我能夠快速有效地從現有的數據主體中拼湊出實(shí)現相當成熟的可視化的應用程序。此應用程序能夠很方便地進(jìn)行擴展,以便查看不同年度的數據,或以各種方式操作數據。本文的下載提供了所有代碼,請自由試驗,創(chuàng )造一切可能。
NEW:Explore the sample code online! - or - 代碼下載位置:MapsWithVB9WPF2007_12.exe (30813KB)
本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
用 Python 繪制空間數據可視化地圖
.Net5 WPF快速入門(mén)系列教程
WPF Databinding----Collections
ComponentOne DataGrid for WPF 基礎教程:4.列的類(lèi)型
gis原理十六
地理信息系統導論學(xué)習筆記(11)——矢量數據分析
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久