第 3 章:控制項和 XAML
簡介
第 1 章:「Longhorn」 應用程式模型
第 2 章:建置 「Longhorn」 應用程式
第 3 章:控制項和 XAML
Brent Rector
明智的 Owl 諮詢
2003 年 12 月
目錄
XAML 元素
XAML 面板
控制項
資源和樣式
圖形和動畫
檔服務
總結
如您在第 2 章中所見,Longhorn 平臺應用程式通常由 Application 物件和一組使用者介面頁面所組成,這些頁面是以稱為 XAML 的宣告式標記語言撰寫。
Application物件是單一物件,會在應用程式的存留期內持續存在。 它可讓您的應用程式邏輯處理最上層事件,並在頁面之間共用程式碼和狀態。 Application物件也會判斷應用程式是單一視窗應用程式還是導覽應用程式。
您通常會使用名為 Extensible Application Markup Language (XAML) 的 XML 方言來撰寫每個使用者介面頁面。 每個頁面都包含 XAML 元素、文位元組點,以及組織在階層式樹狀結構中的其他元件。 這些元件的階層式關聯性會決定頁面呈現和行為的方式。
您也可以將 XAML 頁面視為物件模型的描述。 當執行時間建立頁面時,它會具現化 XAML 檔中所述的每個元素和節點,並在記憶體中建立對等的物件模型。 您可以以程式設計方式操作此物件模型,例如,您可以新增和移除元素和節點,讓頁面呈現和行為不同。
基本上,XAML 頁面描述執行時間應該建立的類別、類別的屬性值和事件處理常式,以及物件模型階層,也就是哪個實例是另一個實例的父系。
所有 XAML 檔都是格式正確的 XML 檔,可使用一組定義的專案名稱。 因此,有關格式正確 XML 檔的所有規則都同樣適用于 XAML 檔。 例如,檔必須包含單一根項目;所有專案名稱都會區分大小寫;專案定義不能與另一個元素定義重迭,但必須完全包含它等等。 如果您不熟悉 XML 語法,現在是學習它的絕佳時機。
XAML 元素
每個 XAML 頁面都包含一或多個 元素 ,可控制頁面的配置和行為。 您會在樹狀結構中以階層方式排列這些元素。 每個元素只有一個父代。 元素通常可以有任意數目的子專案。 不過,某些元素類型,例如 Scrollbar,沒有子系;和其他元素類型,例如 Border,可以有單一子項目。
每個元素名稱都會對應至 Managed 類別的名稱。 將專案新增至 XAML 檔會導致執行時間建立對應類別的實例。 例如,下列標記代表具有單一子Table元素的根DockPanel元素。 Table元素包含三個子Row元素。 每個 Row 元素都包含三個子系,其中一些子系具有子文位元組點。
<Border xmlns="https://schemas.microsoft.com/2003/xaml"
Background="BlanchedAlmond">
<DockPanel>
<Table>
<Body>
<Row>
<Cell><Button/></Cell>
<Cell><Text>Item</Text></Cell>
<Cell><Text>Price</Text></Cell>
</Row>
<Row>
<Cell><CheckBox Checked="true"/></Cell>
<Cell><TextBox Height="50">Nissan 350Z</TextBox></Cell>
<Cell><TextBox Height="50">29.95</TextBox></Cell>
</Row>
<Row>
<Cell><CheckBox/></Cell>
<Cell><TextBox Height="50">Porsche Boxster</TextBox></Cell>
<Cell><TextBox Height="50">9.95</TextBox></Cell>
</Row>
</Body>
</Table>
</DockPanel>
</Border>
此 XAML 檔會建立物件階層,如圖 3-1 所示,如圖 3-2 所示。
圖 3-1。 範例 XAML 頁面物件模型
圖 3-2. 上一個 XAML 的顯示 (按一下以取得較大的影像)
您可以使用標記來存取這類物件的大部分功能。 僅使用標記,您可以執行下列任一動作:
- 描述執行時間將具現化的階層式物件集
- 將物件屬性設定為以靜態方式已知的值
- 將物件屬性設定為從資料來源擷取的值
- 將變更的屬性值儲存回資料來源
- 重複變更一段時間的屬性值
- 將事件處理常式系結至物件的事件
不過,雖然您可以只使用標記來建立一些令人讚歎的使用者介面,但您也可以使用 XAML 物件模型以程式設計方式存取元素的功能。 物件模型可讓您動作頁面上元素的每個層面。 它實際上提供無法透過 XAML 存取的其他功能。
每個 XAML 元素都衍生自 System.Windows.UIElement 或 System.Windows.ContentElement,因此所有元素都有一些通用功能。 元素可以群組在下列四個基本類別中:
- 控制項 衍生自 System.Windows.Control 並處理使用者互動。
- 面板 是衍生自 System.Windows.Panel 的特殊控制項,並處理頁面配置,並作為元素的容器。
- 文字格式設定元素 衍生自 System.Windows.TextElement ,並處理文字格式設定和檔結構。
- 圖形 會處理向量圖形圖形。
XAML 面板
XAML 頁面通常以面板元素開始。 面板是頁面內容的容器,可控制該內容的位置和轉譯。 事實上,當您使用 XAML 顯示任何專案時,面板一律會牽涉到,但有時候是隱含的,而不是明確描述的面板。 面板可以包含其他面板,讓您將顯示介面分割成區域,每個區域都是由其面板所控制。
Longhorn 平臺中有六個內建 的 Panel 類別:
- Canvas會使用相對於 Canvas區域的座標來明確放置每個子專案。
- DockPanel會將其子系放在面板的上、下、左、右或中央。 當您將多個子系指派給相同的區域時, DockPanel 會在該區域內水準或垂直排列它們。
- FlowPanel會根據其換行和對齊屬性來排列其子項目。 當內容超過單行的長度時,面板會中斷行、換行行,並適當地對齊內容。
- TextPanel會以多個文字格式轉譯多行文字。 只有在需要複雜的文字配置時,您才會使用它。 在大部分情況下,您將使用輕量型 Text 元素來支援基本文字。
- GridPanel是輕量型元素,會將其子項目排列在形成格線的資料列和資料行中。 它很適合用來建立簡單資料表,但功能有限。 您會使用 資料表 控制項進行複雜的資料表配置。
- FixedPanel會將其子項目放在固定版面配置頁面上。 固定版面配置頁面上的元素一律具有相同的位置和分頁,不論裝置解析度或視窗大小為何。
一般而言,這些面板會為大部分開發人員提供足夠的功能。 不過,您也可以建立自己的面板類別,以特殊方式定位和顯示內容。
畫布
[畫布 ] 面板提供相當多的彈性,以在畫面上定位和排列元素。 它可讓您指定每個子專案的位置,而且當元素重迭時,您可以藉由變更專案出現在標記中的順序,指定畫布繪製重迭元素的順序。
下列標記會產生三個重迭的圖形,如圖 3-1 所示:綠色矩形具有橙色框線、藍色框線的半透明黃色橢圓形,以及矩形中置中的一些文字。 (從未再撰寫WM_PAINT處理常式,以繪製類似這樣的內容,會將眼部卸載。 。我快要新增的快樂!) 架構會依呈現的順序繪製圖形,因此文字會出現在矩形上。
<Canvas xmlns="https://schemas.microsoft.com/2003/xaml" >
<Rectangle
Fill="#33CC66"
Width="2in" Height="1in"
Canvas.Top="25" Canvas.Left="50"
StrokeThickness="6px" Stroke="Orange" />
<Ellipse
Fill="yellow"
CenterX="1.5in" CenterY="1.1in"
RadiusX=".5in" RadiusY="1in"
StrokeThickness="4px" Stroke="Blue" />
<Text
Canvas.Top="50" Canvas.Left="60" Foreground="#000000"
FontWeight="Bold" FontFamily="Arial"
FontStyle="Normal" FontSize="25">Hello Shapes!</Text>
</Canvas>
圖 3-3. 使用換行面板的範例
DockPanel
DockPanel 面板會以水準或垂直方式排列子專案,彼此相對。 DockPanel類別會檢查每個子專案的Dock屬性,以判斷如何沿著面板邊緣對齊專案。 您可以將 Dock 屬性設定為五個值的其中一個: Top、 Bottom、 Left、 Right或 Fill。
例如,面板會將第一個子項目與其 Dock 屬性 對齊,使其 與面板的上邊緣相等。 然後面板會將下一個子項目與其 Dock 屬性對齊在先前元素正下方的 Top 。 面板同樣會將子項目與其 Dock 屬性設定為 Bottom、 Left 或 Right對齊。 將最後一個子項目的 Dock 屬性設定為 Fill 會導致它佔用 DockPanel中的所有剩餘空間。 永不遵循 Dock=「Fill」 元素與其他元素,因為後續元素將不會顯示。 Dock屬性的預設值為Left,因此當您未設定元素的Dock屬性時,它會水準堆疊到左邊。
Dock屬性是附加屬性,它是由DockPanel類別所定義,但您會在子項目上設定它,如下所示:
<child DockPanel.Dock="Top"/>
或在程式碼中:
DockPanel.SetDock(child, Dock.Top)
下列標記使用 DockPanel 和五個 Canvas 面板來建立常用的使用者介面。 DockPanel會對齊DockPanel頂端的前兩個畫布。 它會將第三個畫布對齊 DockPanel的下邊緣、第四個與左邊緣對齊,第五個畫布會填滿剩餘的空間。 您可以將功能表放在頂端面板中,並將工具列放在功能表正下方的面板中。 此決策會保留樹狀檢視的左面板、狀態列的底部面板,以及詳細選取專案檢視的剩餘面板,如圖 3-4 所示。
<Border xmlns="https://schemas.microsoft.com/2003/xaml"
Background="White">
<DockPanel>
<Border Width="500" DockPanel.Dock="Top"
BorderThickness="2,2,2,2" BorderBrush="Black" Background="#87ceeb" >
<Text>Dock = "Top"</Text>
</Border>
<Border Width="500" DockPanel.Dock="Top"
BorderThickness="2,2,2,2" BorderBrush="Black" Background="#87ceeb" >
<Text>Dock = "Top"</Text>
</Border>
<Border Width="500" DockPanel.Dock="Bottom"
BorderThickness="2,2,2,2"
BorderBrush="Black" Background="#ffff99" >
<Text>Dock = "Bottom"</Text>
</Border>
<Border Width="200" DockPanel.Dock="Left"
BorderThickness="2,2,2,2" BorderBrush="Black" Background="#98fb98" >
<Text>Dock = "Left"</Text>
</Border>
<Border Width="300" DockPanel.Dock="Fill"
BorderThickness="2,2,2,2" BorderBrush="Black" Background="White" >
<Text>Dock = "Fill"</Text>
</Border>
</DockPanel>
</Border>
圖 3-4. 使用 DockPanel 面板的範例
FlowPanel
FlowPanel 面板提供許多自動版面配置功能,並允許複雜的文字和圖形呈現。 您可以使用面板的 Width 和 Height 屬性來定義面板的大小。 然後面板會以最適合面板空間的方式顯示其子項目,並視需要包裝和對齊元素。 FlowPanel的預設流程方向是從左至右和由上至下。
下列標記範例示範 FlowPanel 如何中斷和包裝內容。 FlowPanel包含四個一英吋平方畫布。 FlowPanel會嘗試向左到右和由上至下顯示其子項目。
<Border xmlns="https://schemas.microsoft.com/2003/xaml" Background="White">
<FlowPanel>
<Border Background="Red" Width="1in" Height="1in"/>
<Border Background="Green" Width="1in" Height="1in"/>
<Border Background="Blue" Width="1in" Height="1in"/>
<Border Background="Yellow" Width="1in" Height="1in"/>
</FlowPanel>
</Border>
圖 3-3 顯示 當 FlowPanel 可以容納單行上所有元素時的輸出。 圖 3-4 示範將最後一個專案換行到新行的 FlowPanel 。 圖 3-5 顯示 FlowPanel 必須將每個元素放在其本身行的最差案例。 圖 3-6 顯示最後一個專案換行到新行,圖 3-7 顯示每個元素換行到新行。
圖 3-5. FlowPanel 只會在必要時中斷行。
圖 3-6: 將最後一個專案換行到新行的 FlowPanel 面板
圖 3-7: FlowPanel 面板會將每個元素換行到新行
TextPanel
TextPanel 面板會格式化、大小及繪製文字。 此面板類別支援多行文字以及多個文字格式。 當您需要複雜的版面配置支援時,通常會使用 TextPanel 類別。 不過,當您只需要簡單的文字顯示時,最好改用 Text 元素。
下列標記範例示範 TextPanel 如何中斷和包裝內容。 TextPanel會在調整視窗大小時調整每個資料行的資料行數目和高度。
<Border xmlns="https://schemas.microsoft.com/2003/xaml" Background="White">
<TextPanel
ColumnCount="3"
ColumnWidth="200px"
ColumnGap="25px"
ColumnRuleWidth="5px"
ColumnRuleBrush="blue">
<Block Background="LightGray">
<Inline FontFamily="Arial" FontWeight="Bold"
FontSize="16pt">Transcript of the
<Italic>Nicolay Draft</Italic>
of the Gettysburg Address.
</Inline>
</Block>
§
</TextPanel>
</Border>
圖 3-8 顯示產生的輸出。
圖 3-8: 具有多個字型特性、資料行和格式設定的 TextPanel
GridPanel
GridPanel 面板會顯示表格式資料。 GridPanel支援許多屬性,可用來自訂表格格式資料的版面配置。 例如,您可以設定 Columns 和Rows 屬性來控制方格中的資料行和資料列數目。 同樣地, ColumnStyles 和 RowStyles 屬性可讓您設定 GridPanel 分別套用至資料列和資料行的屬性集合。
GridPanel 會依序排列其子系,從左上方儲存格開始,並移至右邊直到資料列結尾為止。 如果您在子系上設定 GridPanel.ColumnSpan 屬性,子系可以接受多個資料行。 同樣地, GridPanel.RowSpan 可讓子系跨越多個資料列。
下列標記會顯示與 Windows 計算機公用程式相當類似的計算機使用者介面。
<Border xmlns="https://schemas.microsoft.com/2003/xaml" Background="#DEE7F7">
<DockPanel Dock="Left">
<Border BorderThickness="0,0,0,0">
<!-- Padding="10, 10, 10, 10" -->
<GridPanel Columns="7">
<GridPanel.ColumnStyles>
<Column Width="16%"/>
<Column Width="4%"/>
<Column Width="16%"/>
<Column Width="16%"/>
<Column Width="16%"/>
<Column Width="16%"/>
<Column Width="16%"/>
</GridPanel.ColumnStyles>
<GridPanel.RowStyles>
<Row Height="25"/>
<Row Height="10"/>
<Row Height="35"/>
<Row Height="7"/>
<Row Height="35"/>
<Row Height="35"/>
<Row Height="35"/>
<Row Height="35"/>
</GridPanel.RowStyles>
<Border GridPanel.ColumnSpan="7" BorderBrush="#DEE7F7"
BorderThickness="2,2,2,2" Background="White">
<Text HorizontalAlignment="right"
ID="CalcText">0.</Text>
</Border>
<Text GridPanel.ColumnSpan="7"/>
<Border BorderThickness="0,0,0,0">
<GridPanel>
<Border BorderBrush="#DEE7F7" BorderThickness="2,2,2,2">
<Text Width="16%"
HorizontalAlignment="center"></Text>
</Border>
</GridPanel>
</Border>
<Text Width="4%"/>
<DockPanel GridPanel.ColumnSpan="5" Dock="Left">
<Button Width="33.33%" Foreground="Red">Backspace</Button>
<Button Width="33.33%" Foreground="Red">CE</Button>
<Button Width="33.33%" Foreground="Red">C</Button>
</DockPanel>
<Text GridPanel.ColumnSpan="7"/>
<Button Foreground="Red">MC</Button>
<Text/>
<Button Foreground="Blue">7</Button>
<Button Foreground="Blue">8</Button>
<Button Foreground="Blue">9</Button>
<Button Foreground="Red">/</Button>
<Button Foreground="Blue">sqrt</Button>
<Button Foreground="Red">MR</Button>
<Text/>
<Button Foreground="Blue">4</Button>
<Button Foreground="Blue">5</Button>
<Button Foreground="Blue">6</Button>
<Button Foreground="Red">*</Button>
<Button Foreground="Blue">%</Button>
<Button Foreground="Red">MS</Button>
<Text/>
<Button Foreground="Blue">1</Button>
<Button Foreground="Blue">2</Button>
<Button Foreground="Blue">3</Button>
<Button Foreground="Red">-</Button>
<Button Foreground="Blue">1/x</Button>
<Button Foreground="Red">M+</Button>
<Text/>
<Button Foreground="Blue">0</Button>
<Button Foreground="Blue">+/-</Button>
<Button Foreground="Blue">.</Button>
<Button Foreground="Red">+</Button>
<Button Foreground="Red">=</Button>
</GridPanel>
</Border>
</DockPanel>
</Border>
圖 3-9 顯示產生的輸出。
圖 3-9。 GridPanel 作為計算機
FixedPanel
FixedPanel 面板可讓您指定每個元素的確切位置和大小。 FixedPanel上的元素一律會顯示在所有裝置上相同的位置和大小。 我稍後會在一節中討論 FixedPanel 面板。
控制項
XAML 具有您從 Windows 預期的所有控制項—按鈕、核取方塊、選項按鈕、清單方塊、下拉式方塊、功能表、捲軸、滑杆等等。 此範例示範 Longhorn 中提供的一些常見控制項。 您可以在圖 3-10 中看到結果。
<Border
xmlns="https://schemas.microsoft.com/2003/xaml"
xmlns:def="Definition"
Background="BlanchedAlmond"
>
<DockPanel>
<Menu DockPanel.Dock="Top">
<MenuItem Header="File">
<MenuItem Header="New" />
<MenuItem Header="Open" />
</MenuItem>
<MenuItem Header="Edit">
<MenuItem Header="Cut"/>
<MenuItem Header="Copy"/>
<MenuItem Header="Paste"/>
</MenuItem>
</Menu>
<FlowPanel>
<Button> Button </Button>
<Border Width="15"/>
<CheckBox Checked="true"> CheckBox </CheckBox>
<Border Width="15"/>
<RadioButtonList>
<RadioButton> RadioButton 1 </RadioButton>
<RadioButton Checked="true"> RadioButton 2 </RadioButton>
<RadioButton> RadioButton 3 </RadioButton>
</RadioButtonList>
<Border Width="15"/>
<ListBox>
<ListItem> ListItem 1 </ListItem>
<ListItem> ListItem 2 </ListItem>
<ListItem> ListItem 3 </ListItem>
</ListBox>
<Border Width="15"/>
<ComboBox>
<ListItem> ListItem 1 </ListItem>
<ListItem> ListItem 2 </ListItem>
<ListItem> ListItem 3 </ListItem>
</ComboBox>
<Border Width="15"/>
<DockPanel>
<VerticalSlider DockPanel.Dock="Top" Height="200"
Minimum="0" Maximum="255" Value="75"
SmallChange="1" LargeChange="16"/>
<Text DockPanel.Dock="Bottom">Slider</Text>
</DockPanel>
<Border Width="15"/>
<DockPanel>
<VerticalScrollBar DockPanel.Dock="Top"
Minimum="0" Maximum="255" Value="125" Height="200"
SmallChange="1" LargeChange="16"/>
<Text DockPanel.Dock="bottom">ScrollBar</Text>
</DockPanel>
<Border Width="15"/>
<TextBox> TextBox </TextBox>
</FlowPanel>
</DockPanel>
</Border>
圖 3-10。 XAML 控制項的範例
XAML 也可讓您結合元素和控制項來建立豐富的效果。 我們稱之為結合專案 控制群組合,它是 Longhorn 最強大的層面之一。 例如,若要建立具有影像的按鈕,請將 Image 元素放在 Button內:
<Button>
<Image Source="tulip.jpg"/>
</Button>
若要在 Button中同時擁有影像和文字,如圖 3-11 所示,我們使用舊的 Friend DockPanel:
<Button>
<DockPanel>
<Image Source="tulip.jpg"/>
<Text DockPanel.Dock="fill" VerticalAlignment="center"> Button
<Italic>with Image!</Italic>
</Text>
</DockPanel>
</Button>
圖 3-11。 具有影像和文字的按鈕
您可以在任何專案內放置許多專案,包括Button內CheckBox的這個奇怪範例:
<Button>
<CheckBox Checked="true"> CheckBox </CheckBox>
</Button>
組合功能強大,因此許多 Longhorn 控制項實際上都使用組合來定義。 例如, ScrollBar 實際上是兩個按鈕和一個滑杆,再加上一些事件處理常式邏輯來將它們連結在一起。
XAML 也包含一些控制項「基本類型」,主要與控制群組合搭配使用,以建置較大的效果。 例如, ScrollViewer 會採用一個子系 (通常會) 面板,並在其中新增捲軸。 本範例會將非常大型的 CheckBox元素清單放在ScrollViewer內,在 Longhorn 之前需要個別的控制項,例如 Windows Forms 的CheckedListBox:
<Border BorderThickness="1" BorderBrush="black">
<ScrollViewer Height="100" Width="200">
<GridPanel Columns="1">
<CheckBox Checked="true"> CheckBox 1</CheckBox>
<CheckBox Checked="true"> CheckBox 2</CheckBox>
<CheckBox Checked="true"> CheckBox 3</CheckBox>
<CheckBox Checked="true"> CheckBox </CheckBox>
<CheckBox Checked="true"> CheckBox </CheckBox>
<CheckBox Checked="true"> CheckBox </CheckBox>
<CheckBox Checked="true"> CheckBox </CheckBox>
<CheckBox Checked="true"> CheckBox </CheckBox>
</GridPanel>
</ScrollViewer>
</Border>
資源和樣式
XAML 提供非常豐富的功能,可讓您透過稱為樣式的實體來自訂應用程式的外觀。 不過,在進入本主題之前,我們需要瞭解 資源。 此內容中使用的 資源 一詞只是參考重複使用常用物件和值的方式。 讓我們看看以下範例:
<Border
xmlns="https://schemas.microsoft.com/2003/xaml"
xmlns:def="Definition"
Background="BlanchedAlmond"
>
<FlowPanel>
<FlowPanel.Resources>
<SolidColorBrush def:Name="MyColor" Color="Gold"/>
</FlowPanel.Resources>
<Button Background="{MyColor}"/>
<Ellipse Fill="{MyColor}"/>
</FlowPanel>
</Border>
此程式碼會定義名為 MyColor的新資源,其類型為 SolidColorBrush 且值為 Gold。 此資源是 FlowPanel的 Resources 集合的一部分。 每個元素都有 Resources 集合。 您可以在任何您想要的元素上定義資源,但通常只會將它們放在根項目上,在此案例中為 FlowPanel。
定義資源之後,您就可以藉由將資源名稱放在大括弧中,以參考屬性值中的資源,如下所示:
<Button Background="{MyColor}"/>
當 XAML 處理器在此範例中看到 {MyColor} 時,它會先檢查按鈕的 Resources 集合。 因為 Button 沒有 MyColor 的定義 (其 Resources 集合是空的) ,所以它會檢查 Button的父系- -FlowPanel。
其中一種特別有用的資源是 Style。 Style 是類別的名稱,以及所有元素都有的屬性名稱。 Style會定義在元素上設定的屬性,然後使用該指定的樣式。 此範例會定義名為MyStyle的Style,並將該樣式套用至按鈕:
<Border
xmlns="https://schemas.microsoft.com/2003/xaml"
xmlns:def="Definition"
Background="BlanchedAlmond"
>
<FlowPanel>
<FlowPanel.Resources>
<Style def:Name="MyStyle">
<Button Background="Red" FontSize="24"/>
</Style>
</FlowPanel.Resources>
<Button>Normal</Button>
<Button Style="{MyStyle}">Styled</Button>
</FlowPanel>
</Border>
您也可以定義沒有名稱的 Style 資源,這會成為您未指定明確 Style 屬性之元素的預設 樣式 。 本範例會將預設樣式新增至上述範例:
<Border
xmlns="https://schemas.microsoft.com/2003/xaml"
xmlns:def="Definition"
Background="BlanchedAlmond"
>
<FlowPanel>
<FlowPanel.Resources>
<Style>
<Button Background="Green" FontSize="15"/>
</Style>
<Style def:Name="MyStyle">
<Button Background="Red" FontSize="24"/>
</Style>
</FlowPanel.Resources>
<Button>Normal</Button>
<Button Style="{MyStyle}">Styled</Button>
</FlowPanel>
</Border>
您可以藉由設定Style類別的BasedOn屬性來執行一種樣式繼承。 參考新的 Style 類別將會設定舊 Style 執行的所有屬性,以及您指定的其他屬性。 下列範例會定義兩個樣式:第一個會設定 Background 屬性,而第二個則根據第一個設定 FontSize 屬性。
<Border
xmlns="https://schemas.microsoft.com/2003/xaml"
xmlns:def="Definition"
Background="BlanchedAlmond"
>
<FlowPanel>
<FlowPanel.Resources>
<Style def:Name="Style1">
<Button Background="Red"/>
</Style>
<Style def:Name="Style2" BasedOn="{Style1}">
<Button FontSize="24"/>
</Style>
</FlowPanel.Resources>
<Button Style="{Style1}">Style 1</Button>
<Button Style="{Style2}">Style 2</Button>
</FlowPanel>
</Border>
使用稱為屬性觸發程式的功能,甚至可以讓 Style有條件地設定屬性。 Style 具有名為 VisualTriggers的屬性,這是 PropertyTriggers的集合。 每個 PropertyTrigger 都會使用 Property 和 Value 屬性來指定條件,並包含 Set 語句的集合。 當樣式專案的 屬性符合該值時,會套用 Set 語句,而且當條件不再為 true 時,這些值會取消套用,就像一開始從未設定值一樣。 本範例使用屬性觸發程式,在滑鼠位於按鈕上方時讓按鈕變成綠色,否則為紅色:
<Border
xmlns="https://schemas.microsoft.com/2003/xaml"
xmlns:def="Definition"
Background="BlanchedAlmond"
>
<FlowPanel>
<FlowPanel.Resources>
<Style def:Name="Style1">
<Button Background="Red"/>
<Style.VisualTriggers>
<PropertyTrigger Property="IsMouseOver" Value="true">
<Set PropertyPath="Background" Value="Green"/>
</PropertyTrigger>
</Style.VisualTriggers>
</Style>
</FlowPanel.Resources>
<Button Style="{Style1}">Style 1</Button>
</FlowPanel>
</Border>
許多 XAML 控制項都使用控制群組合。 它們結合了一些較小的控制項,以建立較大型且更複雜的控制項。 樣式甚至可讓您變更! 藉由指定不同的組合,您可以完全重新定義控制項的外觀,同時仍保留其行為。
宣告樣式專案及其屬性之後,< Style.VisualTree >標籤會在Style內指定要撰寫的元素以建立較大的控制項。 您可以像往常一樣設定子項目的屬性,並提供給自己子系的子系。 您也可以使用屬性別名來設定屬性值。 例如, Name1=「*Alias (Target=Name2) 」 會將子系的 Name1 屬性設定為較大的控制項 Name2 屬性。 下列範例會建立 Button 的樣式,以變更組合以達到圓形外觀,如圖 3-12 所示。 按鈕的 Background 和 Content 屬性會以視覺化樹狀結構中的適當點別名。
<Border Background="white"
xmlns="https://schemas.microsoft.com/2003/xaml"
xmlns:def="Definition">
<FlowPanel>
<FlowPanel.Resources>
<Style def:Name="RoundButton">
<Button FontSize="20"/>
<Style.VisualTree>
<Canvas>
<Rectangle ID="MainRect"
RadiusX="10" RadiusY="10"
Fill="*Alias(Target=Background)"
Width="100%" Height="100%" />
<FlowPanel Width="100%" Height="100%" >
<ContentPresenter
ContentControl.Content="*Alias(Target = Content)"
Margin="15,3,15,5"/>
</FlowPanel>
</Canvas>
</Style.VisualTree>
</Style>
</FlowPanel.Resources>
<Button Style="{RoundButton}">
standard RoundButton
</Button>
<Button Background="red" Style="{RoundButton}">
red RoundButton
</Button>
<Button>
standard button
</Button>
<Button Background="red">
red standard button
</Button>
</FlowPanel>
</Border>
圖 3-12. FlowPanel 上的幾個 RoundButton 和標準按鈕
圖形和動畫
XAML 提供廣泛的繪圖圖形支援、轉換物件的狀態,以及幾乎以動畫顯示物件的任何屬性。 您可以使用 Shape 元素來繪製、 轉換 專案來改變屬性或物件,以及 動畫 元素,以在一段時間內變更物件的屬性。
圖形
XAML 提供一組 圖形元素以供 繪製,其中包括 橢圓形、 線條、 矩形、 路徑、 多邊形和 Polyline。 圖形具有Fill,這是背景色彩,而Stroke則是外框色彩。 填滿 和 筆觸 預設為透明,因此請確定您至少設定其中一個! StrokeWidth屬性會控制外框的粗細。
圖形不能有子項目。 您通常會將圖形放在 Canvas內,因此標記中的第一個圖案會是繪製的第一個圖形。 此範例說明一些基本圖形,您也可以在圖 3-13 中看到:
<Border
xmlns="https://schemas.microsoft.com/2003/xaml"
xmlns:def="Definition"
Background="BlanchedAlmond"
>
<Canvas Height="400" Width="400">
<Ellipse CenterX="70" CenterY="75"
RadiusX="30" RadiusY="50"
Fill="yellow" Stroke="red" StrokeThickness="15"/>
<Rectangle RectangleLeft="150" RectangleTop="20"
RectangleHeight="100" RectangleWidth="40"
Fill="lightBlue" Stroke="green"/>
<Line X1="20" Y1="220" X2="150" Y2="240"
Stroke="black" StrokeThickness="5"/>
<Polygon Points="220,140 270,240 170,240"
StrokeLineJoin="Round"
Stroke="black" StrokeThickness="20"/>
</Canvas>
</Border>
圖 3-13。 畫布上的各種圖形
到目前為止,我們只使用純色搭配 Stroke 和 Fill 屬性。 但在 XAML 中,您幾乎可以在任何位置使用可指定 Brush的色彩。 SolidColorBrush 是我們目前使用的筆刷類型,但 XAML 也支援 ImageBrush、 LinearGradientBrush和 RadialGradientBrush。 ImageBrush 具有 ImageSource 屬性,指定影像檔的名稱。 SolidColorBrush 具有 Color 屬性。 LinearGradientBrush 和 RadialGradientBrush 包含 GradientStopCollection,其允許非常複雜的漸層。 本範例會將四個筆刷定義為資源,並使用它們做為省略號的 Stroke 和 Fill 。 您可以在圖 3-14 中看到它們的外觀。
<Border
xmlns="https://schemas.microsoft.com/2003/xaml"
xmlns:def="Definition"
Background="BlanchedAlmond"
>
<Border.Resources>
<LinearGradientBrush def:Name="lineargradient" StartPoint="0,0"
EndPoint="1,1" >
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="Blue" Offset="0"/>
<GradientStop Color="white" Offset="1"/>
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
<RadialGradientBrush def:Name="radialgradient" Focus="0.3,0.3">
<RadialGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="red" Offset="0"/>
<GradientStop Color="yellow" Offset="1"/>
</GradientStopCollection>
</RadialGradientBrush.GradientStops>
</RadialGradientBrush>
<ImageBrush def:Name="image" ImageSource="Tulip.jpg" TileMode="Tile"/>
<SolidColorBrush def:Name="solid" Color="gray"/>
</Border.Resources>
<Canvas Height="400" Width="400">
<Ellipse CenterX="100" CenterY="75"
RadiusX="90" RadiusY="50"
Fill="{lineargradient}" Stroke="{image}" StrokeThickness="15"/>
<Ellipse CenterX="300" CenterY="170"
RadiusX="50" RadiusY="150"
Fill="{radialgradient}" Stroke="{solid}" StrokeThickness="15"/>
</Canvas>
</Border>
圖 3-14. 工作漸層
轉換
XAML 支援數種轉換。 RotateTransform 會依 Angle 屬性的數量旋轉。 TranslateTransform 會根據 X 和 Y 屬性移動專案。 ScaleTransform 會根據 ScaleX 和 ScaleY 屬性壓縮或延展。 SkewTransform 會使用 AngleX、 AngleY和 Center 屬性來傾斜專案。 MatrixTransform 支援任意的相依轉換。 最後, TransformCollection 本身是一種 轉換 ,可讓您將數個轉換結合在一起。
某些類別,例如 Brush,具有 Transform 屬性。 在其他情況下,您可以使用 TransformDecorator 元素,其具有 Transform 屬性。 TransformDecorator 會轉換其子專案。 (Like Border,它只能有一個 child.) TransformDecorator 可以包含任何類型的子系,包括圖形、面板和控制項。 此範例會使用 TransformDecorators。 第 一個包含橢圓形,並將它旋轉 45 度。 第二個 TransformDecorator 包含 ListBox ,同時旋轉並調整 ListBox。 您可以在圖 3-15 中看到圖形的外觀。
<Border
xmlns="https://schemas.microsoft.com/2003/xaml"
xmlns:def="Definition"
Background="BlanchedAlmond"
>
<Canvas Height="400" Width="400">
<TransformDecorator Transform="rotate 45">
<Ellipse CenterX="100" CenterY="75"
RadiusX="90" RadiusY="50"
Fill="white" Stroke="black" StrokeThickness="15"/>
</TransformDecorator>
<TransformDecorator Canvas.Top="200" Canvas.Left="100">
<TransformDecorator.Transform>
<TransformCollection>
<RotateTransform Angle="135"/>
<ScaleTransform ScaleX="2" ScaleY="4"/>
</TransformCollection>
</TransformDecorator.Transform>
<ListBox >
<ListItem> ListItem 1 </ListItem>
<ListItem> ListItem 2 </ListItem>
<ListItem> ListItem 3 </ListItem>
</ListBox>
</TransformDecorator>
</Canvas>
</Border>
圖 3-15. 扭曲的 ListBox 和 Ellipse
動畫
XAML 也支援動畫。 您可以讓幾乎每個屬性產生動畫效果。 某些屬性具有對應的「動畫」屬性,例如 RotateTransform.Angle 和 RotateTransform.AngleAnimations。 在其他情況下,您可以使用複合屬性語法,將 動畫集合 指派給屬性。 例如,請參閱下列程式碼:
<Button>
<Button.Width>
… put animation collection here …
</Button.Width>
</Button>
每個類型的屬性都有個別的動畫集合。 Button.Width的類型是Length,因此一個使用LengthAnimationCollection。 同樣地, 動畫物件 本身專屬於您動畫的屬性類型, LengthAnimationCollection 包含一組 LengthAnimation 物件。
動畫物件具有 From 和 To 屬性,其類型符合所要動畫顯示之屬性的類型。 動畫物件也有 Begin、 Duration和 End 屬性,這些屬性是以秒為單位測量,並控制動畫的時間。 Begin 也支援 [即時運算] 值,而 Duration 支援 [無限期]。 您可以使用RepeatCount 和 RepeatDuration屬性自動重複動畫。 Fill屬性會指定動畫結束之後屬性會發生什麼情況。 Fill=「Hold」 是最重要的值之一;它會將 屬性保留在動畫 End 值。
動畫類別不是預設 XAML 命名空間的一部分,因此您必須使用< ?對應 >和xmlns建構以載入MSAvalon.Windows.Media.Animation命名空間。 因為此命名空間包含來自多個 DLL 的類別,所以您需要個別< 的 ?每個 DLL 的對應 >和xmlns。
下一個範例會以動畫顯示兩個屬性 :RotateTransform.Angle 屬性和 Button.Width 屬性,這兩個動畫命名空間都會使用類別。 圖 3-16 顯示不同時間的按鈕。
<?Mapping XmlNamespace="animC" ClrNamespace="MSAvalon.Windows.Media.Animation"
Assembly="PresentationCore" ?>
<?Mapping XmlNamespace="animF" ClrNamespace="MSAvalon.Windows.Media.Animation"
Assembly="PresentationFramework" ?>
<Border
xmlns="https://schemas.microsoft.com/2003/xaml"
xmlns:animC="animC"
xmlns:animF="animF"
xmlns:def="Definition"
Background="BlanchedAlmond"
>
<Canvas Height="400" Width="400">
<TransformDecorator Canvas.Top="200" Canvas.Left="100">
<TransformDecorator.Transform>
<TransformCollection>
<RotateTransform Angle="135">
<RotateTransform.AngleAnimations>
<animC:DoubleAnimationCollection>
<animC:DoubleAnimation From="0" To="360" Duration="4"
AutoReverse="True"
RepeatDuration="Indefinite"/>
</animC:DoubleAnimationCollection>
</RotateTransform.AngleAnimations>
</RotateTransform>
</TransformCollection>
</TransformDecorator.Transform>
<ListBox >
<ListItem> ListItem 1 </ListItem>
<ListItem> ListItem 2 </ListItem>
<ListItem> ListItem 3 </ListItem>
</ListBox>
</TransformDecorator>
<Button Width="40" Canvas.Top="10" Canvas.Left="10">
<Button.Width>
<animF:LengthAnimationCollection>
<animF:LengthAnimation From="40" To="300"
AutoReverse="true" Begin="1" Duration="1.2"
RepeatDuration="Indefinite"/>
</animF:LengthAnimationCollection>
</Button.Width>
Button
</Button>
</Canvas>
</Border>
圖 3-16。 不同時間動畫按鈕的檢視
檔服務
Longhorn 平臺提供廣泛的服務,可支援更好的線上檔檢視體驗。 有兩個主要服務:設計用來檢視、分頁和流覽檔內容的控制項,以及設計來增強閱讀體驗的佈建服務。
PageViewer 控制項
當您想要向使用者顯示檔以供線上檢視時,請使用 PageViewer 控制項。 PageViewer 控制項提供分頁和頁面流覽功能。 控制項會自動將檔的內容格式化為不同的頁面。 使用者可以使用頁面檢視器所提供的控制項,直接流覽至不同的頁面。
分頁和流覽
傳統上,線上內容,例如網頁是連續的。 使用者介面提供捲軸,可讓您檢視無法放入可見區域的內容。 實際上,您會將檢視視窗「捲動」到您想要查看的檔位置。
使用分頁時,您會將檔的內容分割成一或多個個別頁面,類似于書籍。 Longhorn 平臺提供分頁內容的支援,包括數個控制項,可協助您顯示和流覽顯示為離散頁面的內容。 此外,Longhorn 提供分頁應用程式開發介面 (API) 來擴充這些功能,並提供自訂分頁應用程式的豐富分頁支援。
PageViewer 控制項實際上是使用先前所述的控制群組合技術,從較小的控制項建置的複雜控制項。 PageViewer 控制項會使用 PageSource 和 PageElement 控制項來提供其分頁功能。 PageSource 控制項會中斷並格式化頁面的內容。 PageElement 控制項會轉譯單一頁面。 PageViewer 控制項也會使用 PageBar 控制項,讓您流覽頁面。
使用 PageViewer 控制項非常簡單。 若要顯示已知的檔,您可以使用它,如下列程式碼所示。 當然,您可以連結事件處理常式並變更原始檔案,讓頁面檢視器顯示不同的檔。
<Border
xmlns="https://schemas.microsoft.com/2003/xaml"
xmlns:def="Definition"
Background="BlanchedAlmond"
>
<PageViewer Source="AuthorsandPublishers.xaml" />
</Border>
圖 3-17 顯示裝載于瀏覽器視窗中的頁面檢視器,其中顯示其檔。 請注意檔頂端的頁面導覽控制項。
圖 3-17。 PageViewer 控制項
檔版面佈建服務
Longhorn 也提供檔版面佈建服務,其設計目的是讓閱讀體驗變得更好。 Longhorn 包含兩種新類型的檔支援:
- 調適型流程檔
- 已修正版面設定檔
這些新的檔案格式可讓開發人員為應用程式的使用者提供更好的檔閱讀體驗。
調適型流程檔會使用宣告檔應該是 Adaptive 的特殊標記專案。 Longhorn 會自動優化調適型檔,以充分利用可用的螢幕空間,並根據其系統的功能或限制,為使用者提供最佳的閱讀體驗。
例如,使用者可能有最近引進的其中一個 16 by-9 外觀比例寬螢幕顯示器。 很難讀取跨越冗長水平線的文字行。 根據視窗的寬度,調適型檔可能會將文字分成兩個、三個以上的資料行,因而減少使用者掃描文字行的工作。
在另一個範例中,檔可能包含在影像周圍流動的影像和文字。 當您在非固定檔中壓縮檔視窗的大小時,影像會維持固定大小,而且您會看到較少的文字。 當自適性檔判斷視窗中顯示文字不足時,可壓縮影像。 這可讓讀者仍然大致瞭解影像所呈現的內容,但會繼續閱讀影像內容中的文字。 在較小的視窗中,查看影像的每個圖元可能比讀取更多文字更不重要且有用。 另一種替代方法,例如將影像和周圍文字分隔到不同的頁面上,會破壞檔作者的意圖,也就是在內容中呈現文字和影像。
無論檢視器的螢幕大小、視窗大小或輸出裝置為何,固定版面設定檔每次都會顯示相同。 您可以使用特製化標記元素,或使用 Microsoft Windows Vector Graphics (WVG) 印表機驅動程式列印檔案,來建立固定版面設定檔。
調適型版面設定檔
在調適型版面設定檔中,您會在根層級標記中提供重要喜好設定。 Longhorn 接著可以透過最佳方式來轉譯檔,以充分利用視窗區域並增強其可讀性。 Longhorn 會自動判斷頁面的最佳寬度和欄數、適用于所有文字元素的理想大小、所有圖形的最佳大小和位置,以及邊界和裝訂邊的寬度,以提供最佳的內容整體呈現。
產生調適型版面設定檔
若要建立調適型版面設定檔,請使用類似下列的宣告式標記:
<Border
xmlns="https://schemas.microsoft.com/2003/xaml"
xmlns:def="Definition"
Background="BlanchedAlmond"
>
<AdaptiveMetricsContext ColumnPreference="Medium"
FontFamily="Arial">
<TextPanel Background="white">
<Section>
<Heading OutlineLevel="1">Adaptive Layout Example</Heading>
<Paragraph>
This example shows the advanced capabilities of Adaptive Flow
Layout. Lorem ipsum dolor sit amet, consectetuer adipiscing
elit, sed diam nonummy nibh euismod tin cidunt ut laoreet dolore
magna aliquam erat volutpat. Ut wisi enim ad minim veni am, quis
nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip
ex ea commodo consequat. Duis autem vel eum iriure.</Paragraph>
<Paragraph>
<Image TextPanel.FlowBehavior="Figure" Source="picture1.jpg"
TextPanel.Emphasis="Medium" />
Notice how images and text are flowed intelligently to enhance the
reading experi ence. Lorem ipsum dolor sit amet, consectetuer
adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet
dolore magna aliquam erat volutpat. Ut wisi e nim ad minim veniam,
quis nostrud exerci tation ullamcorper suscipit lobortis ni sl ut
aliquip ex ea commodo consequat. Duis autem vel eum iriure.
</Paragraph>
<Paragraph>Adaptive layout is an exciting new feature of Longhorn.
<Image TextPanel.FlowBehavior="Figure" Source="picture2.jpg"
TextPanel.Emphasis="Low" />
Lorem ipsum dolor sit amet, consectetuer
adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet
dolore magna aliquam erat volutpat. Ut wisi e nim ad minim veniam,
quis nostrud exerci tation ullamcorper suscipit lobortis ni sl ut
aliquip ex ea commodo consequat. Duis autem vel eum iriure.
</Paragraph>
</Section>
</TextPanel>
</AdaptiveMetricsContext>
</Border>
Fixed-Layout檔
您可以使用固定版面設定檔,以完全相同的配置和格式呈現檔內容,與所使用的應用程式軟體、硬體和作業系統無關。 此外,固定版面設定檔會在所有輸出裝置上以相同方式呈現。 固定版面設定檔是一組共同描述一或多個頁面外觀的物件。
產生Fixed-Layout檔
您可以使用兩種不同的技術來產生固定版面設定檔:
- 使用 Longhorn 印表機驅動程式將沒有標記的檔列印到檔案
- 使用 XAML 撰寫固定版面設定檔
例如,當您使用大部分的 Microsoft Win32 (應用程式來列印檔案時,Microsoft Office) 使用 Longhorn 印表機驅動程式時,印表機驅動程式會建立包含標記的 XAML 檔案,以分頁並放置列印檔案中每個字元、影像或向量圖形。
您可以選擇將檔輸出為標記檔案,或將標記檔案包含在容器內。 當您選取容器輸出時,也可以將數位版權和檔案保護套用至檔。
或者,您可以使用編輯器建立 XAML。 以下是固定版面設定檔的基本架構範例:
<FixedPanel xmlns="https://schemas.microsoft.com/2003/xaml/" >
<FixedPage Width="8.50in" Height="11.00in"> <!-- PAGE 1 -->
<Text FontFamily="Arial" FontSize="8.4" FixedPage.Left="1.250in"
FixedPage.Top="0.530in" FontWeight="Bold">1.</Text>
<Text FontFamily="Arial" FixedPage.Left="1.350in" FixedPage.Top="0.500in"
FontWeight="Bold" FontSize="12">Fixed Document</Text>
</FixedPage>
<FixedPage>
<Text>This is page 2</Text>
</FixedPage>
<FixedPage>
<Text>This is page 3</Text>
</FixedPage>
</FixedPanel>
總結
面板可讓您將顯示介面分割成具有不同版面配置特性的區域。 您有各種不同的控制項,可用來填入顯示器的面板。 圖形、 轉換和 動畫 可讓您產生動態圖形化輸出。 使用控制群組合,您可以結合這些功能,以實際產生您想要的任何使用者介面。 您可以產生調適型檔,以智慧方式配置您的內容,並讓讀者更容易閱讀。 或者,您可以精確地將每一個專案放在頁面上,並明確控制分頁,以產生與輸出裝置完全相同的檔。 此外,您可以使用 XAML 以宣告方式執行此動作。 這一點可確保撰寫WM_PAINT訊息處理常式!