用WPF山寨折线图,抄?是狠狠的抄
???? 對(duì)于沒有美術(shù)細(xì)胞的我來說,抄襲人家的設(shè)計(jì)或是創(chuàng)意是再平常不過的事,我承認(rèn)這很無恥,如果在偉大“天朝”的教育體系下還可能升級(jí)為道德上的淪喪,畢竟人家搞個(gè)東西也不容易,可任務(wù)在身,只好下策,臉皮總是在生存以后才拿上臺(tái)面的。所以也就不避諱了,俺就是抄的。
????
???? 該圖抄襲自 萬倉一黍 的在winform中運(yùn)用FusionCharts圖表(一)
?
一.抄襲模式
?
??????? 盡管樣式要抄襲,可代碼不能抄襲,因?yàn)闆]有源碼^ – ^ 。首先我們先從使用者的角度出發(fā),作為使用者,我希望怎么來使用控件,而且要考慮到WPF的一些特性。線條可以一個(gè)個(gè)數(shù)組給,和傳統(tǒng)的控件一樣。可我認(rèn)為這并不符合WPF的組裝特性,每個(gè)線條可以是自由控制的,可粗可細(xì),可虛線可實(shí)線。
如效果為這樣的圖:
?
可以是這樣的設(shè)計(jì),也就是每個(gè)控件自己是一層,和其它控件沒有直接聯(lián)系。就連底面也是可以自由搭配的。
使用還有個(gè)就是代碼的書寫,那么在XAML中單個(gè)的控件就可以寫成這樣
<Sample:LineChart LineColor="Orange" LineThickness="20" Datas="{Binding Items}" />如若要實(shí)現(xiàn)多個(gè)拼接,把控件放到可以層疊的容器當(dāng)中就可以了,比如Grid.如果你的數(shù)據(jù)是集合形式的,還可以借助ItemsControl這樣的集合控件。
????? 這里可能已經(jīng)有人看出來抄襲的是WPF裝飾器的模式和概念。
?
二.抄襲圖形
?
????? 初步設(shè)想不錯(cuò),可還不夠靈活,假設(shè)每個(gè)點(diǎn)的樣式可以更改而不僅僅是這種默認(rèn)的白點(diǎn),如根據(jù)喜好可以設(shè)置五角星,小紅旗,這怎么辦?一般情況下我們會(huì)為控件再添加個(gè)點(diǎn)的模板屬性;在這里我又踟躕了很久,是否真的需要這么的“一步到位”?在幾年前,我曾聽說裝修現(xiàn)在有個(gè)觀點(diǎn)叫做“輕裝修,重裝飾”,就是建好一個(gè)架子,里面的東西是可以由著喜好、心情、季節(jié)隨意搭配。所以我更傾向于控件首先能實(shí)現(xiàn)一些比較簡(jiǎn)單的功能,可如果要更高級(jí)的功能和效果應(yīng)該可以附加上的,畢竟有時(shí)候一開始也很難知道用戶的喜好,加上有時(shí)候時(shí)間緊迫就只能先留下框架,以后有機(jī)會(huì)再討價(jià)還價(jià)索要時(shí)間。
????? 產(chǎn)品功能暫時(shí)可以延期,卻不能老是跳票,“永遠(yuǎn)的毀滅公爵”絕不是好榜樣。
????? 對(duì)每個(gè)點(diǎn)進(jìn)行模板,設(shè)置每個(gè)點(diǎn)實(shí)際的位置,很容易讓我們想到使用ItemsControl,做個(gè)放置位置的Panel就可以了, 當(dāng)然很明顯我們并不需要那么多的功能,只要求每個(gè)點(diǎn)都能設(shè)置一個(gè)模板,那么好吧,依葫蘆畫瓢來個(gè)ItemTemplate、ItemTemplateSelector、ItemStringFormat屬性,只需要在初始化的時(shí)候聲明個(gè)UIElementCollection變量,在數(shù)據(jù)存放以后為數(shù)據(jù)new個(gè)性模板就成,如GetContainerForItemOverride()方法。
???? 在這種條件下做個(gè)層,可以輕松的看到類似這樣的效果,當(dāng)然音符是我再次發(fā)揮抄襲特長的結(jié)果,具體的可以看http://xamlbase.com/free-icons.php
對(duì)于層來說,還可以有很多的發(fā)揮,如下:
對(duì)這種應(yīng)用也可以手到擒來:
不要驚訝,WPF是有API的,使用CombinedGeometry然后用GeometryCombineMode.Exclude就可以了。
因?yàn)榈咨部梢噪S意混搭,所以加個(gè)水印、Logo,背景提示語之類的也不是什么難事。
對(duì)于以上的所謂“創(chuàng)意”,當(dāng)然是抄襲的,參見各大網(wǎng)站統(tǒng)計(jì)圖。
?
三.抄襲代碼
?
?????? 項(xiàng)目經(jīng)理有要求圖上的所有線條比例要統(tǒng)一,這個(gè)要求很合乎常理,可我們的線條都是單獨(dú)的一個(gè)控件,你也許會(huì)說讓后端計(jì)算出一個(gè)最大值綁定一下不就OK了,但一般控件都可以達(dá)到的效果,憑什么就要讓業(yè)務(wù)干預(yù),畢竟我們分層的原則是UI和業(yè)務(wù)分離,雖然有時(shí)候會(huì)有些妥協(xié),但我們也要盡可能的做大完善,水平不就是在這樣的“苛責(zé)”中進(jìn)步的么?
?
感覺不錯(cuò)的抄法
▲名字抄襲
????? 做為前端人員,可能希望只要設(shè)置一個(gè)屬性就可以完成,其實(shí)它的目的就是為了功能的附加,感覺有點(diǎn)像ToolTipService吧,那么我們的名字就叫LineChartService。
<Sample:LineChart LineColor="Orange" Sample:LineChartService.GroupName="group1" LineThickness="2" Datas="{Binding Items}" /> <Sample:LineChart LineColor="Green" Sample:LineChartService.GroupName="group1" LineThickness="2" Datas="{Binding Items1}" />?
▲做法抄襲
??? 這種方法是方便,可作為后端的編碼人員應(yīng)該怎么做呢?印象中第一個(gè)出現(xiàn)的類似應(yīng)用可能就是RadioButton,因?yàn)樗灿袀€(gè)GroupName,可以根據(jù)組來決定勾選的控件影響的范圍,好吧看看它的源碼是如何做到的的,其實(shí)所謂的看就是一個(gè)大抄襲,去其特質(zhì)取其共性。
?
▲算法抄襲
???? 在抄襲這一模式的時(shí)候,有個(gè)想法就是計(jì)算出每個(gè)控件的最大值,然后放到一個(gè)全局的隊(duì)列中,這個(gè)隊(duì)列有自動(dòng)排序功能,并有一個(gè)屬性可以取得最大值.這其實(shí)是個(gè)算法,這個(gè)算法哪有的抄呢?當(dāng)時(shí)在看BeginInvoke,我們的DispatcherPriority放進(jìn)去,系統(tǒng)會(huì)根據(jù)值的大小排序,每次有個(gè)屬性可以取得最大值,這不正是我所期望的么,啥都不說了,直接Copy,當(dāng)然也要去掉一些東西,這種簡(jiǎn)單的算法,只要理解了他的目的,也沒啥難度。所以PriorityQueue這個(gè)內(nèi)部類也被我慘無人道的抄襲了。
?
▲WPF特性應(yīng)用抄襲
???? 對(duì)于屏幕的笛卡爾坐標(biāo),和我們普通的坐標(biāo)不同,越向下Y軸值越大,一般的做法是用高度值來減下,以符合需求,可在WPF有Transform,在最后繪制圖形的時(shí)候用這個(gè)來包裝下,個(gè)人認(rèn)為更優(yōu)雅,這一做法抄襲自donjuan的在WPF中使用ItemsControl控件來實(shí)現(xiàn)線狀圖控件(一)
drawingContext.PushTransform(new ScaleTransform(1, -1, 0, RenderSize.Height / 2)); … drawingContext.Pop();?
不爽的抄法
????? 在為點(diǎn)應(yīng)用模板的代碼中,最邪惡的應(yīng)該是以下的一段山寨成果,聲明這一坨真不是我的原創(chuàng),打這一段也打的我老郁悶了,具體可以參看ItemsContorl中的做法。
protected virtual void PrepareContainerForItemOverride(DependencyObject element, double item) {var headeredContentControl = element as HeaderedContentControl;if (headeredContentControl != null){headeredContentControl.Content = item;headeredContentControl.ContentTemplate = ItemTemplate;headeredContentControl.ContentTemplateSelector = ItemTemplateSelector;headeredContentControl.ContentStringFormat = ItemStringFormat;}else{var contentControl = element as ContentControl;if (contentControl != null){contentControl.Content = item;contentControl.ContentTemplate = ItemTemplate;contentControl.ContentTemplateSelector = ItemTemplateSelector;contentControl.ContentStringFormat = ItemStringFormat;}else{var contentPresenter = element as ContentPresenter;if (contentPresenter != null){contentPresenter.Content = item;contentPresenter.ContentTemplate = ItemTemplate;contentPresenter.ContentTemplateSelector = ItemTemplateSelector;contentPresenter.ContentStringFormat = ItemStringFormat;}else{var headeredItemsControl = element as HeaderedItemsControl;if (headeredItemsControl != null){headeredItemsControl.Header = item;headeredItemsControl.HeaderTemplate = ItemTemplate;headeredItemsControl.HeaderTemplateSelector = ItemTemplateSelector;headeredItemsControl.HeaderStringFormat = ItemStringFormat;}else{ItemsControl itemsControl;if (((itemsControl = element as ItemsControl) != null)){itemsControl.ItemTemplate = ItemTemplate;itemsControl.ItemTemplateSelector = ItemTemplateSelector;itemsControl.ItemStringFormat = ItemStringFormat;}}}}} }微軟的類似的代碼其實(shí)并不是最令人憤慨的,大批的internal才是令人反胃的,so,我也就一同copy了這風(fēng)格。
?
四.補(bǔ)充
?
?????? 對(duì)于折線圖的應(yīng)用還可以有線條的動(dòng)畫呈現(xiàn),點(diǎn)的動(dòng)畫變動(dòng),點(diǎn)的手動(dòng)拖拉,大數(shù)據(jù)虛擬化顯示等等,這些都可以發(fā)揮自己的想象做出更美好的作品,但您也可以抄襲一些現(xiàn)有的控件來達(dá)到需求。總之我們“學(xué)習(xí)”、“參考”都是希望有一天那些東西能夠?yàn)槲覀冃?/strong>,對(duì)于類似左邊圖上的效果也很容易抄襲得到。
?????? 如果您下了我的代碼,可能會(huì)發(fā)現(xiàn)所提供的控件,似乎“只可遠(yuǎn)觀不可褻玩”,很多功能貌似都被閹割了。比如:默認(rèn)陰影的兩頭只是簡(jiǎn)單的處理,陰影里沒有圓形的倒影,看起來不真實(shí),默認(rèn)的圓圈半徑和外框線當(dāng)值設(shè)大時(shí)會(huì)有問題(控件的Pen的Thickness的線的中點(diǎn)落在給定圓的半徑上,而不是在半徑外有Thickness),GroupName只處理了最大值而未處理最小值,PointLayer控件所產(chǎn)生的模板好像并未和原來的點(diǎn)重合,這么多控件有些方法居然沒有提成公用方法等等。首先我得承認(rèn)這些問題都是剛開始疏忽了,如果您能放棄那些控件而用自己的方式進(jìn)行山寨,改份更好的,BUG更少的,更易用的,我想您的心情會(huì)更好。
?????? 回顧這些年的程序員生涯,讓我感慨最深的就是復(fù)制和粘貼,從最初的Hello World到WPF的學(xué)習(xí),一路上就是Sample的抄襲和應(yīng)用,整個(gè)過程都是在別人路上進(jìn)行徘徊,模式是別人的,語言是別人的,用法也是別人規(guī)定的,跌撞中偶爾發(fā)現(xiàn)個(gè)技法,也是在使用別人的API下,日復(fù)一日我都產(chǎn)生了做軟件如同搭積木的消極想法。可其實(shí)人的物質(zhì)生活,思想文化又是怎么提高的呢?可以說是站立在偉人的肩膀上,也可以說是把別人發(fā)現(xiàn)的路拓展的更好的基礎(chǔ)上,生活也就在這一點(diǎn)點(diǎn)變化中,愈加美好。當(dāng)然,您得擁有一顆不滿現(xiàn)狀積極向上的心。
??????
PS:因抄襲產(chǎn)生的RP問題概不負(fù)責(zé),畢竟上個(gè)月俺已經(jīng)丟了飯卡一張,門進(jìn)卡一張,手機(jī)一部,手機(jī)卡補(bǔ)的時(shí)候還多花了30元。
附件? 盡管我們是同道中人,還是希望您不會(huì)再要刻度尺,因?yàn)槲乙矝]有^^
轉(zhuǎn)載于:https://www.cnblogs.com/Curry/archive/2010/04/02/LineChart.html
總結(jié)
以上是生活随笔為你收集整理的用WPF山寨折线图,抄?是狠狠的抄的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: F#与ASP.NET(1):基于事件的异
- 下一篇: .Net Validator验证框架 [