基于gpf的甘特圖控件創(chuàng)建_第1頁(yè)
基于gpf的甘特圖控件創(chuàng)建_第2頁(yè)
基于gpf的甘特圖控件創(chuàng)建_第3頁(yè)
基于gpf的甘特圖控件創(chuàng)建_第4頁(yè)
基于gpf的甘特圖控件創(chuàng)建_第5頁(yè)
全文預(yù)覽已結(jié)束

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

基于gpf的甘特圖控件創(chuàng)建

0統(tǒng)一編輯模型的應(yīng)用過(guò)去,windows應(yīng)用程序依靠32個(gè)用戶數(shù)據(jù)庫(kù)和sdi。sdi渲染組件、圖像和文本。WPF以DirectX技術(shù)為基礎(chǔ),為2D和3D圖形提供了更好的渲染效果。WPF通過(guò)統(tǒng)一的編輯模型,對(duì)2D、3D、控件以及視頻、語(yǔ)音等進(jìn)行整合,特別是與XAML技術(shù)結(jié)合,運(yùn)用XML的語(yǔ)法方式以聲明式的編程方式,為軟件的開(kāi)發(fā)特別是UI(UserInterface)部分的設(shè)計(jì)帶來(lái)了極大的便利。在圖形渲染方面,WPF使用矢量圖形,采用與分辨率無(wú)關(guān)的單位,使得應(yīng)用程序在不同的DPI下都可以獲得最佳的顯示效果。此外,WPF硬件加速以及富創(chuàng)作等特性,使得可以在構(gòu)建絢麗的UI的同時(shí)獲得最佳的性能。甘特圖是各類項(xiàng)目管理中廣為采用的一種圖件。本文以甘特圖控件為例,詳細(xì)闡述WPF技術(shù)在控件設(shè)計(jì)與開(kāi)發(fā)中的應(yīng)用方法。1基于甘特圖的布局算法甘特圖主要組成部分:(1)任務(wù)控件。每個(gè)任務(wù)控件都是甘特表中的一條數(shù)據(jù)項(xiàng)的圖形化表示,并且可以對(duì)它進(jìn)行相關(guān)操作,比如拉伸與移動(dòng);(2)甘特圖容器。在WPF中,每個(gè)控件必須放入一個(gè)容器中才能進(jìn)行繪制。對(duì)于甘特圖,每個(gè)任務(wù)控件都位于這樣一個(gè)甘特圖容器中,它提供一個(gè)布局算法來(lái)對(duì)其中所包含的每個(gè)任務(wù)控件進(jìn)行布局;(3)時(shí)間欄。它的作用就相當(dāng)繪制函數(shù)時(shí)的坐標(biāo)系,對(duì)于甘特圖中每個(gè)任務(wù),最基本的要素就是任務(wù)的開(kāi)始時(shí)間與結(jié)束時(shí)間,而時(shí)間欄正相當(dāng)于這樣一個(gè)坐標(biāo)系,根據(jù)任務(wù)的開(kāi)始時(shí)間與結(jié)束時(shí)間來(lái)決定該任務(wù)的在甘特圖中的位置以及任務(wù)條的長(zhǎng)度;(4)甘特表。用于顯示每個(gè)任務(wù)的具體信息,如:編號(hào)、任務(wù)名稱、開(kāi)始時(shí)間、結(jié)束時(shí)間、工期、前置任務(wù)等。1.1甘特圖的設(shè)計(jì)這里采用數(shù)據(jù)庫(kù)來(lái)存儲(chǔ)該控件所需的數(shù)據(jù)。本文的重點(diǎn)是用闡述使用WPF的新特性來(lái)設(shè)計(jì)甘特圖,甘特圖自身的相關(guān)知識(shí)在這里不詳述,而且出于簡(jiǎn)單起見(jiàn),只列出部分字段,如表1所示(數(shù)據(jù)庫(kù)采用Access)。1.2外觀定義與對(duì)象分離這里將每個(gè)任務(wù)看成是一個(gè)控件,使用WPF的自定控件技術(shù)來(lái)構(gòu)建無(wú)外觀控件,而將外觀的定義以及觸發(fā)器等放在樣式表中來(lái)實(shí)現(xiàn),這樣就實(shí)現(xiàn)了控件邏輯與控件外觀的分離。使用WPF的依賴屬性來(lái)定義每個(gè)任務(wù)所需要的屬性。將每個(gè)任務(wù)看成一個(gè)控件的好處除了邏輯上的清晰外,還便于一些鼠標(biāo)事件的實(shí)現(xiàn),比如拖動(dòng)、拉伸、懸停等。1依賴項(xiàng)屬性建立一個(gè)名為Event的WPF自定義控件,在生成的文件中可以看到,類Event是繼承自UserControl的,所以自定義控件都繼承該類。接下來(lái)就是定義該控件的依賴項(xiàng)屬性。這里以任務(wù)的開(kāi)始時(shí)間來(lái)說(shuō)明如何定義依賴項(xiàng)屬性以及為什么要使用依賴項(xiàng)屬性。定義依賴項(xiàng)屬性(注意修飾符以及關(guān)鍵字DependencyProperty):publicstaticreadonlyDependencyPropertyStartDateProperty;必須在類的靜態(tài)構(gòu)造函數(shù)中定義,通過(guò)DependencyProperty.Register方法來(lái)注冊(cè)依賴項(xiàng)屬性。這里用的一個(gè)技巧就是定義一個(gè)FramworkPropertyMetadata,并將它作為參數(shù)提供給DependencyProperty.Register方法,在定義FramworkPropertyMetadata時(shí)我們使用FrameworkPropertyMetadataOptions枚舉來(lái)添加一些附加功能。這里使用枚舉值A(chǔ)ffectsArrange和AffectsMeasure,其作用是當(dāng)此屬性發(fā)生改變時(shí)會(huì)重新測(cè)量和布局該控件。這樣當(dāng)改變一個(gè)任務(wù)的開(kāi)始時(shí)間時(shí),它就會(huì)自動(dòng)進(jìn)行重繪,位置和長(zhǎng)度會(huì)自動(dòng)改變。依賴項(xiàng)屬性的訪問(wèn)與設(shè)置需要使用GetValue方法與SetValue方法,為了像.net中的屬性那樣訪問(wèn)依賴項(xiàng)屬性,下面使用屬性包裝器來(lái)包裝它。同時(shí)使用依賴項(xiàng)屬性便于數(shù)據(jù)綁定。2樣式表的屬性在該類的普通構(gòu)造函數(shù)中,設(shè)置該控件的樣式表以及數(shù)據(jù)上下文,這里樣式表是作為一個(gè)資源訪問(wèn)的:這里構(gòu)造參數(shù)是一個(gè)EventInfo類型,里面定義了和該類相同的屬性,不過(guò)都是普通屬性,將它作為任務(wù)控件的數(shù)據(jù)上下文的作用是便于在樣式表中定義數(shù)據(jù)綁定,然后再將該樣式應(yīng)用于此控件。3雙向數(shù)據(jù)掛鉤關(guān)于每個(gè)任務(wù)的相關(guān)數(shù)據(jù)(開(kāi)始時(shí)間、結(jié)束時(shí)間、任務(wù)名稱等等)保存在數(shù)據(jù)庫(kù)中,在程序加載時(shí)將數(shù)據(jù)表中讀取為L(zhǎng)ist<EventInfo>,將其綁定到甘特表上,對(duì)于List中的每一個(gè)EventInfo實(shí)例,將其作為一個(gè)任務(wù)控件的數(shù)據(jù)上下文,并在控件的Style里進(jìn)行雙向數(shù)據(jù)綁定,這樣在對(duì)控件進(jìn)行操作,比如移動(dòng)和拉伸時(shí),會(huì)修改控件的相關(guān)依賴項(xiàng)屬性。由于進(jìn)行了數(shù)據(jù)綁定,控件對(duì)應(yīng)的EventInfo實(shí)例的數(shù)據(jù)也會(huì)進(jìn)行相應(yīng)修改,同時(shí)EventInfo又與甘特表進(jìn)行了數(shù)據(jù)綁定,這樣數(shù)據(jù)表部分也會(huì)同時(shí)進(jìn)行更新,保存數(shù)據(jù)時(shí)可以將List<EventInfo>寫回?cái)?shù)據(jù)庫(kù),整個(gè)數(shù)據(jù)組織結(jié)構(gòu)如圖1所示。由于EventInfo是自定義的普通類,要實(shí)現(xiàn)它與控件的依賴項(xiàng)屬性的雙向綁定,所以必須對(duì)EventInfo類實(shí)現(xiàn)INotifyPropertyChanged接口,從而使得EventInfo類的屬性發(fā)生改變時(shí)通知綁定,從而進(jìn)行更新。4病毒拉格爾dragstumb一個(gè)任務(wù)控件最基本的鼠標(biāo)操作就是拉伸與移動(dòng),通過(guò)在任務(wù)控件兩端進(jìn)行拉伸來(lái)改變一個(gè)任務(wù)的開(kāi)始時(shí)間或結(jié)束時(shí)間,通過(guò)移動(dòng)一個(gè)任務(wù)可保持任務(wù)的工期不變,開(kāi)始時(shí)間與結(jié)束時(shí)間同時(shí)改變。在此通過(guò)兩個(gè)類來(lái)實(shí)現(xiàn)這個(gè)功能:MoveThumb和RemoveThumb。這兩個(gè)類都是繼承自Thumb類。這里使用該類的目的是為了實(shí)現(xiàn)鼠標(biāo)的拖放事件,可以分別定義DragStarted、DragDelta、DragCompleted三個(gè)事件來(lái)分別響應(yīng)拖放開(kāi)始、拖放中以及拖放結(jié)束時(shí)要執(zhí)行的操作。在拖放開(kāi)始時(shí),可以通過(guò)數(shù)據(jù)上下文來(lái)獲得該控件(數(shù)據(jù)上下文是在樣式表中的數(shù)據(jù)模板中實(shí)現(xiàn)的),然后在拖放事件時(shí)對(duì)該控件的開(kāi)始時(shí)間及結(jié)束時(shí)間進(jìn)行修改并且控件會(huì)自動(dòng)重繪,這樣就實(shí)現(xiàn)了動(dòng)態(tài)效果,在拖放結(jié)束時(shí)也可以進(jìn)行一些操作,如驗(yàn)證等。5種線型標(biāo)識(shí)的融合該控件的邏輯部分實(shí)現(xiàn)后,接下來(lái)就要定義控件的外觀??梢酝ㄟ^(guò)編寫一個(gè)樣式表,定義設(shè)置器、數(shù)據(jù)綁定、控件模板以及相關(guān)的觸發(fā)器,然后將該樣式表應(yīng)用于控件。關(guān)于設(shè)置器與數(shù)據(jù)綁定的部分如前所述,下面主要討論控件模板,通過(guò)定義控件模板就可以方便地定義一個(gè)控件的外觀,這里定義的控件模板主要包含一個(gè)Grid,Grid中主要包含三個(gè)矩形,如圖2所示。這里以三種線型標(biāo)識(shí)三個(gè)矩形,雙線矩形跨三行,它是控件的大輪廓,單線矩形表示了百分比槽,虛線矩形表示了百分比的值。在定義每個(gè)矩形時(shí)還涉及到一些數(shù)據(jù)綁定,這樣矩形的長(zhǎng)度就綁定到相應(yīng)控件的數(shù)據(jù)上了。這里可以把之前實(shí)現(xiàn)的MoveThumb和RemoveThumb放入模板中,并定義為透明的,需要兩個(gè)RemoveThumb,分別位于控件的兩端,一個(gè)MoveThumb位于控件的中間區(qū)域。下面在Style中設(shè)置控件的外觀并進(jìn)行相關(guān)的數(shù)據(jù)綁定。其語(yǔ)法簡(jiǎn)單,在Style中的設(shè)置器中實(shí)現(xiàn),如下:<SetterProperty=″StartDate″Value=″{BindingPath=StartDate,Mode=TwoWay}″/>第一個(gè)StartDate是指該控件的依賴項(xiàng)屬性,第二個(gè)StartDate是該控件的數(shù)據(jù)上下文中EventInfo實(shí)例的普通屬性,Mode值TwoWay即定義的綁定的模式為雙向綁定。還可以定義觸發(fā)器,這里我們定義一個(gè)屬性觸發(fā)器,根據(jù)控件的IsScope屬性,該屬性決定了任務(wù)是一個(gè)普通任務(wù)還是一個(gè)摘要任務(wù)。這個(gè)屬性觸發(fā)器可以在IsScope為真時(shí)定義另一個(gè)數(shù)據(jù)模板,這樣控件的外觀就會(huì)隨著IsScope屬性值而發(fā)生變化。2甘特圖控制軟件WPF中的所有容器都是繼承自Panel類,但鑒于該容器要對(duì)其所包含的每個(gè)任務(wù)控件的位置精確布局,所以這里采用的甘特圖控件繼承自Canvas,接下來(lái)要做的就是重寫兩個(gè)方法:MeasureOverride和ArrangeOverride,前者的作用是計(jì)算每個(gè)任務(wù)控件的大小,后者的作用是確定每個(gè)控件在容器中的具體位置。重寫這兩個(gè)方法后,當(dāng)任務(wù)控件放入甘特圖容器后,就會(huì)自動(dòng)計(jì)算其大小并精確布局。3圖形繪制方法背景與時(shí)間表都是通過(guò)WPF的2D引擎來(lái)繪制的,這里單獨(dú)定義了一個(gè)繼承自Canvas的容器,然后定義一個(gè)繪制背景和時(shí)間表的方法,最后定義一些事件,當(dāng)事件觸發(fā)時(shí)執(zhí)行這個(gè)繪制函數(shù)。這里要用到Visual對(duì)象,然后通過(guò)它的RenderOpeny方法來(lái)獲得一個(gè)DrawingContext對(duì)象,接著調(diào)用DrawingContext對(duì)象的相關(guān)方法進(jìn)行圖形繪制。當(dāng)繪制完成時(shí),將該Visual對(duì)象放入一個(gè)VisualCollection中,這里需要重寫兩個(gè)函數(shù),VisualChildrenCount方法和GetVisualChild方法,前者返回VisualCollection中所包含的Visual對(duì)象的個(gè)數(shù),后者返回VisualCollection中對(duì)應(yīng)的Visual對(duì)象。這樣WPF就會(huì)將VisualCollection中的每個(gè)Visual對(duì)象繪制出來(lái)。4數(shù)據(jù)模件設(shè)計(jì)甘特表的部分可以直接使用DataGrid類,然后通過(guò)樣式表定義數(shù)據(jù)模板以及一些觸發(fā)器,關(guān)鍵的數(shù)據(jù)部分可以用數(shù)據(jù)綁定來(lái)實(shí)現(xiàn),具體通過(guò)將它的ItemsSource賦一個(gè)列表對(duì)象(ObservableCollection列表)。5基于甘特圖的工程管理基于上述WPF技術(shù),系統(tǒng)地研制了一個(gè)外表美觀、功能完善的甘特圖控件,并成功應(yīng)用于國(guó)內(nèi)某煤礦礦井建設(shè)工程施工的項(xiàng)目管理,下面結(jié)合該實(shí)例來(lái)說(shuō)明設(shè)計(jì)流程與核心算法。5.1確定滾動(dòng)條的進(jìn)線方式甘特圖的呈現(xiàn)流程如圖3所示,其中Max值為當(dāng)前屏幕可視區(qū)域的垂直高度,VerOffset值在初次載入時(shí)的值為0,這樣會(huì)從第一條數(shù)據(jù)開(kāi)始顯示,當(dāng)甘特圖載入之后,通過(guò)調(diào)整滾動(dòng)條,會(huì)改變VerOffset的值,從而決定顯示的第一條數(shù)據(jù)對(duì)應(yīng)為數(shù)據(jù)庫(kù)中的第幾條數(shù)據(jù),這樣便呈現(xiàn)出了頁(yè)面的滾動(dòng)效果。這樣的設(shè)計(jì)可以使WPF繪圖引擎只繪制可視范圍內(nèi)的任務(wù)條,從而優(yōu)化了甘特圖呈現(xiàn)的速度及頁(yè)面滾動(dòng)時(shí)的響應(yīng)度。5.2中央算法的排列當(dāng)任務(wù)加入自定義的容器后,容器會(huì)根據(jù)算法1與算法2來(lái)進(jìn)行測(cè)量與排版,最終呈現(xiàn)完整的甘特圖。width值的更新measun方法①容器中的Children數(shù)等于0,返回Size(0,0),結(jié)束。②容器中的Children數(shù)大于0,初始化Width與Height的值為0,遍歷容器的Children中的對(duì)象,調(diào)用其Measure方法。③更新Width值與Height值,其中Height值每次的增量為任務(wù)條的高度加上任務(wù)條之間的空隙,Width取當(dāng)前值與當(dāng)前任務(wù)條右端值中較大的值。④遍歷結(jié)束,返回Size(Width,Height)。此為整個(gè)甘特圖的大小。生成任務(wù)系統(tǒng)坐標(biāo)系①初始化OriginPoint=newPoint(0,0),此為起始點(diǎn)坐標(biāo),初始化x=0,y=0,此為當(dāng)前待排版任務(wù)條的坐標(biāo)。②遍歷Children中的對(duì)象,獲取對(duì)象的寬高值width與height。③根據(jù)任務(wù)的開(kāi)始時(shí)間、序號(hào)以及width,height值來(lái)更新x,y的當(dāng)前值,從而確定任務(wù)條左上角的坐標(biāo)點(diǎn)childPoint=newPoint(x,y)。④調(diào)用系統(tǒng)函數(shù)Canvas.SetTop()與Canvas.SetLeft()來(lái)設(shè)置當(dāng)前對(duì)象的坐標(biāo)。⑤調(diào)用對(duì)象的Arrange()方法來(lái)對(duì)當(dāng)前對(duì)象的位置進(jìn)行排版。5.3效果截圖軟件運(yùn)行時(shí)的效果如圖4所示。6探索

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論