diff --git a/docs/images/scrollviewer-example.webp b/docs/images/scrollviewer-example.webp new file mode 100644 index 0000000..6cf0d39 Binary files /dev/null and b/docs/images/scrollviewer-example.webp differ diff --git a/docs/images/simulatetouch-example.webp b/docs/images/simulatetouch-example.webp new file mode 100644 index 0000000..d0b0193 Binary files /dev/null and b/docs/images/simulatetouch-example.webp differ diff --git a/docs/images/transition-example1.webp b/docs/images/transition-example1.webp new file mode 100644 index 0000000..ddc3cb0 Binary files /dev/null and b/docs/images/transition-example1.webp differ diff --git a/docs/images/transition-example2.webp b/docs/images/transition-example2.webp new file mode 100644 index 0000000..808e41d Binary files /dev/null and b/docs/images/transition-example2.webp differ diff --git a/docs/images/transition-example3.webp b/docs/images/transition-example3.webp new file mode 100644 index 0000000..f2ed001 Binary files /dev/null and b/docs/images/transition-example3.webp differ diff --git a/docs/images/windowoption-example1.png b/docs/images/windowoption-example1.png new file mode 100644 index 0000000..fa7a8fe Binary files /dev/null and b/docs/images/windowoption-example1.png differ diff --git a/docs/images/windowoption-example10.png b/docs/images/windowoption-example10.png new file mode 100644 index 0000000..98a801d Binary files /dev/null and b/docs/images/windowoption-example10.png differ diff --git a/docs/images/windowoption-example11.png b/docs/images/windowoption-example11.png new file mode 100644 index 0000000..8a26e62 Binary files /dev/null and b/docs/images/windowoption-example11.png differ diff --git a/docs/images/windowoption-example12.png b/docs/images/windowoption-example12.png new file mode 100644 index 0000000..3b5d805 Binary files /dev/null and b/docs/images/windowoption-example12.png differ diff --git a/docs/images/windowoption-example2.png b/docs/images/windowoption-example2.png new file mode 100644 index 0000000..16ff4a0 Binary files /dev/null and b/docs/images/windowoption-example2.png differ diff --git a/docs/images/windowoption-example3.png b/docs/images/windowoption-example3.png new file mode 100644 index 0000000..8a40006 Binary files /dev/null and b/docs/images/windowoption-example3.png differ diff --git a/docs/images/windowoption-example4.png b/docs/images/windowoption-example4.png new file mode 100644 index 0000000..06322c0 Binary files /dev/null and b/docs/images/windowoption-example4.png differ diff --git a/docs/images/windowoption-example5.png b/docs/images/windowoption-example5.png new file mode 100644 index 0000000..b941e86 Binary files /dev/null and b/docs/images/windowoption-example5.png differ diff --git a/docs/images/windowoption-example6.png b/docs/images/windowoption-example6.png new file mode 100644 index 0000000..71ff4c7 Binary files /dev/null and b/docs/images/windowoption-example6.png differ diff --git a/docs/images/windowoption-example7.png b/docs/images/windowoption-example7.png new file mode 100644 index 0000000..aa30046 Binary files /dev/null and b/docs/images/windowoption-example7.png differ diff --git a/docs/images/windowoption-example8.png b/docs/images/windowoption-example8.png new file mode 100644 index 0000000..b7f154d Binary files /dev/null and b/docs/images/windowoption-example8.png differ diff --git a/docs/images/windowoption-example9.png b/docs/images/windowoption-example9.png new file mode 100644 index 0000000..b1c2afe Binary files /dev/null and b/docs/images/windowoption-example9.png differ diff --git a/docs/zh/enhanced_controls.md b/docs/zh/enhanced_controls.md index acec57a..9784757 100644 --- a/docs/zh/enhanced_controls.md +++ b/docs/zh/enhanced_controls.md @@ -107,4 +107,60 @@ TextBox 和 PasswordBox 现在可以通过 Placeholder 属性来设置占位符. ``` -![圆角裁剪示例效果](/images/borderclip-example.png) \ No newline at end of file +![圆角裁剪示例效果](/images/borderclip-example.png) + +## 平滑滚动 + +如果你使用 WPF Suite 提供的 ScrollViewer, 那么对于使用鼠标的内容滚动, 会有更平滑的效果. + +| 附加属性 | 类型 | 描述 | +| --- | --- | --- | +| ScrollWithWheelDelta | bool | 通过 Wheel 事件的 delta 值决定滚动距离, 此选项用于优化触摸板滚动效果, 默认为 true | +| EnableScrollingAnimation | bool | 启用滚动动画, 决定使用鼠标进行滚动时是否使用缓动的效果, 默认为 true, 并且此选项要求 ScrollWithWheelDelta 设为 true, 否则不起作用 | +| ScrollingAnimationDuration | Duration | 滚动动画的时长, 默认为 250ms | +| MouseScrollDeltaFactor | double | 当使用鼠标进行滚动时, 滚动 Delta 值的乘数. 改变此值可以变更滚动速度与方向, 默认为 1 | +| TouchpadScrollDeltaFactor | double | 当使用触摸板进行滚动时, 滚动 Delta 值的乘数. 改变此值可以变更滚动速度与方向, 默认为 1 | +| AlwaysHandleMouseWheelScrolling | bool | 总是处理鼠标 Wheel 事件的滚动, 当鼠标滚轮滚动时则滚动 ScrollViewer 内容. 默认为 true | + +{: .tip } +> 将 AlwaysHandleMouseWheelScrolling 设置为 false 时, ScrollViewer 的滚动效果将不会应用于 TextBox 上 + +使用示例: +{: .fw-300} + +```xml + + 省略内容... + +``` + +![ScrollViewer 示例效果](/images/scrollviewer-example.webp) + +## 触摸模拟 + +原生的 WPF 是无法使用笔对 ScrollViewer 进行滚动的, 如果你想要通过笔来滚动, 可以使用 "触摸设备模拟". 通过笔来模拟一个触摸设备, 实现笔滚动. + +| 附加属性 | 类型 | 描述 | +| --- | --- | --- | +| StylusTouchDevice.Simulate | bool | 是否将笔模拟为触摸设备, 默认为 false | +| StylusTouchDevice.MoveThreshold | double | 移动阈值, 笔在移动超过指定的距离之后, 才会将移动汇报为触摸移动, 默认为 3 | +| MouseTouchDevice.Simulate | bool | 是否将鼠标模拟为触摸设备, 默认为 false | +| MouseTouchDevice.MoveThreshold | double | 移动阈值, 笔在移动超过指定的距离之后, 才会将移动汇报为触摸移动, 默认为 3 | + +{: .tip } +> 如果你将移动阈值设为 0, 那么你将无法通过笔来进行点击 ScrollViewer 内的控件, 因为笔总是存在抖动的, 触摸移动会进行 ScrollViewer 的滚动, 从而打断点击这一动作. +> +> 所以, 根据你想要的 "精度", 适当调整 "移动阈值". +> (很多程序对于这个都有一个较大的阈值, 例如 5px, 甚至 10px 或更多) + +使用示例: +{: .fw-300} + +```xml + + 省略内容... + +``` + +![模拟触摸示例效果](/images/simulatetouch-example.webp) \ No newline at end of file diff --git a/docs/zh/index.md b/docs/zh/index.md index d37d162..176beb1 100644 --- a/docs/zh/index.md +++ b/docs/zh/index.md @@ -13,7 +13,7 @@ WPF Suite 为 WPF 拓展了一些基础但必备的功能, 能够极大的提升 {: .fs-6 .fw-300 } -[快速开始](#getting-started){: .btn .btn-primary .fs-5 .mb-4 .mb-md-0 .mr-2 } +[快速开始](#快速开始){: .btn .btn-primary .fs-5 .mb-4 .mb-md-0 .mr-2 } [在 GitHub 上查看](https://github.com/OrgEleCho/EleCho.WpfSuite){: .btn .fs-5 .mb-4 .mb-md-0 } --- diff --git a/docs/zh/transition_effects.md b/docs/zh/transition_effects.md new file mode 100644 index 0000000..a2175b1 --- /dev/null +++ b/docs/zh/transition_effects.md @@ -0,0 +1,201 @@ +--- +title: 过渡效果 +layout: default +nav_order: 4 +permalink: /zh/transition-effects +parent: 中文文档 +--- + +# 过渡效果 +{: .fs-9 } + +当内容切换时, 执行一个过渡效果, 例如淡入淡出, 或者滑入滑出, 能够让程序美观许多. +{: .fs-6 .fw-300 } + +--- + +下面是有关 WPF Suite 中过渡动画的介绍 + +## IContentTransition + +表示一个内容过渡效果的接口 + +定义 +{: .fw-300} + +```cs +/// +/// Content transition +/// +public interface IContentTransition +{ + /// + /// Run the content transition + /// + /// Container UIElement + /// Old content UIElement + /// New content UIElement + /// This transition is forward + /// Cancellation token + /// + public Task Run( + FrameworkElement container, + FrameworkElement? oldContent, + FrameworkElement? newContent, + bool forward, + CancellationToken cancellationToken); +} + +``` + +下面是一些内置的过渡效果: + +| 类名 | 描述 | +| --- | --- | +| FadeTransition | 淡入淡出效果, 通过对 Opacity 运行动画实现 | +| SlideTransition | 滑动过渡效果, 通过设置 RenderTransform, 对 TranslateTransform 运行动画实现 | +| RotateTransition | 旋转过渡效果, 通过设置 RenderTransform, 对 RotateTransform 运行动画实现 | +| SlideFadeTransition | 淡入淡出与滑动过渡效果的结合 | +| RotateFadeTransition | 淡入淡出与旋转过渡效果的结合 | + +## TransitioningContentControl + +允许使用过渡动画的 ContentControl 实现. 继承自 Control. + +| 属性 | 类型 | 描述 | +| Content | object | 内容, 默认为 null | +| ContentTemplate | DataTemplate | 内容的模板, 默认为 null | +| ContentTemplateSelector | DataTemplateSelector | 内容的模板选择器, 默认为 null | +| Transition | IContentTransition | 内容切换所使用的过渡效果, 默认为 null | +| CornerRadius | CornerRadius | 圆角边缘半径 | + +{: .warning } +> TransitioningContentControl 并不继承自 ContentControl + +使用示例 +{: .fw-300} + +```xml + + + + + + + +``` + +```cs +private void Button_Click(object sender, RoutedEventArgs e) +{ + buttonContentControl.Content = System.IO.Path.GetRandomFileName(); +} +``` + +![过渡演示1](/images/transition-example1.webp) + +更复杂的使用 +{: .fw-300} + +```xml + + + + + + + + + + + + + + + +``` + +```cs +[ObservableProperty] +[NotifyPropertyChangedFor(nameof(CurrentImageSource))] +private int _currentImageSourceIndex; + +[ObservableProperty] +private bool _transitionReverse; + +public ObservableCollection ImageSources { get; } = new() +{ + new BitmapImage(new Uri("pack://application:,,,/WpfTest;component/Assets/Banners/1.jpg")), + new BitmapImage(new Uri("pack://application:,,,/WpfTest;component/Assets/Banners/2.jpg")), + new BitmapImage(new Uri("pack://application:,,,/WpfTest;component/Assets/Banners/3.jpg")), + new BitmapImage(new Uri("pack://application:,,,/WpfTest;component/Assets/Banners/4.jpg")), + new BitmapImage(new Uri("pack://application:,,,/WpfTest;component/Assets/Banners/5.jpg")), +}; + +public ImageSource? CurrentImageSource => ImageSources[CurrentImageSourceIndex]; + +public WelcomePage() +{ + InitializeComponent(); + + DataContext = this; +} + +[RelayCommand] +public void GoPrev() +{ + TransitionReverse = true; + var prevIndex = CurrentImageSourceIndex; + if (prevIndex == 0) + prevIndex = ImageSources.Count; + + prevIndex--; + + CurrentImageSourceIndex = prevIndex; +} + +[RelayCommand] +public void GoNext() +{ + TransitionReverse = false; + CurrentImageSourceIndex = (CurrentImageSourceIndex + 1) % ImageSources.Count; +} +``` + +{: .tip } +> 这里的 ObservableProperty 和 RelayCommand 是使用了 CommunityToolkit.Mvvm 自动生成可观察属性与指令 + +![过渡演示2](/images/transition-example2.webp) + +## Frame + +WPF Suite 中提供的 Frame 控件也支持导航, 所以, 当你的程序是一个多页面程序时, 可以用过渡效果来使其更美观 + +| 属性 | 类型 | 描述 | +| --- | --- | ---- | +| CornerRadius | CornerRadius | 圆角边缘半径 | +| Transition | IContentTransition | 内容切换的过渡效果 | + +大致效果 +{: .fw-300} + +![过渡演示3](/images/transition-example3.webp) \ No newline at end of file diff --git a/docs/zh/value_converters.md b/docs/zh/value_converters.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/zh/window_options.md b/docs/zh/window_options.md new file mode 100644 index 0000000..84d445b --- /dev/null +++ b/docs/zh/window_options.md @@ -0,0 +1,303 @@ +--- +title: 窗口选项 +layout: default +nav_order: 4 +permalink: /zh/window-options +parent: 中文文档 +--- + +# 窗口选项 +{: .fs-9 } + +通过窗口选项, 你可以设置窗口的背景类型, 亮暗色主题, 标题栏可见性, 标题栏菜单按钮可见性等 +{: .fs-6 .fw-300 } + +--- + +下面是关于窗口选项的介绍 + +## WindowOption + +用于设置窗口选项的工具类 + +| 附加属性 | 类型 | 描述 | +| --- | --- | --- | +| Backdrop | WindowBackdrop | 背景类型, 可以是自动(Auto), 无(None), 云母(Mica), 亚克力(Acrylic)或备选云母(MicaAlt). 默认为 "自动" | +| Corner | WindowCorner | 窗口边缘类型, 可以是默认(Default), 无圆角(DoNotRound), 圆角(Round), 小圆角(RoundSmall), 默认为 "默认" | +| CaptionColor | WindowOptionColor | 窗体标题栏颜色, 可以是默认(Default), 无(None) 或任意自定义 RGB 颜色, 默认为 "默认" | +| TextColor | WindowOptionColor | 文字颜色, 即标题栏文字颜色, 可以是默认(Default), 无(None) 或任意自定义 RGB 颜色, 默认为 "默认" | +| BorderColor | WindowOptionColor | 边框颜色, 可以是默认(Default), 无(None) 或任意自定义 RGB 颜色, 默认为 "默认" | +| IsDarkMode | bool | 表示窗口是否是暗色模式, 默认为 false | +| AccentState | WindowAccentState | 窗口风格状态, 可以是无(None), 渐变(Gradient), 透明(Transparent), 模糊背景(BlurBehind), 亚克力模糊背景(AcrylicBlurBehind), 以及 HostBackdrop, 默认为 "无" | +| AccentBorder | bool | 表示当应用窗口风格(Accent)时, 是否带有边框, 默认为 true | +| AccentGradientColor | Color | 窗体风格的渐变色, 默认为 ScRGB(0.25, 1, 1, 1) | +| IsCaptionVisible | bool | 是否显示标题栏, 默认为 true | +| IsCaptionMenuVisible | bool | 是否显示标题栏的菜单, 其中包含应用图标, 以及最小化, 最大化和关闭按钮, 默认为 true | +| IsMinimumButton | bool | 表示一个 Visual 是否是窗体的最小化按钮, 用于自定义最小化按钮, 默认为 false | +| IsMaximumButton | bool | 表示一个 Visual 是否是窗体的最大化按钮, 用于自定义最大化按钮, 默认为 false | +| IsCloseButton | bool | 表示一个 Visual 是否是窗体的关闭按钮, 用于自定义关闭按钮, 默认为 false | + +## 在 Windows11 上设置窗口背景 + +如果系统版本大于等于 22621, 那么是可以通过 WindowOption.Backdrop 来设置窗口背景的. +注意别忘了将窗口背景设为 Transparent, 否则默认窗口的白色背景会遮挡你设置的背景. + +使用示例 +{: .fw-300} + +```xml + + + +``` + +![窗口选项示例1](/images/windowoption-example1.png) + +再将 `ws:WindowOption.Backdrop` 的值改为 `Acrylic`, 效果如下: + +![窗口选项示例2](/images/windowoption-example2.png) + +注意, 如果你需要使用 WindowChrome, 那么 GlassFrameThickness 表示的是背景效果所应用的厚度 + +由于 GlassFrameThickness 默认为 0, 所以你会发现背景效果没有了, 将它设置为 -1 (无限大)就可以重新看到背景了 + +```xml + + + + + +``` + +![窗口选项示例3](/images/windowoption-example3.png) + +{: .warning } +> 其实 Backdrop 还要求窗口 HwndSource 的 CompositionTarget.BackgroundColor 值为 Transparent, 所以如果你将它设为其他值, Backdrop 同样会失效. + +## 在 Windows11 上为窗口启用暗色模式 + +在系统版本 22000 上, 你可以为窗口启用暗色模式, 这样, 标题栏以及设置的窗口背景都会变成暗色. + +使用示例 +{: .fw-300} + +```xml + + + +``` + +![窗口选项示例4](/images/windowoption-example4.png) + +在亚克力背景窗口下也是如此 + +![窗口选项示例5](/images/windowoption-example5.png) + + + +## 在 Windows11 上设置颜色, 边框 + +设置标题栏颜色, 文字颜色, 窗口边缘样式和边框颜色可以在系统版本高于 22000 时使用. + +关闭圆角 +{: .fw-300} + +```xml + + + + + +``` + +![窗口选项示例6](/images/windowoption-example6.png) + +设置标题栏颜色, 文字颜色, 以及边框颜色 +{: .fw-300} + +```xml + + + +``` + +![窗口选项示例7](/images/windowoption-example7.png) + +## 在 Windows10 中使用亚克力 + +早在 Windows10, 就已经可以通过一个隐藏的 API "SetWindowCompositionAttribute" 来设置背景了. +唯一的缺点就是无法将亚克力拓展到标题栏区域. + +使用 AccentState 设置窗口背景为亚克力 +{: .fw-300} + +```xml + + + +``` + +![窗口选项示例8](/images/windowoption-example8.png) + +{: .warning } +> 注意, 如果你要使用 WindowChrome, 与 Backdrop 不同的是, AccentState 要求 GlassFrameThickness 必须为 0 +> 否则亚克力效果不会显示出来 + +当然, 通过任意方式去除标题栏, 你就可以得到一个干净的亚克力窗口了. 例如下面设置 `WindowStyle` 为 `None`, 设置 `ResizeMode` 为 `NoResize`. + +为亚克力去除标题栏 +{: .fw-300} + +```xml + + + +``` + +![窗口选项示例9](/images/windowoption-example9.png) + +{: .tip } +> 之所以窗口设置了 `WindowStyle` 为 `None` 却仍然有一个边框, 是因为 `AccentBorder` 默认为 true. +> 在底层使用 API 应用 Accent 时, 还是会为窗口添加一个边框的 + +当然, 使用 WindowChrome 去除标题栏也可以得到一个纯净的亚克力窗口, 而且还能保留窗体拖拽边框调整大小的功能. +只不过窗口的最小化, 最大化以及关闭按钮会消失. + +```xml + + + + + +``` + +![窗口选项示例10](/images/windowoption-example10.png) + +## 自定义窗口菜单按钮 + +如果你希望去除窗口的三个按钮, 并换成自定义的实现, 可以执行以下操作: + +1. 对 Window 设置 ws:WindowOption.IsCaptionMenuVisible 为 false, 以去除系统的标题菜单 +2. 为自定义的最大化按钮设置 ws:WindowOption.IsMaximumButton 为 true, 以正确响应系统行为 + +使用示例: +{: .fw-300} + +```xml + + + + + + + + + + + + + + + + + + +``` + +![窗口选项示例11](/images/windowoption-example11.png) + +如果你使用的是 Windows11 操作系统, 鼠标悬停在最大化按钮上, 也会正确显示出布局选项 + +![窗口选项示例12](/images/windowoption-example12.png) \ No newline at end of file