「Win10 UAP 開發系列」之主題模式切換

微軟動做真是快,原本想寫WP8.1RT系列,結果剛整理了一點就出Win10 UAP了。不過還好RTWin10的差異還不算太大。前兩天參加了Win10開發極客秀,雖然沒獲獎,不過在韋恩卑鄙的幫助下順利將澎湃新聞WP8.1版升級到了Win10UAP,使用了一些新的特性,最近爭取有時間慢慢把一些東西總結一下。css

今天先說一下如何在Win10 UAP中切換主題模式。app

切換日間、夜間主題模式這個功能我從WP8就實現了,並封裝成了一個庫,用在我全部的WP8app裏。到了WP8.1由於系統主題樣式都改了,又重寫了一遍。還沒來得及整理寫blogWin10的樣式又改了……吐槽不完啊簡直。不過思路都是同樣的,如今以Win10版本爲例總結一下。框架

UAP的樣式和之前的版本基本同樣,都是一些相似css的東西,咱們經過覆蓋系統的style,就能夠實現本身的主題樣式。首先找到UAP的style的位置:async

C:\Program Files (x86)\Windows Kits\10\Include\10.0.10069.0\winrt\xaml\design\themeresources.xamlide

2015-12-29 update:字體

升級10586後,該文件的地址在:this

C:\Program Files (x86)\Windows Kits\10\DesignTime\CommonConfiguration\Neutral\UAP\10.0.10586.0\Genericspa

裏面有generic.xaml和themeresources.xaml3d

打開這個文件,能夠看到裏面存放的是系統默認的主題樣式。blog

順便說一下,WP8 和WP8.1 的默認主題樣式也能夠找到,位置不同。

1、新建UAP項目

新建個UAP項目。由於我習慣用MVVM-Sidekick來作,因此之後都會基於這個框架來作,順便給@韋恩卑鄙 作下廣告^_^

這個例子就叫ThemeDemo。肯定。

等待框架程序建立完成。

可見如今Win10 UAP的項目只有一個,與WP8.1時代分別爲PC和手機新建項目的方式已經不一樣了。這樣能夠更方便。

2、添加默認主題

用VS2015RC打開剛纔找到的系統默認樣式文件,如圖:

這樣看比較亂,把代碼摺疊一下:

這樣看就清楚了,包括了Default、Light和高對比對三種主題樣式,和各類style、字體、字體大小、各類Color和Brush、控件的style等等,如今咱們須要提取出來進行修改。

在項目中添加一個名爲CustomTheme的文件夾。

通常只須要對Dark和Light分別處理便可,好比我想Dark的背景色不是純黑,Light的背景色不是純白等等。

新建兩個xaml文件,命名爲ThemeResourcesDark.xaml和ThemeResourcesLight.xaml,根節點這樣寫:

而後把系統樣式文件裏有關Color和Brush的部分複製過來,Default對應Dark,Light對應Light。

控件的style另外建個文件CustomStyleResources.xaml,把控件的style複製過來,由於不一樣主題下控件只是背景色不一樣,margin、padding這些屬性都是一致的。

我還添加了一套FlatUI的顏色資源,FlatUIColorsResources.xaml,裏面存放了各類Flat風格的Color和Brush來方便使用。

3、引入自定義樣式資源

打開App.xaml,添加如下代碼:

控件的style和主題的style都引入進來了,順便說一下,控件模板等東西不要往App.xaml裏堆,多了顯得太亂,應該都統一放到資源文件裏進行管理。

4、修改自定義樣式

如今運行程序,樣子是默認的,仍是白底黑字。由於RequestedTheme="Light"

如今咱們修改個背景色看看。打開MainPage.xaml 能夠看到如下代碼:

也就是說,根Grid的背景色名字是ApplicationPageBackgroundThemeBrush

而後去ThemeResourcesLight.xaml文件裏找這個資源,改一下顏色:

修改的顏色最好加個註釋。

而後跑一下:

好了背景色已經變了,再也不是純白了。而後能夠繼續改前景色、Dark主題的背景色、前景色……。

5、在程序中切換主題

UAP的主題是經過RequestedTheme來設置的,能夠在頁面中綁定一個屬性來實現切換。

打開MainPage_Model.cs,添加一個屬性,輸入代碼段propvm按Tab

/// <summary>

///當前主題

/// </summary>

public ElementTheme CurrentTheme

{

get { return _CurrentThemeLocator(this).Value; }

set

{

_CurrentThemeLocator(this).SetValueAndTryNotify(value);

}

}

#region Property ElementTheme CurrentTheme Setup

protected Property<ElementTheme> _CurrentTheme = new Property<ElementTheme> { LocatorFunc = _CurrentThemeLocator };

static Func<BindableBase, ValueContainer<ElementTheme>> _CurrentThemeLocator = RegisterContainerLocator<ElementTheme>("CurrentTheme", model => model.Initialize("CurrentTheme", ref model._CurrentTheme, ref _CurrentThemeLocator, _CurrentThemeDefaultValueFactory));

static Func<ElementTheme> _CurrentThemeDefaultValueFactory = () => { return ElementTheme.Default; };

#endregion

在初始化VM的時候,給其賦值:

添加一個Command,輸入propcmd按Tab

/// <summary>

///切換日間夜間模式

/// </summary>

public CommandModel<ReactiveCommand, String> CommandSetCustomTheme

{

get { return _CommandSetCustomThemeLocator(this).Value; }

set { _CommandSetCustomThemeLocator(this).SetValueAndTryNotify(value); }

}

#region Property CommandModel<ReactiveCommand, String> CommandSetCustomTheme Setup

protected Property<CommandModel<ReactiveCommand, String>> _CommandSetCustomTheme = new Property<CommandModel<ReactiveCommand, String>> { LocatorFunc = _CommandSetCustomThemeLocator };

static Func<BindableBase, ValueContainer<CommandModel<ReactiveCommand, String>>> _CommandSetCustomThemeLocator = RegisterContainerLocator<CommandModel<ReactiveCommand, String>>("CommandSetCustomTheme", model => model.Initialize("CommandSetCustomTheme", ref model._CommandSetCustomTheme, ref _CommandSetCustomThemeLocator, _CommandSetCustomThemeDefaultValueFactory));

static Func<BindableBase, CommandModel<ReactiveCommand, String>> _CommandSetCustomThemeDefaultValueFactory =

model =>

{

var resource = "SetCustomTheme"; // Command resource

var commandId = "SetCustomTheme";

var vm = CastToCurrentType(model);

var cmd = new ReactiveCommand(canExecute: true) { ViewModel = model }; //New Command Core

cmd

.DoExecuteUIBusyTask(

vm,

async e =>

{

//Todo: Add SetCustomTheme logic here, or

await MVVMSidekick.Utilities.TaskExHelper.Yield();

if (vm.CurrentTheme == ElementTheme.Dark || vm.CurrentTheme == ElementTheme.Default)

{

vm.CurrentTheme = ElementTheme.Light;

}

else

{

vm.CurrentTheme = ElementTheme.Dark;

}

}

)

.DoNotifyDefaultEventRouter(vm, commandId)

.Subscribe()

.DisposeWith(vm);

 

var cmdmdl = cmd.CreateCommandModel(resource);

cmdmdl.ListenToIsUIBusy(model: vm, canExecuteWhenBusy: false);

return cmdmdl;

};

#endregion

 

ElementTheme和ApplicationTheme是不一樣的,後者是App的屬性,前者能夠應用於UIElement。因此能夠把這個屬性綁定到根Grid上。

在頁面中加一個Button,Content設置爲"切換主題",而後把Command綁定到CommandSetCustomTheme

跑一下看看:

能夠順利切換了,並且背景色和前景色也變成了咱們設置的樣子,不是純黑純白了。

其實TextBlock和Button並無設置背景色前景色,都是繼承系統的,因此不用特別設置。其餘的控件也同樣,若是須要特殊處理就本身添加樣式便可。

6、設置控件的style

順便說一下CustomStyleResources.xaml的做用,我建議把控件的樣式寫在這裏,覆蓋系統默認的。好比能夠把全部的Grid都更改一下背景色,就能夠在這裏改,或者改全局Pivot的頭部margin之類的。

 

忘了最後附上源碼:

連接: http://pan.baidu.com/s/1mgFvXos 密碼: wnck

相關文章
相關標籤/搜索