配置系統

更新:2007 年 11 月

本主題說明 Windows Presentation Foundation (WPF) 配置系統。在製作美觀又好用的使用者介面時,一定要了解配置計算的發生方式和時機。

本主題包含下列章節。

  • 配置系統

  • 項目週框方塊

  • 測量和排列子系

  • 面板項目和自訂配置行為

  • 配置效能考量

  • 下一步

  • 相關主題

配置系統

「配置」一詞是描述測量和排列 Panel 項目的 Children 集合成員,然後將它們繪製在畫面上的程序。這是一個密集的處理序,而且 Children 集合越大,計算次數就越多。根據擁有集合的 Panel 項目所定義的配置行為,也有可能會讓整個程序變得更複雜。不需要較複雜的 Panel (例如 Grid) 時,相對簡單的配置 (例如 Canvas) 可以產生絕佳的效能。

每次子 UIElement 變更它的位置時,配置系統就可能觸發新的傳遞。就這一點而論,重要的是了解可以叫用 (Invoke) 配置系統的事件,因為不必要的叫用可能會導致應用程式效能變差。

簡單來說,配置是一個遞迴系統,可以調整項目大小、定位項目以及將項目繪製在畫面上。配置系統會針對 Children 集合中的每個成員完成兩項傳遞:測量傳遞和排列傳遞。每個子 Panel 會提供它自己的 MeasureOverrideArrangeOverride 方法,以便達成它自己特有的配置行為。這就是每次叫用配置系統時所發生的一系列事件。

  1. UIElement 開始配置處理序的第一步,是先測量它的核心屬性。

  2. 接著評估定義於 FrameworkElement 的調整大小屬性,例如 WidthHeightMargin

  3. 然後套用 Panel 特定邏輯,例如 Dock 方向或堆疊 Orientation

  4. 測量所有子系之後,排列內容。

  5. Children 集合繪製到螢幕。

  6. 如果有其他 Children 加入至集合、套用 LayoutTransform,或呼叫 UpdateLayout 方法,則會再次叫用此處理序。

在後續的章節中,會更加詳細定義此處理序以及其叫用方法。

項目週框方塊

在考慮 Windows Presentation Foundation (WPF) 中的應用程式配置時,重要的是了解圍繞所有項目的週框方塊。此抽象概念有助於了解配置系統的行為。配置系統所取用的每個 FrameworkElement,都可視為已放入配置分割中的矩形。系統會公開 LayoutInformation 這個類別,它可以傳回項目配置的幾何界限,或位置。系統會計算可用的螢幕空間、任何條件約束 (Constraint) 的大小、配置特定屬性 (像是邊界與邊框距離),以及父 Panel 項目的個別行為,進而決定該矩形的大小。處理此資料後,系統即可計算指定之 Panel 的所有子系的位置。請務必記得,定義於父項目的調整大小特性 (例如 Border) 會影響其子系。

例如,請考量下列的簡單配置案例。

典型的 Grid,沒有週框方塊疊加於其上。

使用下列可延伸標記語言 (XAML),即可達成此配置。

<Grid Name="myGrid" Background="LightSteelBlue" Height="150">
  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="250"/>
  </Grid.ColumnDefinitions>
  <Grid.RowDefinitions>
    <RowDefinition />
    <RowDefinition />
    <RowDefinition />
  </Grid.RowDefinitions>
  <TextBlock Name="txt1" Margin="5" FontSize="16" FontFamily="Verdana" Grid.Column="0" Grid.Row="0">Hello World!</TextBlock>
  <Button Click="getLayoutSlot1" Width="125" Height="25" Grid.Column="0" Grid.Row="1">Show Bounding Box</Button>
  <TextBlock Name="txt2" Grid.Column="1" Grid.Row="2"/>
</Grid>

單獨的 TextBlock 項目是裝載在 Grid 中,而文字僅填滿所在欄位的左上角,所以 TextBlock 的配置空間實際上大很多。使用 GetLayoutSlot 方法,即可擷取任何 FrameworkElement 的週框方塊。使用這個方法,TextBlock 項目的週框方塊會重疊 (這是可行的,因為 TextBlock 裝載於 Grid 中,這是一個允許共用配置座標的 Panel 項目)。

現在可以看得到 TextBlock 的週框方塊。

圍繞的白線現在很明顯地指出,配置給 TextBlock 項目的分割實際上比它所填滿的空間大很多。隨著其他項目加入至 Grid,根據所加入項目的類型與大小而定,此配置可以縮減或擴大。

系統會使用 GetLayoutSlot 方法 (這是一種很適合用於顯示項目週框方塊的技術),傳回 TextBlock 的配置位置並將它轉譯成 Path

Private Sub getLayoutSlot1(ByVal sender As Object, ByVal e As RoutedEventArgs)
    Dim myRectangleGeometry As New RectangleGeometry
    myRectangleGeometry.Rect = LayoutInformation.GetLayoutSlot(txt1)
    Dim myGeometryDrawing As New GeometryDrawing
    Dim myPath As New Path
    myPath.Data = myRectangleGeometry
    myPath.Stroke = Brushes.LightGoldenrodYellow
    myPath.StrokeThickness = 5
    Grid.SetColumn(myPath, 0)
    Grid.SetRow(myPath, 0)
    myGrid.Children.Add(myPath)
    txt2.Text = "LayoutSlot is equal to " + LayoutInformation.GetLayoutSlot(txt1).ToString()
End Sub
private void getLayoutSlot1(object sender, System.Windows.RoutedEventArgs e)
{
    RectangleGeometry myRectangleGeometry = new RectangleGeometry();
    myRectangleGeometry.Rect = LayoutInformation.GetLayoutSlot(txt1);
    GeometryDrawing myGeometryDrawing = new GeometryDrawing();
    Path myPath = new Path();
    myPath.Data = myRectangleGeometry;
    myPath.Stroke = Brushes.LightGoldenrodYellow;
    myPath.StrokeThickness = 5;
    Grid.SetColumn(myPath, 0);
    Grid.SetRow(myPath, 0);
    myGrid.Children.Add(myPath);
    txt2.Text = "LayoutSlot is equal to " + LayoutInformation.GetLayoutSlot(txt1).ToString();
}

測量和排列子系

呈現 Window 物件的內容時,會自動叫用配置系統。為了要顯示內容,視窗的 Content 必須定義根 Panel,該項目可用於定義在螢幕上組織 Children 所依據的架構。請參閱面板項目和自訂配置行為,以取得可用 Panel 項目清單以及有關建立自訂配置項目的資訊。

配置的第一項傳遞為測量傳遞,會在其中評估 Children 集合的每個成員。此處理序一開始會呼叫 Measure 方法。此方法是在父 Panel 項目的實作內進行呼叫,而且不須明確地呼叫,配置即可發生。

首先,評估 UIElement 的原生大小屬性,例如 ClipVisibility。這會產生名稱為 constraintSize 的值,該值會傳遞至 MeasureCore

其次,處理定義於 FrameworkElement 的架構屬性,進而影響 constraintSize 的值。這些屬性主要用於描述基礎 UIElement 的調整大小特性,例如其 HeightWidthMarginStyle。而每個屬性都可以改變顯示項目所需的空間。接著,會以 constraintSize 當做參數來呼叫 MeasureOverride

注意事項:

HeightWidth 的屬性,與 ActualHeightActualWidth 的屬性之間有差異存在。例如,ActualHeight 屬性是根據其他高度輸入和配置系統所計算的值。該值是由配置系統本身根據實際呈現動作而設定,因此會稍微落在 Height 之類屬性 (此類屬性是輸入變更的基礎) 的設定值之後。

因為 ActualHeight 是計算而來的值,所以您應該注意,配置系統的各種作業可能會對此值產生眾多或累加的回報變更。配置系統可能正在計算子項目所需的測量空間、父項目的條件約束等。

發生於 MeasureCore 呼叫期間的測量傳遞,其最終目的是要讓子系決定其 DesiredSizeMeasure 會儲存此值,以供內容排列處理期間使用。

排列處理序一開始會呼叫 Arrange 方法。在排列動作期間,父 Panel 項目會產生可表示子系界限的矩形。此值會傳遞至 ArrangeCore 方法以供處理。

ArrangeCore 方法會評估子系的 DesiredSize 以及任何會影響項目呈現大小的其他邊界,並產生 arrangeSize,它可當做參數傳遞至 Panel 的 ArrangeOverrideArrangeOverride 會產生子系的 finalSize,而最後 ArrangeCore 方法會進行位移 (Offset) 屬性 (例如邊界和對齊方式) 的最終評估,然後將子系放在其配置位置中。子系並不需要 (而且經常不會) 填滿整個配置的空間。然後,將控制項傳回至父 Panel,即完成配置處理序。

面板項目和自訂配置行為

Windows Presentation Foundation (WPF) 包含一套衍生的 Panel 項目,可讓您建立許多複雜的配置。使用 StackPanel 項目即可輕易達成常見案例 (例如堆疊項目),而更複雜且自由流動的配置則可使用 Canvas 達成。

下表彙總可用的配置項目。

面板名稱

描述

Canvas

定義一塊區域,在這塊區域中,您可以使用相對於 Canvas 區域的座標,明確放置子項目。

DockPanel

定義一塊區域,在這塊區域中,您可以水平或垂直排列子項目之間的相對位置。

Grid

定義由資料行和資料列組成的彈性方格區域。

StackPanel

將子項目排列成可呈水平或垂直方向的單行。

VirtualizingPanel

Panel 項目提供架構,以「虛擬化」其子資料集合。這是個抽象類別 (Abstract Class)。

WrapPanel

將子項目從左到右依序放置,並在包含的方塊邊緣將內容中斷,換到下一行。之後的順序則依 Orientation 屬性值的不同,可能循序從上到下或從右到左。

如需用以顯示每個項目之使用方式的程式碼範例,請參閱配置範例

至於所需的應用程式配置不可能使用任何預先定義之 Panel 項目的案例,從 Panel 繼承並覆寫 MeasureOverrideArrangeOverride 方法,即可達成自訂配置行為。如需範例,請參閱自訂放射狀面板範例

配置效能考量

配置是個遞迴處理序。Children 集合中的每個子項目會在系統每次引動過程得到處理。因此,應避免在非必要時觸發系統。下列秘訣可協助您達到更高效能。

系統會以公用 (Public) 旗標標記其值會導致初始化配置系統的相依性屬性。至於哪些屬性值變更會強制配置系統進行遞迴更新,AffectsMeasureAffectsArrange 提供了實用的提示。一般而言,任何會影響項目週框方塊大小的屬性,都應將 AffectsMeasure 旗標設定為 true。如需詳細資訊,請參閱相依性屬性概觀

LayoutTransform 可以成為影響使用者介面 (UI) 內容的有用方法。但是,如果轉換的效果不需影響其他項目的位置,最好是改用 RenderTransform,因為 RenderTransform 不會叫用配置系統。LayoutTransform 會套用其轉換並強制執行遞迴配置更新,這麼做是為了考慮到受影響項目的新位置。

避免不必要的 UpdateLayout 呼叫。這個方法會強制執行遞迴配置更新,但經常是不必要的。除非您確定需要進行完全更新,否則就依賴配置系統替您呼叫此方法。

處理大型 Children 集合時,請考慮使用 VirtualizingStackPanel 而非一般的 StackPanel。藉由「虛擬化」子集合,VirtualizingStackPanel 只會記住目前在父代之 ViewPort 中的物件。因此,在大部分情況下都能大幅改善效能。

下一步

了解項目的測量和排列方式,就是有系統了解配置的第一步。若要深入了解可用的 Panel 項目,請參閱面板概觀。若要進一步了解各種會影響配置的定位屬性,請參閱對齊、邊界和填補概觀。如需自訂面板項目的範例,請參閱自訂放射狀面板範例。當您準備要在輕量 (Light-Weight) 應用程式中親身體驗時,請參閱 Windows Presentation Foundation 使用者入門

請參閱

概念

面板概觀

對齊、邊界和填補概觀

WPF 應用程式的像素快照

XAMLPad

最佳化效能:配置與設計

參考

FrameworkElement

UIElement