WPF 简易新手引导
这两天不忙,所以,做了一个简易的新手引导小Demo。因为,不是项目上应用,所以,做的很粗糙,也就是给需要的人,一个思路而已。
新手引导功能的话,就是告诉用户,页面上操作的顺序,第一步要做什么,第二步要做什么,以此类推,然后,最终关闭新手引导页面。
以我的习惯,还是先给大家看看效果。
效果展示的很简单,就是将要告诉用户操作的控件做一个提示。
要实现这个功能化,那思路就是大概以下几项:
一、遮罩窗体
将主窗体进行遮罩,半透明的效果,常用的做遮罩的话,一般是设置一个底色,然后设置透明度,类似于这篇博客http://blog.csdn.net/cmis7645/article/details/7781990,但是,在实际的操作用就会遇到问题,如果使用正常的半透明方式的话,黄色框部分,是不发透出白色的主窗体内容的,因为已经有底色了,所以,本文使用的半透明方法是Clip的擦除,效果如下图,参考的博客http://blog.csdn.net/feitiankoulan/article/details/25201593
先设置一个透明的窗体
<Window x:Class="SimpleGuide.GuideWin" 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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:SimpleGuide" mc:Ignorable="d" Title="GuideWin" WindowStyle="None" AllowsTransparency="True" x:Name="gw" Background="#01FFFFFF" ShowInTaskbar="False">
<Grid>
<Border x:Name="bor" BorderBrush="White" BorderThickness="2" CornerRadius="5" Opacity="0.8">
<Border.Effect>
<DropShadowEffect ShadowDepth="0" Color="#FF414141" BlurRadius="8" />
</Border.Effect>
<Border Background="Black" Opacity="0.5" Margin="0" CornerRadius="5" />
</Border>
<Canvas x:Name="can"></Canvas>
</Grid>
</Window>
从XAML的代码中,可以看到Background这个属性没用头“Transparent”而用的是“#01FFFFFF”,因为如果用Transparent的话,那真的就是透明了,可以直接点击到主窗体里的控件,这个是我们所不希望的,所以,设置了“#01FFFFFF”,一个近乎透明的颜色。
二、显示要操作的控件
既然要对某个控件进行指引的话,那就要把控件先给圈起来,圈起来的首要任务,就是获得控件在当前窗体的坐标位置。
Point point = fe.TransformToAncestor(Window.GetWindow(fe)).Transform(new Point(, ));
当获取完坐标以后,则需要将控件给圈起来,我的方法,就是取当前的坐标-5,宽和高+10,来绘制一个空白的区域,其实,这个部分应该是指擦除
RectangleGeometry rg1 = new RectangleGeometry();
rg1.Rect = new Rect(point.X - , point.Y - , fe.ActualWidth + , fe.ActualHeight + );
borGeometry = Geometry.Combine(borGeometry, rg1, GeometryCombineMode.Exclude, null);
三、绘制一个指引的UC
指引UC,设计起来就比较方便了,样子其实挺简单的
就是用Path,绘制一个范围,但是虚线框,最开始的想法是用Line去做,但是感觉太费事了,就直接用的StrokeDashArray这个属性,Stroke是Path本身的边框线,当然,真的是边框,所以,又不好设置Margin或者Padding,所以,最后的做法,就是,在外层又绘制了一个区域,只是这个区域不包含边框线而已,填充色相同
<Path Fill="#FF2FBEED">
<Path.Data>
<GeometryGroup>
<PathGeometry Figures="M 8,22 A 12,12 0 1 1 22,8 L 102 8 L 102 62 L 8 62 Z" />
</GeometryGroup>
</Path.Data>
</Path>
<Path StrokeThickness="1" Stroke="White" StrokeDashArray="2,1" Fill="#FF2FBEED">
<Path.Data>
<GeometryGroup>
<PathGeometry Figures="M 10,20 A 10,10 0 1 1 20,10 L 100 10 L 100 60 L 10 60 Z" />
</GeometryGroup>
</Path.Data>
</Path>
显示内容的部分是一个Textblock,当时遇到了一个问题,就是换行问题,Textblock必须要有Width,才会换行,但是由于最外层是Viewbox,所以,尝试过获取UC的Width或者ActualWidth,都不行,所以,最后的解决办法是,传入一个窗体的宽度和高度进来,而不是在外部设置此UC的宽和高。
public HintUC(string xh, string content, Visibility vis = Visibility.Visible, int width = , int height = )
{
InitializeComponent();
this.Width = width;
this.Height = height;
this.tb_nr.Width = width / ; this.tb_xh.Text = xh;
this.tb_nr.Text = content;
this.btn_next.Visibility = vis;
}
四、下一步的触发
触发下一步,相当于是子控件调用主控件的事件,这样的话,就是写一个委托,在主窗体里去实现具体的方法。
private void show(int xh, FrameworkElement fe, string con, Visibility vis = Visibility.Visible)
{
Point point = fe.TransformToAncestor(Window.GetWindow(fe)).Transform(new Point(, ));//获取控件坐标点 RectangleGeometry rg = new RectangleGeometry();
rg.Rect = new Rect(, , this.Width, this.Height);
borGeometry = Geometry.Combine(borGeometry, rg, GeometryCombineMode.Union, null);
bor.Clip = borGeometry; RectangleGeometry rg1 = new RectangleGeometry();
rg1.Rect = new Rect(point.X - , point.Y - , fe.ActualWidth + , fe.ActualHeight + );
borGeometry = Geometry.Combine(borGeometry, rg1, GeometryCombineMode.Exclude, null); bor.Clip = borGeometry; HintUC hit = new HintUC(xh.ToString(), con, vis);
Canvas.SetLeft(hit, point.X + fe.ActualWidth + );
Canvas.SetTop(hit, point.Y + fe.ActualHeight + );
hit.nextHintEvent -= Hit_nextHintEvent;
hit.nextHintEvent += Hit_nextHintEvent;
can.Children.Add(hit); index++;
}
private void Hit_nextHintEvent()
{
if (list[index - ] != null)
{
can.Children.Clear();
}
if (index == list.Count - )
show(index + , list[index].Uc, list[index].Content, Visibility.Collapsed);
else
show(index + , list[index].Uc, list[index].Content);
}
我们要在外部声明一个index的变量来记录当前的List集合的索引,首先要判断,当前的内容里,是否不为空,如果是的话,要清除掉,如果不清除的话,就会看到一堆的提示框,然后,判别是否是List集合里的最后一个控件了,如果是的话,那就不再显示“下一步按钮了”。
五、扩展部分
由于是一个小Demo,所以发现了一些问题,但是就没有再解决了,例如如果主窗体不是无边框的话,取值定位会有问题。
这是由于弹出的引导窗体获取了主窗体的大小,但是Point去获取控件坐标位置的时候,主窗体是不包含头部的,由于遮罩没有头部,所以定位出错了,这个我还没有找到好的解决办法,如果有大神知道如何解决的话,请赐教,谢谢了。

显示引导内容的部分,也可以换成一个Grid,这样的话,就可以传入UserControl了,有兴趣的朋友可以自行修改。
源码:Demo
WPF 简易新手引导的更多相关文章
- WPF 简易手风琴 (ListBox+Expander)
概述 之前听说很多大神的成长之路,几乎都有个习惯--写博文,可以有效的对项目进行总结.从而提高开发的经验.所以初学WPF的我想试试,顺便提高一下小学作文的能力.O(∩_∩)O哈哈~ 读万卷书不如行万里 ...
- WPF简易北京地铁效果图
这个是百度地图上北京地铁的地址http://map.baidu.com/?subwayShareId=beijing,131,我们先看下百度上面的效果图 我要实现的内容比较简单,就是绘制这些图,和在地 ...
- WPF 简易的跑马灯效果
最近项目上要用到跑马灯的效果,和网上不太相同的是,网上大部分都是连续的,而我们要求的是不连续的. 也就是是,界面上就展示4项(展示项数可变),如果有7项要展示的话,则不断的在4个空格里左跳,当然,衔接 ...
- WPF 简易的喷泉效果
这两天领导让我做个喷泉的效果,要把一个个UserControl从一个位置喷出,然后,最后落在最终需要在的位置. 喷泉效果说白了,就是两个步骤:1.放大,从0放大到需要的倍数:2.缩小,平移,从放大的倍 ...
- WPF 简易进度条效果
最近做一个项目,看到以前同事写的进度条效果不错,所以,拿来简化了下,不炫,但是项目中还是够用的. 还是,先来看下调用以后的效果 1.因为ProgressbBar的Foreground显示不得不一样,所 ...
- WPF简易聊天室
一.聊天界面如下
- WPF|快速添加新手引导功能(支持MVVM)
阅读导航 前言 案例一 案例二 案例三(本文介绍的方式) 如何使用? 控件如何开发的? 总结 1. 前言 案例一 站长分享过 眾尋 大佬的一篇 WPF 简易新手引导 一文,新手引导的效果挺不错的,如下 ...
- WPF Timeline简易时间轴控件的实现
原文:WPF Timeline简易时间轴控件的实现 效果图: 由于整个控件是实现之后才写的教程,因此这里记录的代码是最终实现后的,前后会引用到其他的一些依赖属性或者代码,需要阅读整篇文章. 1.确定T ...
- 【WPF on .NET Core 3.0】 Stylet演示项目 - 简易图书管理系统(4) - 图书列表界面
在前三章中我们完成了登录窗口, 并掌握了使用Conductor来切换窗口, 但这些其实都是在为我们的系统打基础. 而本章中我们就要开始开发系统的核心功能, 即图书管理功能了. 通过本章, 我们会接触到 ...
随机推荐
- Geohash-》基本使用
我把类文件放到了以上这个路径,在要使用的文件引入使用. 以下是测试代码, 1.先实例化类 2.再调用函数 3.这个函数返回GeoHash编码
- hadoop+hive+spark搭建(二)
上传hive软件包到任意节点 一.安装hive软件 解压缩hive软件包到/usr/local/hadoop/目录下 重命名hive文件夹 在/etc/profile文件中添加环境变量 export ...
- onoffswitch-checkbox
@foreach (EmailSubscription es in Model) { if(true){ <div class="onoffswitch"> ...
- c语言贪吃蛇详解5.GameOver功能与显示成绩
c语言贪吃蛇详解5.GameOver功能与显示成绩 以前我们已经做出来了一个能吃东西变长的蛇.不过它好像不会死... 现在就来实现一下game over的功能吧. 写个函数判断蛇是否撞到自己或者撞到墙 ...
- boltdb的实现
整个代码不是很复杂,可以从代码中理解如何实现. 特点:btree,很小巧,但实现了完整事务机制,稳定,即使丢电也不会导致数据库错误. 整个结构如下: meta page (前两页) --- > ...
- JavaScript(二)基本概念
JS区分大小写 html/css 中 标签选择器不区分大小写 id class 选择器区分大小写 其中属性名 属性名 属性值 不区分大小写 行间事件 onclick 等 不区分大小写 而 执 ...
- C++雾中风景6:拷贝构造函数与赋值函数
在进行C++类编写的过程之中,通常会涉及到类的拷贝构造函数与类的赋值函数.初涉类编写的代码,对于两类函数的用法一直是挺让人困惑的内容.这篇文章我们会详细来梳理拷贝构造函数与赋值函数的区别. 1.调用了 ...
- H5中的web worker示例demo分析
web worker 是运行在后台的 JavaScript,不会影响页面的性能. 什么是 Web Worker? 当在 HTML 页面中执行脚本时,页面的状态是不可响应的,直到脚本已完成. web w ...
- centos7配置阿里云yum源
1)下载repo文件 wget http://mirrors.aliyun.com/repo/Centos-7.repo 2)备份并替换系统的repo文件 cp Centos-7.repo /etc/ ...
- RED_HAWK:基于PHP实现的信息收集与SQL注入漏洞扫描工具
无事早上就去逛freebuf看到一款不错的工具,打算介绍给大家 RED_HAWK:基于PHP实现的信息收集与SQL注入漏洞扫描工具 RED HAWK 最新版本:v1.0.0[2017年6月11日] 下 ...