聲明:本文內容適用於 Visual Studio 2015 RC 及 Windows 10 10069 SDK 環境下,若以后有任何變更,請以新的特性為准。
一、Password 控件的小眼睛屬性的變更
在 Windows 8.1(含 Windows 8) 及 Windows Phone 8.1 Runtime 中,Password 控件的小眼睛是由 IsPasswordRevealButtonEnabled 屬性定義的,但是,盡管是相同的屬性名字,卻有着不同的表現形式。
這就給開發人員帶來困惑了,因為所占的空間大小不一樣,導致整個頁面的布局難以控制。(所謂的牽一發而動全身就是這種情況吧)
在 Windows 10 中,控制這個小眼睛變更為 Password 控件的 PasswordRevealMode 屬性。這個屬性是 PasswordRevealMode 枚舉類型,分別有三個值:Peek、Hidden 和 Visible,對 Password 控件來說,Peek 是默認值。也就是說默認是這樣的:
若設置為 Hidden,則不顯示小眼睛;設置為 Visible,則 Password 控件直接顯示密碼原文,這時候樣子就跟 TextBox 一個樣。
PS:IsPasswordRevealButtonEnabled 屬性在 Windows 10 的 Password 控件仍存在,但已被標注為過時。
二、新的 ContentDialog 樣式
用法沒有變,但外觀我個人認為是變得更好看了,而且帶有動畫效果。
Desktop 下:
Mobile 下:
三、AutoSuggestBox
這個控件在 Windows Phone 8.1 Runtime 就已經存在了,但是在 Windows 8.1 中是沒有的(取而代之的是 Windows 8.1 有 SearchBox 控件)。在大一統的思想下,AutoSuggestBox 控件將取代 SearchBox。
四、SplitView
這個控件暫時還沒有官方的中文名稱,因此有人喜歡叫漢堡、也有人喜歡叫側滑菜單(主要視乎你怎么用這個控件)。這里我暫時還是用 SplitView 來稱呼它。
1、示例
先來個示例代碼:
<Page x:Class="Build2015XamlDemo.SplitViewPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:Build2015XamlDemo" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <StackPanel Orientation="Horizontal"> <FontIcon HorizontalAlignment="Left" VerticalAlignment="Top" x:Name="Hamburger" FontFamily="Segoe MDL2 Assets" Glyph="" PointerPressed="BtnHam_Click" /> <SymbolIcon HorizontalAlignment="Left" VerticalAlignment="Top" Symbol="Back" PointerReleased="BtnBack_Click" /> </StackPanel> <SplitView Grid.Row="1" x:Name="svw"> <SplitView.Pane> <Grid Background="Gold"> <TextBlock Text="漢堡內容" /> </Grid> </SplitView.Pane> <Grid Background="LightBlue"> <TextBlock Text="主要內容" /> </Grid> </SplitView> </Grid> </Page>
后台代碼:
using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Input; namespace Build2015XamlDemo { public sealed partial class SplitViewPage : Page { public SplitViewPage() { this.InitializeComponent(); } private void BtnHam_Click(object sender, PointerRoutedEventArgs e) { e.Handled = true; svw.IsPaneOpen = !svw.IsPaneOpen; } private void BtnBack_Click(object sender, PointerRoutedEventArgs e) { e.Handled = true; Frame.GoBack(); } } }
PS:后台部分省略了個判斷,作為示例不要在意。
效果:
2、SplitView 的 DisplayMode 屬性
這個屬性算是 SplitView 里最重要的一個屬性了,所以有必要說一下。DisplayMode 屬性的類型是 SplitViewDisplayMode,是一個枚舉類型。包含如下值:
- Overlay(SplitView 的 DisplayMode 屬性的默認值)
- Inline
- CompactOverlay
- CompactInline
測試代碼:
XAML:
<Page x:Class="Build2015XamlDemo.SplitViewModePage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:Build2015XamlDemo" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition /> </Grid.RowDefinitions> <StackPanel Orientation="Horizontal"> <FontIcon HorizontalAlignment="Left" VerticalAlignment="Top" x:Name="Hamburger" FontFamily="Segoe MDL2 Assets" Glyph="" PointerPressed="BtnHam_Click" /> <SymbolIcon HorizontalAlignment="Left" VerticalAlignment="Top" Symbol="Back" PointerReleased="BtnBack_Click" /> </StackPanel> <SplitView x:Name="svw" Grid.Row="1"> <SplitView.Pane> <Grid Background="Gold"> <TextBlock Text="漢堡內容" /> </Grid> </SplitView.Pane> <Grid> <ComboBox x:Name="cmb" HorizontalAlignment="Center" VerticalAlignment="Center" /> </Grid> </SplitView> </Grid> </Page>
后台代碼:
using System; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Input; namespace Build2015XamlDemo { public sealed partial class SplitViewModePage : Page { public SplitViewModePage() { this.InitializeComponent(); var modes = Enum.GetValues(typeof(SplitViewDisplayMode)); foreach (var mode in modes) { cmb.Items.Add(mode.ToString()); } cmb.SelectionChanged += Cmb_SelectionChanged; cmb.SelectedIndex = 0; } private void Cmb_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (cmb.SelectedItem != null) { var mode = (SplitViewDisplayMode)Enum.Parse(typeof(SplitViewDisplayMode), (string)cmb.SelectedItem); svw.DisplayMode = mode; } } private void BtnBack_Click(object sender, PointerRoutedEventArgs e) { e.Handled = true; Frame.GoBack(); } private void BtnHam_Click(object sender, PointerRoutedEventArgs e) { e.Handled = true; svw.IsPaneOpen = !svw.IsPaneOpen; } } }
Overlay:
在 Overlay 模式下,SplitView 在關閉狀態下,Pane 里的內容不顯示,在打開的狀態下,Pane 里的內容就會像是在 Content 上覆蓋一層。
Inline:
此模式下,關閉狀態與 Overlay 模式相同,不同的是在打開狀態下,Pane 會推開 Content,形成左側 Pane,右側 Content 的效果。如圖:
CompactOverlay、CompactInline:
打開模式參考上面,在關閉模式下,Pane 不會完全關閉,而是會留下一定的空間(該空間寬度由 SplitView 控件的 CompactPaneLength 屬性決定,默認為 48),我們可以用來顯示 Pane 里每一項的圖標,例如 Windows 10 10074 中的郵件應用。
五、VisualStateTrigger
在當前 Web 頁面開發中,因為越來越多的移動設備,響應式布局成為了一項重要的頁面表示形式。經過時間驗證,響應式布局的確十分有效。因此在 Windows 10 里,可以使用 VisualStateTrigger 來實現根據 App 的大小或其它因素來呈現不同的布局。
1、Demo 1 根據窗口寬度顯示不同文本
XAML:
<Page x:Class="Build2015XamlDemo.VisualStateTriggerDemo1Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:Build2015XamlDemo" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <VisualStateManager.VisualStateGroups> <VisualStateGroup> <VisualState x:Name="narrow"> <VisualState.Setters> <Setter Target="status.Text" Value="Narrow view" /> </VisualState.Setters> <VisualState.StateTriggers> <AdaptiveTrigger MinWindowWidth="0" /> </VisualState.StateTriggers> </VisualState> <VisualState x:Name="wide"> <VisualState.Setters> <Setter Target="status.Text" Value="Wide view" /> </VisualState.Setters> <VisualState.StateTriggers> <AdaptiveTrigger MinWindowWidth="600" /> </VisualState.StateTriggers> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups> <TextBlock x:Name="status" FontSize="40" HorizontalAlignment="Center" VerticalAlignment="Center" /> </Grid> </Page>
效果:
2、為 SplitView 設置為響應式
對於大窗口來說,SplitView 我們當然是想完整顯示,而對於小窗口或者移動設備,我們並不想推開主要內容(因為推開了位置就更加不足了),而是想“浮在”主要內容上,因此我們可以對 SplitView 作響應式處理。
<VisualState.Setters> <Setter Target="splitView.DisplayMode" Value="Inline" /> </VisualState.Setters> <VisualState.StateTriggers> <AdaptiveTrigger MinWindowWidth="720" /> </VisualState.StateTriggers> <VisualState.Setters> <Setter Target="splitView.DisplayMode" Value="Overlay" /> </VisualState.Setters> <VisualState.StateTriggers> <AdaptiveTrigger MinWindowWidth= "0" /> </VisualState.StateTriggers>
3、自定義 StateTrigger
在 10069 的 SDK 中,StateTrigger 就只有兩種,一個是我們上面提到的 AdaptiveTrigger,另一個是 StateTrigger,這個 StateTrigger 十分簡單,有一個 IsActive 屬性,因此這個 StateTrigger 相當於一個開關,因為比較簡單,所以大家可以自行嘗試,這里就不給出示例了。
回到正題,我們要實現一個 StateTrigger,那我們先看看內置的 StateTrigger,它們都繼承自 StateTriggerBase,而 StateTriggerBase 又繼承自 DependencyObject,因此我們可以定義依賴屬性(StateTrigger 的 IsActive 屬性也是一個依賴屬性)。接下來我們實現我們的代碼(這里我們實現一個根據設備類型的 StateTrigger):
using Windows.UI.Xaml; namespace Build2015XamlDemo { public enum DeviceType { Unknown, Desktop, Mobile } public class DeviceTrigger : StateTriggerBase { public static readonly DependencyProperty DeviceProperty = DependencyProperty.Register(nameof(Device), typeof(DeviceType), typeof(DeviceTrigger), new PropertyMetadata(DeviceType.Unknown, DeviceChanged)); public DeviceType Device { get { return (DeviceType)GetValue(DeviceProperty); } set { SetValue(DeviceProperty, value); } } private static void DeviceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var trigger = (DeviceTrigger)d; var value = (DeviceType)e.NewValue; var qualifiers = Windows.ApplicationModel.Resources.Core.ResourceContext.GetForCurrentView().QualifierValues; if (qualifiers.ContainsKey("DeviceFamily")) { switch (qualifiers["DeviceFamily"]) { case "Desktop": trigger.SetActive(trigger.Device == DeviceType.Desktop); break; case "Mobile": trigger.SetActive(trigger.Device == DeviceType.Mobile); break; } } } } }
其中 SetActive 方法傳入一個布爾值,使該 StateTrigger 生效或失效。
XAML:
<Page x:Class="Build2015XamlDemo.VisualStateTriggerDemo2Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:Build2015XamlDemo" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <VisualStateManager.VisualStateGroups> <VisualStateGroup> <VisualState x:Name="Desktop"> <VisualState.Setters> <Setter Target="device.Text" Value="Desktop" /> </VisualState.Setters> <VisualState.StateTriggers> <local:DeviceTrigger Device="Desktop" /> </VisualState.StateTriggers> </VisualState> <VisualState x:Name="Mobile"> <VisualState.Setters> <Setter Target="device.Text" Value="Mobile" /> </VisualState.Setters> <VisualState.StateTriggers> <local:DeviceTrigger Device="Mobile" /> </VisualState.StateTriggers> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups> <TextBlock x:Name="device" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="40" /> </Grid> </Page>
效果:
六、RelativePanel
這是一個新的系統內置控件,我們可以叫它為相對面板。
這幅圖是今年 Build 大會 ppt 上的一頁,上面很好地說明了這個控件應該如何使用。這個控件十分像安卓中的 RelativeLayout,因為安卓沒怎么學過,這里就不班門弄斧了。
七、Transform3D(3D 變換)
實例代碼:
<Page x:Class="Build2015XamlDemo.Transform3DPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:Build2015XamlDemo" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <Grid Background="Black"> <Grid.Transform3D> <PerspectiveTransform3D /> </Grid.Transform3D> <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center"> <Border Width="200" Height="100" Background="#FF11321E"> <Border.Transform3D> <CompositeTransform3D RotationX="-45" CenterY="100"></CompositeTransform3D> </Border.Transform3D> <TextBlock Text="Hello" /> </Border> <Border Width="200" Height="100" Background="#FF0B5B29"> <Border.Transform3D> <CompositeTransform3D RotationX="45"></CompositeTransform3D> </Border.Transform3D> <TextBlock Text="World" /> </Border> </StackPanel> </Grid> </Grid> </Page>
效果:
是不是有點立體的感覺呢?(●'◡'●)
現在 Windows 10 開始菜單中的磁貼 3D 變換效果也是用這種方式實現的哦。
八、自定義窗口標題欄
因為這點在我機子上顯示的是錯誤的(SDK 沒完成的原因吧),因此使用 Build 大會的 ppt 的圖片好了。
倒數第二行告訴系統使用自定義標題欄,不使用系統標題欄。
最后一行則使用已經渲染的控件作為標題欄。(需要注意的是“已渲染”這幾個字,跟 RenderTargetBitmap 類的 Render 方法類似)
九、新的綁定——x:Bind
在 Windows 10 的 XAML 里,新添加了這種新的綁定方式,那么既然已經有舊的綁定({Binding}),那為什么還需要新的綁定呢?必然是有好處的。
這里有兩幅 Build 大會 ppt 的圖片:
可以看出,無論是 CPU 占用還是內存占用,新的綁定({x:Bind})都要優於以前的綁定({Binding})。
1、為什么 x:Bind 的性能這么好?
在 Build 大會上,微軟介紹 x:Bind 使用的是“compiled binding”,即編譯時綁定。而傳統的綁定,是動態的,例如數據源你可能在運行時從 int 變成 string 都說不定,因此系統不得不承受這些動態變換帶來的損失。而新的綁定,是在編譯時進行綁定,因此類型都是已知的,那么類型的轉換也能夠明確確定。
2、試試 x:Bind
XAML:
<TextBlock Text="{x:Bind Path=Relax}" />
后台 cs:
public sealed partial class XBindDemo1 : Page { private string Relax = "坐和放寬"; public XBindDemo1() { this.InitializeComponent(); } }
效果:
這是很不可思議的,我們沒有聲明 DataContext。但實現效果就是這么棒!
從 Build 大會的 ppt 我們知道:
- x:Bind 為強類型;
- x:Bind 的上下文為當前 Page 或 UserControl(且無法更改!);
- x:Bind 的 Mode 默認為 OneTime。
假如我們將上面的后台代碼中的 Relax 誤拼寫為 Ralex 的話,編譯會得到如下錯誤:
3、事件綁定
你沒看錯,新的綁定能夠綁定事件處理了。
添加新的測試代碼:
XAML:
<Button Content="click bind" Click="{x:Bind Path=MyClick}" />
后台代碼:
private async void MyClick(object sender, RoutedEventArgs e) { await new MessageDialog("you click button").ShowAsync(); }
編譯,運行,通過。
可能你會問,這樣有什么意思,只不過將 Click="MyClick" 換成上面的寫法而已,而且敲的代碼更多了。
現在我們先將 MyClick 的第二個參數的類型改成 object 試試。
private async void MyClick(object sender, object e) { await new MessageDialog("you click button").ShowAsync(); }
竟然能正常運行!!!
這就是新的綁定的威力,在事件的綁定上,有一定的“協變”(請與 C# 中協變區分清楚,這里只是借用一下概念,是兩種完全不同的東西)。
那么什么樣的方法才能夠被綁定呢?
根據官方現在的文檔,有以下幾點需要注意。
- 沒有方法參數,例如 void MyClick(){} 也能夠被上面的 Click 所綁定;
- 完全匹配,跟上面最開始的代碼一樣;
- 方法參數是子類,例如上面將 RoutedEventArgs 修改為 object 后的情況。
- 不支持重載,例如上面三點的方法同時存在兩個或以上就沒法通過編譯了。
- 暫時不是所有事件都支持,關於這點,我們只能在自己測試了,微軟官方還沒有詳細文檔說明那些事件是支持的。
- 由於沒有傳統綁定的 CommandParameter,所以這種情況下還是需要使用傳統的綁定。
4、模板中使用 x:Bind
由於上面也說了,x:Bind 是強類型的,因此必須在模板中聲明數據類型。
<ListView> <ListView.ItemTemplate> <DataTemplate x:DataType="local:FreeBookCategory"> <StackPanel> <SymbolIcon Symbol="{x:Bind Symbol}"/> <TextBlock Text="{x:Bind Name}"/> <Button Click="{x:Bind Click}"/> </StackPanel> </DataTemplate> </ListView.ItemTemplate> </ListView>
5、在資源字典中使用 x:Bind
這點在官方說明中是最為繁瑣的。
首先我們新建一個資源文件,例如就叫 MyTemplate.xaml。
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:Build2015XamlDemo"> <DataTemplate x:Key="RelaxTemplate" x:DataType="local:Person"> <TextBlock Text="{x:Bind Name}" /> </DataTemplate> </ResourceDictionary>
Person 類的定義如下:
namespace Build2015XamlDemo { public class Person { public string Name { get; set; } } }
這時候編譯是不通過的。
新建一個 MyTemplate.xaml.cs 的文件。
partial class MyTemplate { public MyTemplate() { InitializeComponent(); } }
修改上面的 XAML 文件。
<ResourceDictionary x:Class="Build2015XamlDemo.MyTemplate" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:Build2015XamlDemo"> <DataTemplate x:Key="RelaxTemplate" x:DataType="local:Person"> <TextBlock Text="{x:Bind Name}" /> </DataTemplate> </ResourceDictionary>
注意多了一個x:Class,填寫 MyTemplate 類的命名空間全路徑。
這時候就可以編譯通過了,之后就可以在其它地方使用這個 Template 了。
2015 年 10 月 29 日補充,在 xaml 頁面中如何引用該模板。(下面的 Application 換成 Page、UserControl 同樣)
<Application> <Application.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <local:MyTemplate /> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </Application.Resources> </Application>
在 10240 中實測,在此感謝“最硬的小石頭”指出。
6、啰嗦一句
x:Bind 並不能完全代替舊的 Binding ,因為在上面也說了,x:Bind 是強類型的,因此像使用 Json.NET 的 JsonObject 或其它動態類型的情況下,仍然需要用到舊的 Binding。但是如果能使用新的綁定,則應該盡量使用新的綁定,因為性能有較大幅度的提升。
十、分階段渲染
在 Windows 10 中的 XAML,增加了一種新語法實現分階段渲染。這里我們還是用上面的 Person 類。新建頁面,編寫如下代碼
<Page x:Class="Build2015XamlDemo.XPhaseDemo" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:Build2015XamlDemo" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <ListView ItemsSource="{x:Bind LotsOfPersons}"> <ListView.ItemTemplate> <DataTemplate x:DataType="local:Person"> <Grid> <TextBlock Text="{x:Bind Name}" Foreground="Red" /> <TextBlock Text="{x:Bind Name}" Foreground="Green" x:Phase="1" /> </Grid> </DataTemplate> </ListView.ItemTemplate> </ListView> </Grid> </Page>
后台代碼:
using System; using System.Collections.Generic; using Windows.UI.Xaml.Controls; namespace Build2015XamlDemo { public sealed partial class XPhaseDemo : Page { public List<Person> LotsOfPersons { get; set; } public XPhaseDemo() { this.InitializeComponent(); LotsOfPersons = new List<Person>(); for (int i = 0; i < 10000; i++) { LotsOfPersons.Add(new Person() { Name = Guid.NewGuid().ToString() }); } } } }
運行程序的話,應該會看見有一些紅色,然后很快就變成綠色的。x:Phase 的值越大,越后渲染。
由於處理速度太快,因此也不太好截圖,性能差點的機器應該會能看見效果的。
這點對於移動設備等性能較差的機器改善用戶體驗很有用。
轉載請保留到該頁面的鏈接http://www.cnblogs.com/h82258652/p/4508777.html。謝謝!





















