View - Axvser/MinimalisticWPF GitHub Wiki
假设我们有一个 MyControl : UIElement 作为 View
Ⅰ 主题切换
- 如果你希望属性可以在主题发生切换时自动加载过渡效果……
[Theme(nameof(Background), typeof(Dark), ["#1e1e1e"])]
[Theme(nameof(Background), typeof(Light), ["White"])]
public partial class MyControl : UserControl
{
}
-
Theme特性的第三个参数
- 是一个对象数组
- 用于构造值,例如 ["White"] 声明了 Background 在 Light 主题下应为 白色
- TransitionSystem中6种支持自动过渡的目标均可构造,因此类似于 " 玻璃圆角 " 也可作为主题
- Brush具备一些特殊优化
- 可以传入 App.Xaml 中定义的静态资源的 Key ( 也就是说可以是任意画刷 ,而不局限于纯色画刷 )
- 可以传入 public static w-r 字段/属性的名称
-
依据需求,我们可以令程序
跟随系统主题
or手动设定主题
,只需在 App.cs 中执行下述语句- FollowSystem 在系统主题发生切换时,启动程序的主题切换,若读取系统主题失败,使用指定的默认值
- StartWith 手动指定初始主题,并在需要时手动切换主题
public partial class App : Application
{
public App()
{
DynamicTheme.FollowSystem(typeof(Dark));
DynamicTheme.StartWith(typeof(Dark));
}
}
- 手动切换主题
var param = new TransitionParams() // 自定义参数
{
Duration = 0.5,
FrameRate = 30,
};
TransitionParams.Theme.Duration = 0.2; // 全局共享参数 ( 默认参数 )
DynamicTheme.Apply(typeof(Dark));
DynamicTheme.Apply(typeof(Dark), param);
- 自定义主题
- IThemeAttribute接口必须实现
- 构造器具备唯一参数 params object?[]
using MinimalisticWPF.StructuralDesign.Theme;
namespace DynamicTest_MinWpf
{
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public sealed class GlassAttribute(params object?[] param) : Attribute, IThemeAttribute
{
public object?[] Parameters { get; set; } = param;
}
}
- 最后,关于主题过渡的参数,需要注意一些问题
- 若跟随系统主题,Duration不建议超过0.3,系统事件不应耗时过长
- 不建议界面拥有超大量元素,如果一定有,应选取下述方案
-
- 降低 FrameRate ,极限情况下 ,直接设定为 0 ,仅加载1帧
-
- 切换Theme要求重启程序
-
Ⅱ 悬停交互
- 如果你希望鼠标悬停时,属性可以加载过渡效果…… ( 悬停不同于主题,它的效果需要在Style内设定,参照 Ⅲ )
[Hover([nameof(Background), nameof(Foreground)])]
public partial class MyControl : UserControl
{
}
Ⅲ Style定义
总的来说, Ⅰ 和 Ⅱ 为主题过渡、悬停过渡功能快速生成了一个框架结构 ,能够设定默认值 ,而 Style 用于修改默认值以实现效果差异化
-
有关于 Ⅰ 和 Ⅱ 所提供的功能扩展,都是基于 生成代理属性 + 生成效果控制属性 ,若要构建灵活且便于维护的项目 ,Style是必须的
- 我们以Background属性为例
- 如果仅使用Hover特性,没有使用Theme特性,则生成
HoveredBackground
与NoHoveredBackground
属性,修改他们即可直接改变悬停时加载的过渡 - 如果同时拥有Hover与Theme特性,此处假设有Dark和Light主题
- DarkHoveredBackground & DarkNoHoveredBackground 用于控制Dark主题下的Background属性
- LightHoveredBackground & LightNoHoveredBackground 用于控制Light主题下的Background属性
- 如果仅使用Hover特性,没有使用Theme特性,则生成
- 我们以Background属性为例
-
这比起传统实现,有哪些特点呢,不都是用Style吗 ?
-
- 无Trigger模式,减少XAML中的嵌套
-
- 无Animation模式,所有过渡均由库自动计算并加载,减少XAML中的动画定义
-
-
有一些小技巧,我希望能派上用场
-
- 利用C#类继承,从UserControl派生一些Base类,然后将这些扩展用在Base类,这样,可以更少地使用特性
-
- 利用Style继承,我知道类似 LightHoveredBackground 这样的命名很长 ,不是所有人都喜欢 ,即便它传达的意思无比清晰
-
Ⅳ 循环帧
- 如果你希望像一些游戏引擎所做的事情那样,以一定的帧率刷新……
- CanMonoBehaviour 属性用于控制当前是否可以执行刷新
- Awake 发生在一切开始之前
- Start 发生在帧循环开始前
- Update 发生在每一帧
- LateUpdate 发生在每一帧执行完后
- ExitMonoBehaviour 发生在帧循环被终结时
[MonoBehaviour(16.6)]
// 16.6ms 相当于 60FPS
public partial class MyControl : UserControl
{
partial void Awake()
{
CanMonoBehaviour = false; // 默认是true,若你希望不要立刻开始帧循环,可以在这个阶段关闭
}
partial void Start()
{
throw new NotImplementedException();
}
partial void Update()
{
throw new NotImplementedException();
}
partial void LateUpdate()
{
throw new NotImplementedException();
}
partial void ExitMonoBehaviour()
{
throw new NotImplementedException();
}
}