閱讀導(dǎo)航
- 前言
- 案例一
- 案例二
- 案例三(本文介紹的方式)
- 如何使用王滤?
- 控件如何開發(fā)的逻杖?
- 總結(jié)
1. 前言
案例一
站長(zhǎng)分享過 眾尋 大佬的一篇 WPF 簡(jiǎn)易新手引導(dǎo) 一文竭鞍,新手引導(dǎo)的效果挺不錯(cuò)的编振,如下圖:
該文給出的代碼未使用 MVVM 的開發(fā)方式宜狐,提示框使用的用戶控件肛搬、蒙版窗體樣式與后臺(tái)代碼未分離饭豹,但給大家分享了開發(fā)新手引導(dǎo)功能的一個(gè)參考鸵赖。
案例二
開源項(xiàng)目 AIStudio.Wpf.Controls,它的新手引導(dǎo)效果如下:
此開源項(xiàng)目也有參考上文(WPF 簡(jiǎn)易新手引導(dǎo))拄衰,并且重構(gòu)為 MVVM 版本它褪,方便綁定使用。
并且提示框顯示的位置還跟隨目標(biāo)控件在主窗體中的位置靈活變換翘悉,不至于顯示在蒙版窗體之外茫打,如下圖所示:
當(dāng)目標(biāo)控件右側(cè)空間足夠顯示引導(dǎo)提示框時(shí),引導(dǎo)提示框就顯示在目標(biāo)控件右側(cè)妖混;在右側(cè)空間不足時(shí)老赤,則將引導(dǎo)提示框顯示在目標(biāo)控件左側(cè):
案例三(本文介紹的方式)
站長(zhǎng)根據(jù)上面的開源項(xiàng)目 AIStudio.Wpf.Controls 做了一個(gè)自己的版本 Dotnet9WPFControls,去掉了上一步按鈕制市、增加標(biāo)題綁定抬旺、下一步按鈕內(nèi)容綁定、提示框樣式修改等祥楣,效果如下:
后面段落就介紹 怎么使用 Dotnet9WPFControls 添加新手引導(dǎo)功能开财,并簡(jiǎn)單提及這個(gè)自定義控件的開發(fā)細(xì)節(jié),主要原理還是看上文 WPF 簡(jiǎn)易新手引導(dǎo) 哈荣堰。
希望對(duì)有需要給自己的項(xiàng)目添加新手引導(dǎo)功能的朋友有一定幫助床未,通過此文你也能修改出滿足自己需求的效果。
2. 如何使用振坚?
2.1 創(chuàng)建一個(gè)WPF項(xiàng)目
使用 .NET 6|7 創(chuàng)建一個(gè)名為 "NewbieGuideDemo" 的 WPF 解決方案:
2.2 引入nuget包
- 添加Nuget包1: Dotnet9WPFControls
該包提供引導(dǎo)控件及其樣式薇搁,記得勾選“包括預(yù)發(fā)行版”,然后點(diǎn)擊安裝渡八。
- 添加Nuget包2:Prism.DryIoc
使用該包啃洋,主要是使用 Prism 封裝的一些 MVVM、IOC 功能屎鳍,方便協(xié)助開發(fā)宏娄。
添加上述兩個(gè)Nuget包后,項(xiàng)目工程文件定義如下:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net6.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<UseWPF>true</UseWPF>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Dotnet9WPFControls" Version="0.1.0-preview.2" />
<PackageReference Include="Prism.DryIoc" Version="8.1.97" />
</ItemGroup>
</Project>
2.3 添加樣式文件
打開 App.xaml
文件逮壁,引入 Dotnet9WPFControls 默認(rèn)主題文件:
<prism:PrismApplication
x:Class="NewbieGuideDemo.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="http://prismlibrary.com/">
<prism:PrismApplication.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/Dotnet9WPFControls;component/Themes/Dotnet9WPFControls.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</prism:PrismApplication.Resources>
</prism:PrismApplication>
注意上面的根節(jié)點(diǎn) <prism:PrismApplication />
孵坚,同時(shí)修改App.xaml.cs
文件,這里不做過多說明,具體使用請(qǐng)參考 Prism:
using Prism.DryIoc;
using Prism.Ioc;
using System.Windows;
namespace NewbieGuideDemo
{
public partial class App : PrismApplication
{
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
}
protected override Window CreateShell()
{
return Container.Resolve<MainWindow>();
}
}
}
2.4 定義引導(dǎo)信息
給主窗體 MainWindow
添加一個(gè) ViewModel 類:MainWindowViewModel.cs
:
using Dotnet9WPFControls.Controls;
using Prism.Mvvm;
using System.Collections.Generic;
namespace NewbieGuideDemo
{
public class MainWindowViewModel : BindableBase
{
private GuideInfo? _guide;
public GuideInfo Guide =>
_guide ??= new GuideInfo("快速添加新手引導(dǎo)", "這樣添加新手引導(dǎo)卖宠,或許比較優(yōu)雅");
public List<GuideInfo> Guides => new() {Guide};
}
}
在上面的 ViewModel 中巍杈,定義了一個(gè)引導(dǎo)屬性 Guide
,這個(gè)屬性是與提示框綁定展示:
- 第一個(gè)參數(shù)定義了引導(dǎo)提示框的標(biāo)題
“快速添加新手引導(dǎo)”
- 第二個(gè)參數(shù)定義了引導(dǎo)提示框的提示內(nèi)容
“這樣添加新手引導(dǎo)扛伍,或許比較優(yōu)雅”
第二個(gè)屬性 Guides
, 是一個(gè)引導(dǎo)信息列表筷畦,可綁定多個(gè)引導(dǎo)信息,點(diǎn)擊按鈕即會(huì)查看下一個(gè)引導(dǎo)刺洒,本示例為了演示鳖宾,只寫了一個(gè)引導(dǎo)。
2.5 界面綁定引導(dǎo)信息
先貼上 MainWindow.xaml
所有代碼:
<Window
x:Class="NewbieGuideDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:prism="http://prismlibrary.com/"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:dotnet9="https://dotnet9.com"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="Dotnet9 WPF新手引導(dǎo)功能" Width="800" Height="450"
prism:ViewModelLocator.AutoWireViewModel="True"
AllowsTransparency="True" Background="Transparent" WindowStyle="None"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d">
<Window.Resources>
<dotnet9:BindControlToGuideConverter x:Key="BindControlToGuideConverter" />
</Window.Resources>
<Border
Background="White" BorderBrush="#ccc" BorderThickness="1" MouseLeftButtonDown="Border_MouseDown">
<Grid>
<Button HorizontalAlignment="Center" VerticalAlignment="Center" Content="點(diǎn)擊測(cè)試新手引導(dǎo)">
<dotnet9:GuideHelper.GuideInfo>
<MultiBinding Converter="{StaticResource BindControlToGuideConverter}">
<Binding RelativeSource="{RelativeSource Self}" />
<Binding Path="Guide" />
</MultiBinding>
</dotnet9:GuideHelper.GuideInfo>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:ChangePropertyAction PropertyName="Display" TargetName="GuideControl" Value="True" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
<dotnet9:GuideControl x:Name="GuideControl" Guides="{Binding Guides}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<i:ChangePropertyAction PropertyName="Display" Value="True" />
</i:EventTrigger>
</i:Interaction.Triggers>
</dotnet9:GuideControl>
</Grid>
</Border>
</Window>
下面快速過一遍逆航。
2.5.1 引入的命名空間說明
看上面的代碼鼎文,引入了 dotnet9
和 prism
、i
三個(gè)命名空間:
-
dotnet9
命名空間
引入引導(dǎo)控件 GuideControl
及 轉(zhuǎn)換器 BindControlToGuideConverter
纸泡。
-
prism
命名空間
主要用途在 prism:ViewModelLocator.AutoWireViewModel="True"
這句代碼漂问,將視圖 MainWindow.xaml
與 MainWindowViewModel.cs
進(jìn)行綁定,有興趣可以看 Prism 源碼女揭,了解視圖是如何發(fā)現(xiàn)ViewModel的約定規(guī)則。
-
i
命名空間
主要用此命名空間下的觸發(fā)器栏饮,事件觸發(fā)屬性更改吧兔。
2.5.2 幾處關(guān)鍵代碼簡(jiǎn)單說明
上面代碼貼的是引導(dǎo)控件(自定義控件)的使用方式(站長(zhǎng)注:Dotnet9WPFControls 中還有引導(dǎo)窗體的方式,本文不做說明袍嬉,要不然太占篇幅了境蔼,請(qǐng)查看控件Demo GuideWindowView)。
a: 將引導(dǎo)控件加到容器最上層
先關(guān)注后面的幾行代碼:
<Grid>
<!--這里省略業(yè)務(wù)控件布局-->
<dotnet9:GuideControl x:Name="GuideControl" Guides="{Binding Guides}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<i:ChangePropertyAction PropertyName="Display" Value="True" />
</i:EventTrigger>
</i:Interaction.Triggers>
</dotnet9:GuideControl>
</Grid>
- 將引導(dǎo)控件加到
Grid
容器最后伺通,意圖是讓引導(dǎo)控件顯示在所有控件的最上層(同一層級(jí)添加了多個(gè)控件箍土,如果位置重疊,那么后加入的控件會(huì)顯示在先添加的控件上方罐监,呈現(xiàn)遮擋效果)吴藻; - 綁定了前面
MainWindowViewModel
中定義的引導(dǎo)信息列表Guides
,點(diǎn)擊下一步按鈕(本文顯示為我知道了
)時(shí)弓柱,會(huì)按列表添加順序切換引導(dǎo)信息沟堡; - 使用
i:Interaction.Triggers
實(shí)現(xiàn)控件加載完成時(shí),自動(dòng)顯示引導(dǎo)提示信息矢空,見上面的 示例三效果航罗;
b:綁定目標(biāo)控件與引導(dǎo)屬性
目標(biāo)控件的引導(dǎo)屬性與目標(biāo)控件引用綁定
,引導(dǎo)界面顯示時(shí)通過目標(biāo)控件計(jì)算出目標(biāo)控件的位置和大小屁药,準(zhǔn)確將目標(biāo)控件標(biāo)識(shí)出來粥血,引導(dǎo)提示框定位也才能正確設(shè)置:
<dotnet9:BindControlToGuideConverter x:Key="BindControlToGuideConverter" />
<Button HorizontalAlignment="Center" VerticalAlignment="Center" Content="點(diǎn)擊測(cè)試新手引導(dǎo)">
<dotnet9:GuideHelper.GuideInfo>
<MultiBinding Converter="{StaticResource BindControlToGuideConverter}">
<Binding RelativeSource="{RelativeSource Self}" />
<Binding Path="Guide" />
</MultiBinding>
</dotnet9:GuideHelper.GuideInfo>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:ChangePropertyAction PropertyName="Display" TargetName="GuideControl" Value="True" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
如上代碼引入 BindControlToGuideConverter 轉(zhuǎn)換器
, 該轉(zhuǎn)換器是個(gè)黏合類,將目標(biāo)控件的引用添加到引導(dǎo)對(duì)象上,轉(zhuǎn)換器具體定義如下:
public class BindControlToGuideConverter : IMultiValueConverter
{
public object? Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values.Length < 2)
{
return null;
}
var element = values[0] as FrameworkElement;
var guide = values[1] as GuideInfo;
if (guide != null)
{
guide.TargetControl = element;
}
return guide;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
目標(biāo)控件的引用賦值給引導(dǎo)對(duì)象的 TargetControl
屬性复亏。
Demo代碼完畢绢彤,直接運(yùn)行項(xiàng)目,效果如下蜓耻,源碼在這 NewbieGuideDemo:
3. 控件如何開發(fā)的茫舶?
關(guān)于原理,WPF 簡(jiǎn)易新手引導(dǎo) 這篇介紹的不錯(cuò)刹淌,可以先看看饶氏。
關(guān)于本示例的實(shí)現(xiàn)方式,暫時(shí)不做太多說明有勾,詳細(xì)請(qǐng)直接查看源碼 Dotnet9WPFControls疹启,本文后半截大概提一下。
代碼組織結(jié)構(gòu)如下:
- GuideInfo:定義引導(dǎo)信息類蔼卡,如標(biāo)題喊崖、內(nèi)容、下一步按鈕顯示內(nèi)容雇逞。
- GuideHintControl:引導(dǎo)提示框控件荤懂,顯示引導(dǎo)標(biāo)題、引導(dǎo)內(nèi)容塘砸、下一步按鈕节仿,即
GuideInfo
綁定的控件。 - GuideControl:引導(dǎo)控件掉蔬,用于目標(biāo)控件無法獲取到自己的窗體這種(即無法獲取在窗體中的位置)廊宪,比如您開發(fā)的程序?yàn)榈谌匠绦虿寮@種,上面的代碼即是使用此引導(dǎo)控件實(shí)現(xiàn)的效果女轿。
- GuideWindow:引導(dǎo)窗體箭启,
GuideControl
引導(dǎo)控件的相互補(bǔ)充。 - GuideControlBase:引導(dǎo)控件輔助類
- BindControlToGuideConverter:引導(dǎo)信息與引導(dǎo)的目標(biāo)控件綁定轉(zhuǎn)換器
- GuideHelper:引導(dǎo)幫助類蛉迹,綁定目標(biāo)控件的引導(dǎo)信息使用傅寡,外加一個(gè)顯示 引導(dǎo)窗體 的靜態(tài)命令。
- Guide.xaml:定義引導(dǎo)遮罩層(
GuideControl
和GuideWindow
)婿禽、引導(dǎo)提示框(GuideHintControl
)樣式的資源文件赏僧,定義外觀請(qǐng)改這個(gè)文件
重點(diǎn):
a)
GuideControlBase
GuideControlBase
是 GuideControl
和 GuideWindow
的輔助類,因?yàn)檫@兩個(gè)類實(shí)現(xiàn)的功能是類似的扭倾,所以封裝大部分功能在 GuideControlBase
中淀零,比如將目標(biāo)控件區(qū)域從遮罩層 Clip 出來,并將 GuideHintControl
提示框控件添加到遮罩層之上膛壹,顯示出新手引導(dǎo)的效果驾中。
b)
GuideControl 和 GuideWindow
GuideControl
是用于顯示在包含目標(biāo)控件的容器內(nèi)使用的唉堪,GuideControl
放置的容器不一定是目標(biāo)控件的直接容器,可以有嵌套肩民,比如目標(biāo)控件在ListBox
子項(xiàng)ListBoxItem
內(nèi)唠亚,而引導(dǎo)控件GuideControl
可以在ListBox
的外層容器之上;
GuideWindow
用于貼在目標(biāo)控件所在的窗體上持痰,GuideWindow
作為目標(biāo)控件窗體的子窗體灶搜,Show()
在目標(biāo)控件窗體上,不能使用ShowDialog()
的方式(為啥工窍?ShowDialog()
會(huì)使除引導(dǎo)窗體之外的窗體處于無效狀態(tài)(disable))割卖。
這兩種方式(GuideControl 和 GuideWindow)總體呈現(xiàn)效果是一樣的,目標(biāo)控件所在的窗體是自定義窗體患雏,Demo能正常顯示下面的效果鹏溯,普通窗體需要對(duì)目標(biāo)控件 Clip 的位置和提示框的位置進(jìn)行偏移處理,修改位置見 GuideControl
和 GuideWindow
的方法 ShowGuide(FrameworkElement? targetControl, GuideInfo guide)
淹仑。
控件帶的兩個(gè)新手引導(dǎo)Demo如下:
新手引導(dǎo)Demo一
GuideControl方式丙挽,站長(zhǎng)推薦,即以控件的方式顯示新手引導(dǎo)匀借,點(diǎn)擊看代碼:
新手引導(dǎo)Demo二
GuideWindow方式颜阐,即以子窗體的方式顯示新手引導(dǎo),點(diǎn)擊看代碼:
詳細(xì)開發(fā)不展開說了怀吻,一切都在代碼中瞬浓。
4. 總結(jié)
前面寫了不少,其實(shí)不多蓬坡,謝謝開源帶來的力量。
- 參考文章:WPF 簡(jiǎn)易新手引導(dǎo)
- 參考開源項(xiàng)目:AIStudio.Wpf.Controls
- 本文Demo
NewbieGuideDemo
:Github磅叛、Gitee - Dotnet9Controls 新手引導(dǎo)Demo一 源碼:Github屑咳、Gitee
- Dotnet9Controls 新手引導(dǎo)Demo二 源碼
GuideWindowView
:Github、Gitee - Dotnet9Controls控件:Github弊琴、Gitee