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