“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

相关文章
相关标签/搜索