博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[WPF自定义控件库] 给WPF一个HyperlinkButton
阅读量:5044 次
发布时间:2019-06-12

本文共 3474 字,大约阅读时间需要 11 分钟。

1. 在WPF怎么在UI上添加超级链接

这篇文章的目的是介绍怎么在WPF里创建自定义的HyperlinkButton控件。很神奇的,WPF居然连HyperlinkButton都没有,不过它提供了另一种方式用于在UI上添加超级链接:

Click here
private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e){    Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri));    e.Handled = true;}

1.png

如果需要在超级链接里放图片或其它东西,代码如下:

2.png

这真是很怪,为什么要先有TextBlock然后再有Hyperlink,为什么TextBlock里面可以放Image,这真的很难理解。

2. Hyperlink怎么设置样式

要给Hyperlink设置样式也有点难搞,因为在对象树上Hyperlink毫无存在感,所以也没办法使用Blend创建它的Style。

4.png

我的做法是用ILSpy拿到它的Style再修改。例如我需要MouseOver状态下文字不是红色而是紫色,可以使用下面的Style:

3.gif

3. 自定义一个HyperlinkButton

自定义一个HyperlinkButton有什么好处?因为用起来简单啊,不需要CodeBehind的代码,绑定内容和Command都简单,而且XAML更加简单直观。在外观上,很多人喜欢Hyperlink下面的横线在鼠标MouseOver才显示,另外如上面图片所示插入图片后Hyperlink下面有一条横线,这很奇怪但又取消不了。

Silverlight和UWP都很普通地提供了HyperlinkButton。不过在Silverlight中为了显示MouseOver时出现的下划线使用了两层内容,一层用于正常显示(contentPresenter),另一层用于显示下划线(UnderlineTextBlock),如果HyperlinkButton的内容是文本,当MouseOver时UnderlineTextBlock就会显示UnderlineTextBlock。

但是这样效果十分差,重叠在一起的文本看上去变得模糊。

5.gif

而UWP中的HyperlinkButton的下划线是代码里写死的,大概是这样:

if (VisualTreeHelper.GetChildrenCount(contentPresenter) == 1 && VisualTreeHelper.GetChild(contentPresenter, 0) is TextBlock textBlock){    textBlock.TextDecorations = Text.TextDecorations.Underline;}

而且它还没有提供任何方法关闭或修改这个下划线。我很讨厌这种代码里控制样式的行为,UI和代码应该足够解耦。UWP很多使用代码控制样式的行为,通常宣称理由是为了性能,但Button是整个UI中最不需要性能的部分,毕竟一个UI中不可能有几百个Button,就算有几百个HyperlinkButton,现代的UI框架也不可能仅仅因为下划线就导致性能下降。所以我认为没必要在代码里控制下划线的显示。

而无论Silverlight还是UWP,只要HyperlinkButton的Content不是纯文本就不能显示下划线,这应该也算一个功能缺陷。

我在Kino.Toolkit.Wpf里也提供了一个HyperlinkButton,使用方式如下:

不仅使用起来简单,HyperlinkButton的代码也很简单。

public Uri NavigateUri{    get => GetValue(NavigateUriProperty) as Uri;    set => SetValue(NavigateUriProperty, value);}protected override void OnClick(){    base.OnClick();    if (NavigateUri != null && NavigateUri.IsAbsoluteUri)    {        try        {            Process.Start(new ProcessStartInfo(NavigateUri.AbsoluteUri));        }        catch (Win32Exception)        {        }    }}

上面是HyperlinkButton的核心代码,需要一个HyperlinButton被点击后导航到的NavigateUri属性,以及在OnClick函数中使用Process.Start在新进程打开目标Uri。关于Process和ProcessStartInfo的具体用法可见本文最后给出的参考链接。

XAML的部分基本上照抄Silverlight的HyperlinkButton,不过关于下划线的处理稍有不同。

上面是HyperlinkButton的DefaultStyle的大致内容。Pressed和Disabled的状态使用VisualState控制外观,这部分略过。在ControlTemplate.Resources中添加了一个TextBlock的全局样式,里面的DataTrigger设置为当鼠标进入父节点的HyperlinkButton时TextDecorations变为Underline。运行效果如下:

38937-20190820103534021-181456441.gif

在下面的ContentPresenter.Resources中也添加了同样的DataTrigger,这是为了应对下面这种情况:

这里TextBlock不是HyperlinkButton的逻辑树上的子元素,或许就是因为这样它不能应用ControlTemplate.Resources中的TextBlock的全局样式。

最后记得在最外层的Grid上设置Background:

如果不设置一个透明的background的话,就只有文字部分能捕获鼠标点击事件,这样HyperlinkButton就会很难点中。(我记得在UWP中就没有这个问题,UWP的ContentPresenter自带透明背景)

4. 结语

HyperlinkButton明明很重要但WPF又不提供,幸好自己写起来也很简单。

这么简单的一个控件我也能水这么长的文章,我也很佩服我自己。

5. 参考

6. 源码

转载于:https://www.cnblogs.com/dino623/p/WPF_HyperlinkButton.html

你可能感兴趣的文章
二叉树的遍历 - 数据结构和算法46
查看>>
类模板 - C++快速入门45
查看>>
centos7 搭建vsftp服务器
查看>>
RijndaelManaged 加密
查看>>
Android 音量调节
查看>>
HTML&CSS基础学习笔记1.28-给网页添加一个css样式
查看>>
windows上面链接使用linux上面的docker daemon
查看>>
Redis事务
查看>>
Web框架和Django基础
查看>>
python中的逻辑操作符
查看>>
CSS兼容性常见问题总结
查看>>
HDU 1548 A strange lift (Dijkstra)
查看>>
每天一个小程序—0005题(批量处理图片大小)
查看>>
C# 启动进程和杀死进程
查看>>
tcp实现交互
查看>>
IIS的各种身份验证详细测试
查看>>
JavaScript特效源码(3、菜单特效)
查看>>
聊聊、Zookeeper Linux 单服务
查看>>
Linux常用命令总结
查看>>
yii模型ar中备忘
查看>>