WPF面板自定義方法介紹
WPF作為一種方便使用的圖形界面顯示工具,幫助開發(fā)人員完成了許多工能。在WPF中,有很多種面板,比如Grid, StackPanel等,這讓我們的界面布局更加的靈活,但也許這些WCF面板并不能完全滿足你的需求,這時(shí)你需要自定義面板來滿足你的布局要求. #t#
1,WCF面板布局是如何實(shí)現(xiàn)的
WPF 布局引擎采用了一種遞歸的方式來實(shí)現(xiàn)控件及其子控件的布局,大致過程是這樣的:要實(shí)現(xiàn)控件A的布局,那么先要實(shí)現(xiàn)A的子控件a1,a2,a3...的布局,要實(shí)現(xiàn)a1的布局,那么得實(shí)現(xiàn)a1的子控件a11,a12,a13...的布局,如此循環(huán),然后但子控件的布局完成后,在完成父控件的布局,最后遞歸回去,遞歸結(jié)束,布局才算完成.
控件的最終大小和位置是由該控件和父控件相磋商來完成的,父控件先給出其能給予子控件的力所能及的布局空間,子控件在反饋給父控件一個(gè)自己的期望值,父控件最后根據(jù)自己所擁有的空間大小與子控件的期望值分配一定的空間給子控件并返回自己的大小.這一系列過程是通過重寫面板的MeasureOverride和ArrangeOverride方法來完成的.
2,Size MeasureOverride(Size availableSize)方法
該方法為WCF面板布局中控件所需要的空間大小進(jìn)行評(píng)估. 參考如下代碼:
- protected override
- Size MeasureOverride(Size
availableSize) {- Size childrenSize =
new Size(0, 0);- foreach (UIElement child in
this.Children) { child.Measure
(new Size(Double.PositiveInfinity
,Double.PositiveInfinity));
childrenSize.
Width += child.DesiredSize.Width;
childrenSize.Height += child.
DesiredSize.Height;- }
- return childrenSize;
- }
在MeasureOverride階段我們對(duì)WCF面板中的每個(gè)Child調(diào)用了其Measure(Size sz)方法,該方法的作用是父控件告訴子控件其預(yù)計(jì)要分配給子控件的空間大小,對(duì)Child調(diào)用了該Measure方法后,子控件會(huì)在其內(nèi)部給父控件一個(gè)回應(yīng)以便告訴父控件它所期望的大小,而子控件的該期望值便保存在其child.DesiredSize中.如果Measure方法中傳入的是正無窮大 (new Size(Double.PositiveInfinity,Double.PositiveInfinity))時(shí),相當(dāng)于父控件在對(duì)子控件說"盡管說出你所需要的大小吧,如果可以的話全世界都可以給你".
MeasureOverrice方法中的availableSize參數(shù)正是其父控件(你編寫的面板控件以后在實(shí)際使用時(shí)其父控件)對(duì)其調(diào)用Measure方法時(shí)傳入的值(減去一些邊界值,比如要減掉Margin等)
MeasureOverride方法的返回值正是其告訴其父控件的期望值,即是其父控件(你編寫的面板控件以后在實(shí)際使用時(shí)其父控件)對(duì)其調(diào)用Measure方法后,其DesiredSize值
注意:作為父控件,你可以很慈愛地僅可能地滿足子控件的需要(盡管不一定有這能力),所以可以在對(duì)子控件調(diào)用Measure方法時(shí)傳入一個(gè)正無窮大的尺寸, 但作為子控件,你不能貪婪地向父控件索要正無窮大的空間,所以我們不能將正無窮大作為MeasureOverride方法的返回值,也不能直接將該方法的 availableSize參數(shù)作為返回值(因?yàn)槟愕母缚丶锌赡軐⒄裏o窮大作為該參數(shù)傳遞給你)
3,Size ArrangeOverride(Size finalSize)方法
該方法作用在于為WCF面板子控件提供布局空間即排列子控件并返回自身大小,參考下面的代碼:
- protected override
- Size ArrangeOverride(Size
finalSize) {- Point childPos = new Point(0, 0);
- foreach (UIElement child in
this.Children)
{ child.Arrange(new Rect
(childPos, new
Size(child.DesiredSize.Width,
finalSize.
Height))); childPos.X += child.
RenderSize.Width;- }
- return finalSize;
- }
該方法對(duì)每個(gè)Child調(diào)用Arrange方法,Arrange方法中傳入的Rect結(jié)構(gòu)告訴子控件其被安排在那個(gè)空間內(nèi)進(jìn)行布局,然后子元素會(huì)根據(jù)自己得到的空間以及自己的對(duì)齊屬性(XXXAlignment)進(jìn)行放置,放置完成后子控件的大小等便得到了確定,而該值便存放在子控件的 RenderSize中(即是ActualWidth與ActualHeight).
控件本身也可以根據(jù)子控件占用的實(shí)際空間大小來決定自己的大小,也可以直接將得到的空間大小(即是ArrangeOverride方法中的finalSize參數(shù))作為自己的最終大小返回
ArrangeOverride方法中的finalSize參數(shù)是該控件的父控件(你編寫的面板控件以后在實(shí)際使用時(shí)其父控件)在對(duì)該控件調(diào)用Arrange方法時(shí)傳入的Rect的大小,正如該控件對(duì)其子控件調(diào)用Arrange方法一樣.
注意:Child的Arrange方法只是給定一個(gè)空間讓W(xué)CF面板子控件在此空間內(nèi)進(jìn)行擺放,該空間并沒有決定子控件的具體位置和大小,這還得取決于子控件的其它屬性,比如HorizontalAlignment與VerticalAlignment等. 在Arrange期間,系統(tǒng)會(huì)自動(dòng)進(jìn)行對(duì)齊(Alignment)操作.