您好,登錄后才能下訂單哦!
這篇“WPF怎么在VisualTree上增加Visual”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“WPF怎么在VisualTree上增加Visual”文章吧。
先從我遇到的一個典型的問題開始吧:寫一個MyElement類,要求如下:
從FrameworkElement繼承
增加一個Button到它的VisualTree上
在Visual上有一個AddVisualChild方法,相信很多剛接觸這個方法的同學們(好吧,至少我是這樣)都會“顧名思義”地認為這個方法就可以解決本文的問題。再加上MSDN上也給出了一個例子來“火上澆油”一把。于是,一陣竊喜之后,我興奮地敲出了以下代碼:
class MyElement : FrameworkElement { private Button _button = new Button() { Content = "I'm a Button!"}; public MyElement() { this.AssembleVisualChildren(); } private void AssembleVisualChildren() { this.AddVisualChild(this._button); } protected override int VisualChildrenCount { get { return 1; } } protected override Visual GetVisualChild(int index) { return this._button ; } }
然后將這個MyElement加入測試窗口,代碼如下:
<Window x:Class="AddVisualChildTest.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:loc="clr-namespace:AddVisualChildTest" WindowStartupLocation="CenterScreen" Title="Window1" Height="300" Width="300"> <Grid> <loc:MyElement Margin="10"/> </Grid> </Window>
運行后的結果如下:
空空如也!嗯,被忽悠了。一陣失落、打擊之后,我的好奇心被激發了:這是為什么呢?于是我狂找資料,終于被我發現了:
實際上,在上面這個例子中,AddVisualChild這個方法只是在MyElement和Button之間建立起了一種VisualTree上的父子關系,但是并沒有將Button掛接到MyElement的VisualTree上,所以最終我們沒有在屏幕上看到這個Button。
為了將Button真正掛接到MyElement的VisualTree上,還需要額外做一件事情:在VisualTree上為這個Button分配空間并且指定位置,這個過程叫做Layout。此過程分兩個部分:一個是Measure,另一個是Arrange。這兩個過程在FrameworkElement上對應著兩個方法:MeasureOverride和ArrangeOverride方法。具體做法如下:
protected override Size MeasureOverride(Size availableSize) { if (this.VisualChildrenCount > 0) { UIElement child = this.GetVisualChild(0) as UIElement; Debug.Assert(child != null); // !Assert child.Measure(availableSize); return child.DesiredSize; } return availableSize; } protected override Size ArrangeOverride(Size finalSize) { Rect arrangeRect = new Rect() { Width = finalSize.Width, Height = finalSize.Height }; if (this.VisualChildrenCount > 0) { UIElement child = this.GetVisualChild(0) as UIElement; Debug.Assert(child != null); // !Assert child.Arrange(arrangeRect); } return finalSize; }
再次運行程序:
目標實現。
由此,我們可以總結出這個問題的解決方案如下:
在MyElement的構造器中調用AddVisualChild方法;
重寫VisualChildCount屬性;
重寫GetVisualChild方法;
重寫MeasureOverride方法;
重寫ArrangeOverride方法;
另外,WPF在此問題的解決上也為開發者提供了一些必要的幫助。就我所知的,有如下幾個內容:
還是本文開始提到的問題,只不過要將其中的FrameworkElement換為Panel。除了上面所提到的方法,Panel為我們提供了更加方便的實現方式。代碼如下:
class MyElement : Panel { private Button _button = new Button() { Content = "I'm a Button!" }; public MyElement() { this.Children.Add(_button); } protected override Size MeasureOverride(Size availableSize) { if (this.VisualChildrenCount > 0) { UIElement child = this.GetVisualChild(0) as UIElement; Debug.Assert(child != null); // !Assert child.Measure(availableSize); return child.DesiredSize; } return availableSize; } protected override Size ArrangeOverride(Size finalSize) { Rect arrangeRect = new Rect() { Width = finalSize.Width, Height = finalSize.Height }; if (this.VisualChildrenCount > 0) { UIElement child = this.GetVisualChild(0) as UIElement; Debug.Assert(child != null); // !Assert child.Arrange(arrangeRect); } return finalSize; } }
之所以能這樣做的原因是Panel已經替我們將如下幾個工作封裝在了UIElementCollection(Panel的Children屬性)中:
AddVisualChild
VisualChildCount
GetVisualChild
另外,在這個過程中,我們還可以使用一個叫做VisualCollection的類來作為所有 Visual Child的容器。這個容器構造的時候需要一個Visual類型的Parent,然后在添加、刪除Visual Child的時候,它的相應方法(Add,Remove)就會幫助我們自動調用Parent的AddVisualChild和RemoveVisualChild方法。
以上就是關于“WPF怎么在VisualTree上增加Visual”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。