內容控件與容器控件是構建 Windows 8 Store Apps 介面的基石。本篇系統整理 ToolTip、Frame、AppBar、ContentControl/ContentPresenter、Border、Viewbox、Popup 七大控件的核心屬性、事件與實戰範例,助你快速掌握導航、提示、彈出視窗與版面縮放等關鍵技術。
提供滑鼠懸停或觸控時的輔助說明。可直接用 ToolTipService.ToolTip 附加屬性簡單設定,或建立獨立 ToolTip 物件以支援豐富內容。
Placement:顯示位置IsOpen:手動控制顯隱Opened/Closed:事件<Page x:Class="XamlDemo.Controls.ToolTipDemo" ...>
<Grid Background="Transparent">
<StackPanel Name="root" Margin="120 0 0 0">
<TextBlock Text="TextBlock" ToolTipService.ToolTip="ToolTipService.ToolTip" ToolTipService.Placement="Bottom" FontSize="14.667" />
<TextBlock Text="TextBlock" FontSize="14.667" Margin="0 100 0 0">
<ToolTipService.ToolTip>
<ToolTip Name="toolTip" Content="ToolTipService.ToolTip" Placement="Bottom" />
</ToolTipService.ToolTip>
</TextBlock>
</StackPanel>
</Grid>
</Page>
App 內頁面導航的核心容器。支援前進/後退堆疊、頁面快取、導航狀態序列化與還原。
| 成員 | 說明 |
|---|---|
Navigate(Type, Object) | 導航至指定頁面,可傳參數 |
GoBack()/GoForward() | 堆疊導航 |
CanGoBack/CanGoForward | 是否可導航 |
CacheSize | 最大快取頁數 (預設 10) |
GetNavigationState()/SetNavigationState() | 序列化/還原導航歷史 |
Disabled:每次重新實例化 (預設)Enabled:快取,超過 CacheSize 先進先出Required:強制快取,忽略 CacheSize<Page x:Class="XamlDemo.Controls.Frame.Demo" ...>
<Grid Background="Transparent">
<StackPanel Margin="120 0 0 0" Orientation="Horizontal">
<StackPanel Width="400">
<Button Name="btnGotoFrame1" Content="導航至 Frame1" Click="btnGotoFrame1_Click_1" />
<Button Name="btnGotoFrame2" Content="導航至 Frame2" Click="btnGotoFrame2_Click_1" Margin="0 10 0 0" />
<Button Name="btnBack" Content="後退" Click="btnBack_Click_1" Margin="0 10 0 0" />
<Button Name="btnForward" Content="前進" Click="btnForward_Click_1" Margin="0 10 0 0" />
<TextBlock Name="lblMsg" FontSize="14.667" TextWrapping="Wrap" Margin="0 10 0 0" />
</StackPanel>
<Frame Name="frame" VerticalAlignment="Top" Margin="10 0 0 0" />
</StackPanel>
</Grid>
</Page>
public sealed partial class Demo : Page {
public Demo() { this.InitializeComponent(); }
protected override void OnNavigatedTo(NavigationEventArgs e) {
frame.Navigated += frame_Navigated;
}
void frame_Navigated(object sender, NavigationEventArgs e) {
lblMsg.Text = "CacheSize: " + frame.CacheSize + "\n";
lblMsg.Text += "BackStackDepth: " + frame.BackStackDepth + "\n";
lblMsg.Text += "CanGoBack: " + frame.CanGoBack + "\n";
lblMsg.Text += "CanGoForward: " + frame.CanGoForward + "\n";
lblMsg.Text += "CurrentSourcePageType: " + frame.CurrentSourcePageType + "\n";
lblMsg.Text += "NavigationState: " + frame.GetNavigationState();
}
private void btnGotoFrame1_Click_1(object sender, RoutedEventArgs e) {
frame.Navigate(typeof(Frame1), "param1");
}
private void btnGotoFrame2_Click_1(object sender, RoutedEventArgs e) {
frame.SourcePageType = typeof(Frame2);
}
private void btnBack_Click_1(object sender, RoutedEventArgs e) {
if (frame.CanGoBack) frame.GoBack();
}
private void btnForward_Click_1(object sender, RoutedEventArgs e) {
if (frame.CanGoForward) frame.GoForward();
}
}
public sealed partial class Frame1 : Page {
public Frame1() {
this.InitializeComponent();
this.NavigationCacheMode = Windows.UI.Xaml.Navigation.NavigationCacheMode.Enabled;
this.Loaded += Frame1_Loaded;
}
void Frame1_Loaded(object sender, RoutedEventArgs e) {
lblMsg.Text += "\nLoaded: " + DateTime.Now.ToString();
}
protected override void OnNavigatedTo(NavigationEventArgs e) {
lblMsg.Text += "\nOnNavigatedTo: " + DateTime.Now.ToString();
}
}
放置全域或頁面級命令按鈕,支援上/下兩列,可設定黏性模式防止點擊外部自動關閉。
Page.TopAppBar/Page.BottomAppBar:定義位置IsSticky:true 時需手動或邊緣手勢關閉IsOpen:程式控制開合AppBarButtonStyle 等系統資源<Page.BottomAppBar>
<AppBar x:Name="appBar" Padding="10,0">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50*"/>
<ColumnDefinition Width="50*"/>
</Grid.ColumnDefinitions>
<StackPanel x:Name="LeftPanel" Orientation="Horizontal" Grid.Column="0" HorizontalAlignment="Left">
<Button Style="{StaticResource AppBarButtonStyle}" Content="" AutomationProperties.Name="編輯" />
<Button Style="{StaticResource SaveAppBarButtonStyle}" AutomationProperties.Name="保存" />
<Button Style="{StaticResource DeleteAppBarButtonStyle}" AutomationProperties.Name="刪除" />
</StackPanel>
<StackPanel x:Name="RightPanel" Orientation="Horizontal" Grid.Column="1" HorizontalAlignment="Right">
<Button Style="{StaticResource RefreshAppBarButtonStyle}" AutomationProperties.Name="刷新" />
<Button Style="{StaticResource HelpAppBarButtonStyle}" AutomationProperties.Name="幫助" />
</StackPanel>
</Grid>
</AppBar>
</Page.BottomAppBar>
private void chkIsSticky_Checked_1(object sender, RoutedEventArgs e) { appBar.IsSticky = true; }
private void chkIsSticky_Unchecked_1(object sender, RoutedEventArgs e) { appBar.IsSticky = false; }
private void btnOpen_Click_1(object sender, RoutedEventArgs e) { appBar.IsOpen = true; }
private void btnClose_Click_1(object sender, RoutedEventArgs e) { appBar.IsOpen = false; }
ContentControl 可承載單一內容,ContentPresenter 則用於 ControlTemplate 內呈現該內容,實現樣式與內容分離。
<ContentControl Width="200" Margin="5" Content="我是 ContentControl" HorizontalAlignment="Left">
<ContentControl.Template>
<ControlTemplate>
<Border BorderBrush="Red" BorderThickness="1">
<Grid Background="Yellow">
<ContentPresenter HorizontalAlignment="Right" Foreground="Black" FontSize="14.667" />
</Grid>
</Border>
</ControlTemplate>
</ContentControl.Template>
</ContentControl>
提供邊框、背景、圓角與內容轉場動畫。
BorderThickness/BorderBrush/CornerRadius:外觀Child:單一子元素ChildTransitions:如 EntranceThemeTransition 進場動畫<Border BorderThickness="1,10,20,30" BorderBrush="Red" Background="Blue" CornerRadius="10" Width="400" Height="100">
<Border.Child><TextBlock Text="我是 Border 裡的內容" TextAlignment="Center" /></Border.Child>
</Border>
<Border BorderThickness="20" Width="400" Height="100" Margin="0 10 0 0">
<Border.BorderBrush><ImageBrush ImageSource="/Assets/Logo.png" /></Border.BorderBrush>
<TextBlock Text="我是 Border 裡的內容" />
<Border.ChildTransitions><TransitionCollection><EntranceThemeTransition /></TransitionCollection></Border.ChildTransitions>
</Border>
控制子元素如何拉伸填滿可用空間,四種 Stretch 模式:
Fill:非等比填滿None:原始大小,超出裁切Uniform:等比縮放 (預設)UniformToFill:等比填滿,超出裁切<Border BorderBrush="Red" BorderThickness="1" Width="100" Height="100">
<Viewbox Width="100" Height="100" Stretch="Fill"><StackPanel><TextBlock Text="webabcd" /></StackPanel></Viewbox>
</Border>
<!-- None, Uniform, UniformToFill 同理 -->
獨立於視覺樹的浮動容器,常用於下拉選單、工具提示、Toast 模擬。
IsOpen:控制顯隱IsLightDismissEnabled:點擊外部自動關閉HorizontalOffset/VerticalOffset:相對定位ChildTransitions:如 PopupThemeTransition、PaneThemeTransition<Popup Name="popup" HorizontalOffset="200" VerticalOffset="10"
IsLightDismissEnabled="{Binding IsChecked, ElementName=chkIsLightDismissEnabled}">
<Popup.Child>
<Border BorderBrush="Red" BorderThickness="1" Background="Blue" Width="200" Height="200">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock Text="我是 Popup" FontSize="24.667" HorizontalAlignment="Center" />
<Button Name="btnClosePopup" Content="關閉" HorizontalAlignment="Center" Click="btnClosePopup_Click_1" />
</StackPanel>
</Border>
</Popup.Child>
<Popup.ChildTransitions><TransitionCollection><PopupThemeTransition /></TransitionCollection></Popup.ChildTransitions>
</Popup>
private Popup _popupToast = new Popup();
private void btnOpenPopupToast_Click_1(object sender, RoutedEventArgs e) {
if (!_popupToast.IsOpen) {
Border border = new Border() {
BorderBrush = new SolidColorBrush(Colors.Red),
BorderThickness = new Thickness(1),
Background = new SolidColorBrush(Colors.Blue),
Width = 600, Height = 100,
Child = new TextBlock() { Text = "我是 Popup", FontSize = 24.667, HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center }
};
_popupToast.IsLightDismissEnabled = true;
_popupToast.Child = border;
_popupToast.VerticalOffset = 100d;
_popupToast.ChildTransitions = new TransitionCollection() { new PaneThemeTransition() { Edge = EdgeTransitionLocation.Left } };
_popupToast.IsOpen = true;
}
}
內容與容器控件構成了 App 介面的骨架與互動層。善用 Frame 導航架構、AppBar 命令列、Popup 浮動介面,並配合 Border、Viewbox 進行版面微調,能大幅提升開發效率與使用者體驗。完整原始碼請參考 源碼下載。