首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

深入掌握 Windows 8 Store Apps 設定合約

     編輯:關於.NET

前言

在 Windows 8 Store Apps 中,「契約」是應用程式之間以及應用程式與系統互動的核心機制。設定合約讓使用者能從右側邊欄的 Charm 列直接存取應用程式的設定選項,提供一致且直觀的使用體驗。本文將詳細解析 Settings Contract 的實作方式,並透過完整的程式碼範例示範如何註冊設定命令、開啟設定面板以及建立自訂的詳細設定頁面。

核心概念

  • SettingsPane:設定面板,透過 GetForCurrentView() 取得目前視圖的實例,並使用 Show() 方法開啟。
  • CommandsRequested 事件:每次開啟 SettingsPane 時觸發,開發者需在此事件中將自訂的設定命令加入 ApplicationCommands 集合。
  • SettingsCommand:代表設定面板中的單一設定項目,包含 Id(識別碼)、Label(顯示名稱)與 Invoked(點擊後的回呼處理函式)。
  • UICommandInvokedHandler:處理設定項目被點擊時的委派,參數為實作 IUICommand 介面的物件。

實作步驟

1. 註冊 CommandsRequested 事件

在頁面載入時註冊事件,離開頁面時移除註冊,避免記憶體洩漏。

<Page x:Class="XamlDemo.Contracts.SettingsContract.Demo" xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="https://schemas.microsoft.com/expression/blend/2008" xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d">
<Grid Background="Transparent">
<StackPanel Margin="120 0 0 0">
<Button Name="btnAddSettings" Content="註冊 SettingsPane 的 CommandsRequested 事件" Click="btnAddSettings_Click_1" />
<Button Name="btnShowSettings" Content="開啟 SettingsPane" Click="btnShowSettings_Click_1" Margin="0 10 0 0" />
<TextBlock Name="lblMsg" FontSize="14.667" TextWrapping="Wrap" Margin="0 10 0 0" />
</StackPanel>
</Grid>
</Page>

2. 程式碼後置邏輯

using System;
using Windows.UI.ApplicationSettings;
using Windows.UI.Popups;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Media.Animation;
using Windows.UI.Xaml.Navigation;

namespace XamlDemo.Contracts.SettingsContract
{
    public sealed partial class Demo : Page
    {
        private Popup _settingsPopup = new Popup();
        private bool _commandsRequestedRegistered = false;

        public Demo()
        {
            this.InitializeComponent();
        }

        protected override void OnNavigatedFrom(NavigationEventArgs e)
        {
            base.OnNavigatedFrom(e);
            if (this._commandsRequestedRegistered)
            {
                SettingsPane.GetForCurrentView().CommandsRequested -= onCommandsRequested;
                _commandsRequestedRegistered = false;
            }
        }

        private void btnAddSettings_Click_1(object sender, RoutedEventArgs e)
        {
            if (!_commandsRequestedRegistered)
            {
                SettingsPane.GetForCurrentView().CommandsRequested += onCommandsRequested;
                _commandsRequestedRegistered = true;
            }
            else
            {
                lblMsg.Text += "已經為 SettingsPane 註冊了 CommandsRequested 事件";
                lblMsg.Text += Environment.NewLine;
            }
        }

        private void btnShowSettings_Click_1(object sender, RoutedEventArgs e)
        {
            SettingsPane.Show();
        }

        void onCommandsRequested(SettingsPane settingsPane, SettingsPaneCommandsRequestedEventArgs eventArgs)
        {
            UICommandInvokedHandler handler = new UICommandInvokedHandler(onSettingsCommand);
            SettingsCommand aboutCommand = new SettingsCommand("about", "關於", handler);
            eventArgs.Request.ApplicationCommands.Add(aboutCommand);
            SettingsCommand contactCommand = new SettingsCommand("contactUs", "聯繫我們", handler);
            eventArgs.Request.ApplicationCommands.Add(contactCommand);
            SettingsCommand flyoutCommand = new SettingsCommand("flyout", "彈出一個類「設定」風格的詳細設定頁", handler);
            eventArgs.Request.ApplicationCommands.Add(flyoutCommand);
        }

        void onSettingsCommand(IUICommand command)
        {
            SettingsCommand settingsCommand = (SettingsCommand)command;
            lblMsg.Text += string.Format("commandId:{0} - label:{1}", settingsCommand.Id.ToString(), settingsCommand.Label);
            lblMsg.Text += Environment.NewLine;

            if (settingsCommand.Id.ToString() == "flyout")
            {
                double settingsPageWidth = 600;
                _settingsPopup.IsLightDismissEnabled = true;
                _settingsPopup.Width = settingsPageWidth;
                _settingsPopup.Height = Window.Current.Bounds.Height;
                _settingsPopup.ChildTransitions = new TransitionCollection();
                _settingsPopup.ChildTransitions.Add(new PaneThemeTransition() { Edge = EdgeTransitionLocation.Right });

                CustomSettingsPage mySettingsPage = new CustomSettingsPage();
                mySettingsPage.Width = settingsPageWidth;
                mySettingsPage.Height = Window.Current.Bounds.Height;
                _settingsPopup.Child = mySettingsPage;

                _settingsPopup.HorizontalOffset = Window.Current.Bounds.Width - settingsPageWidth;
                _settingsPopup.VerticalOffset = 0;
                _settingsPopup.IsOpen = true;
            }
        }
    }
}

3. 自訂詳細設定頁面

建立一個獨立的 Page 作為詳細設定頁,包含返回按鈕、標題區塊與捲動內容區域,並套用 PaneThemeTransition 動畫以符合系統視覺風格。

<Page x:Class="XamlDemo.Contracts.SettingsContract.CustomSettingsPage" xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:XamlDemo.Contracts.SettingsContract" xmlns:d="https://schemas.microsoft.com/expression/blend/2008" xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d">
<Page.Resources>
<Style x:Key="SettingsBackButtonStyle" TargetType="Button">
<Setter Property="MinWidth" Value="0"/>
<Setter Property="FontFamily" Value="Segoe UI Symbol"/>
<Setter Property="FontWeight" Value="Normal"/>
<Setter Property="FontSize" Value="26.66667"/>
<Setter Property="AutomationProperties.AutomationId" Value="BackButton"/>
<Setter Property="AutomationProperties.Name" Value="Back"/>
<Setter Property="AutomationProperties.ItemType" Value="Navigation Button"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid x:Name="RootGrid" Width="30" Height="30">
<Grid Margin="-6,-6,0,0">
<TextBlock x:Name="BackgroundGlyph" Text="&#xE0D4;" Foreground="Transparent"/>
<TextBlock x:Name="NormalGlyph" Text="{StaticResource BackButtonSnappedGlyph}" Foreground="White"/>
<TextBlock x:Name="ArrowGlyph" Text="&#xE0C4;" Foreground="#00b2f0" Opacity="0"/>
</Grid>
<Rectangle x:Name="FocusVisualWhite" IsHitTestVisible="False" Stroke="{StaticResource FocusVisualWhiteStrokeThemeBrush}" StrokeEndLineCap="Square" StrokeDashArray="1,1" Opacity="0" StrokeDashOffset="1.5" />
<Rectangle x:Name="FocusVisualBlack" IsHitTestVisible="False" Stroke="{StaticResource FocusVisualBlackStrokeThemeBrush" StrokeEndLineCap="Square" StrokeDashArray="1,1" Opacity="0" StrokeDashOffset="0.5" />
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundGlyph" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource BackButtonPointerOverBackgroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundGlyph" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="White"/>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimation Storyboard.TargetName="ArrowGlyph" Storyboard.TargetProperty="Opacity" To="1" Duration="0"/>
<DoubleAnimation Storyboard.TargetName="NormalGlyph" Storyboard.TargetProperty="Opacity" To="0" Duration="0"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="FocusVisualWhite" Storyboard.TargetProperty="Opacity" To="1" Duration="0"/>
<DoubleAnimation Storyboard.TargetName="FocusVisualBlack" Storyboard.TargetProperty="Opacity" To="1" Duration="0"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Unfocused" />
<VisualState x:Name="PointerFocused" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Page.Resources>
<Grid Background="Transparent" Name="root">
<Border BorderBrush="Red" BorderThickness="1,0,0,0">
<Grid Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="80"/>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Background="#00b2f0" Grid.Row="0">
<StackPanel Orientation="Horizontal" Margin="40, 32, 17, 13">
<Button Name="btnBack" Click="btnBack_Click_1" Margin="0,3,0,0" Style="{StaticResource SettingsBackButtonStyle}"/>
<TextBlock Margin="10,0,0,0" FontFamily="Segoe UI" FontWeight="SemiLight" FontSize="24.6667" Text="Defaults" Foreground="White"/>
</StackPanel>
</Grid>
<ScrollViewer Grid.Row="1">
<StackPanel>
<StackPanel.ChildrenTransitions>
<TransitionCollection>
<PaneThemeTransition Edge="Right" />
</TransitionCollection>
</StackPanel.ChildrenTransitions>
<TextBlock FontSize="56" Foreground="Black" LineHeight="100">
<Run>設定1</Run> <LineBreak />
<Run>設定2</Run> <LineBreak />
<Run>設定3</Run> <LineBreak />
<Run>設定4</Run> <LineBreak />
<Run>設定5</Run> <LineBreak />
<Run>設定6</Run> <LineBreak />
<Run>設定7</Run> <LineBreak />
<Run>設定8</Run> <LineBreak />
<Run>設定9</Run>
</TextBlock>
</StackPanel>
</ScrollViewer>
</Grid>
</Border>
</Grid>
</Page>

4. 詳細設定頁面的程式碼後置

using Windows.UI.ApplicationSettings;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Media.Animation;
using Windows.UI.Xaml.Navigation;

namespace XamlDemo.Contracts.SettingsContract
{
    public sealed partial class CustomSettingsPage : Page
    {
        public CustomSettingsPage()
        {
            this.InitializeComponent();
        }

        private void btnBack_Click_1(object sender, RoutedEventArgs e)
        {
            Popup parent = this.Parent as Popup;
            if (parent != null)
            {
                parent.IsOpen = false;
            }
            if (Windows.UI.ViewManagement.ApplicationView.Value != Windows.UI.ViewManagement.ApplicationViewState.Snapped)
            {
                SettingsPane.Show();
            }
        }
    }
}

重點總結

  • 設定合約提供統一的設定進入點,符合 Windows 8 設計規範。
  • 透過 CommandsRequested 事件動態建立設定命令,支援簡單選項與複雜的自訂頁面。
  • 自訂設定頁面建議使用 Popup 搭配 PaneThemeTransition 實現從右側滑入的效果。
  • 離開頁面時務必移除事件註冊,避免重複註冊導致異常。

[原始碼下載]:https://files.cnblogs.com/webabcd/Windows8.rar

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved