[WPF][Rubyer] 写一个自己的 UI 库 (二) - Icon
前言
制作 WPF 的图标包,主要介绍从 iconfont 下载的图标包导入到 WPF 使用;
1. 添加文件
Ruyber 下添加 自定义控件(WPF) Icon.cs、类 IconType.cs、类 IconDatas.cs
Rubyer.Themes 下添加 资源字典(WPF) Icon.xaml

2.下载图标
iconfont 查找自己喜欢的图标包,浏览器 F12 => Console => 输入下列代码回车,添加所有图标到购物车
var span = document.querySelectorAll('.icon-cover');
for (var i = 0, len = span.length; i < len; i++) {
console.log(span[i].querySelector('span').click());
}
添加到项目

下载到本地

只解压 iconfont.ttf 到项目的 Assets 文件目录下


3.应用图标
在 BaseStyle.xaml 里添加标签
<!--IconFont-->
<FontFamily x:Key="IconFont" >
pack://application:,,,/Rubyer;component/Assets/#iconfont
</FontFamily>
回到刚刚 iconfont 的项目下,右键 F12 => Console => 输入下列代码回车,打印图标 名称 和 编码的对应的 json 数据
var allIcon = document.querySelectorAll('[class^=J_icon_id]');
var iconJson = [];
console.log(allIcon[0].querySelector('.icon-name').innerHTML)
for (var i = 0, len = allIcon.length; i < len; i++) {
iconJson[i] = ({'name':allIcon[i].querySelector('.icon-name').innerHTML,'code':allIcon[i].querySelector('.icon-code').innerHTML});
}
console.log(iconJson)
打印完右键 json 变量 => store as global variable, 生成 temp1,输入 copy(temp1),拷贝整个 json 数据,创建文本文件粘贴 到 内容; 保存文件

新建一个控制台项目,添加 JsonObject.cs 类
public class JsonObject
{
public string Name { get; set; }
public string Code { get; set; }
}
Program.cs 读取刚刚添加的 文本文件 到 List<JsonObject>,打印内容全部拷贝 粘贴 到 IconType.cs,为所有图标名称的枚举类型
/// <summary>
/// 从文件加载到对象
/// </summary>
/// <typeparam name="T">对象类型</typeparam>
/// <param name="fileName">文件名路径</param>
/// <returns></returns>
public static T LoadFile2Object<T>(string fileName)
{
try
{
string json = File.ReadAllText(fileName);
return JsonConvert.DeserializeObject<T>(json);
}
catch (Exception)
{
return default(T);
}
} class Program
{
static void Main(string[] args)
{
var jsonObject = LoadFile2Object<List<JsonObject>>("IconJson.txt"); #region 添加 IconType
int count = ;
foreach (var item in jsonObject)
{
//Console.WriteLine($"name:{item.Name},code:{item.Code}");
var names = item.Name.Trim().Split(' ', '-');
var name = "";
for (int i = ; i < names.Length; i++)
{
if (names[i] == " " || names[i] == "") continue;
name += names[i].Substring(, ).ToUpper() + names[i].Substring();
}
count++;
Console.WriteLine($"{name},");
}
#endregion Console.ReadLine();
}
}
IconType.cs:
public enum IconType
{
BookMinus,
Cookie,
FormatBold,
LedOutline,
Pin,
Speedometer,
Web,
BookMultiple,
Copyright,
...
}
注释掉上面 #region 添加 IconType 的内容,换成下面的代码, 打印出 IconDatas.cs 的内容, 打印内容全部拷贝 粘贴 到 IconDatas.cs,为枚举对应的图标代码
#region 添加 IconDatas
int count = ;
foreach (var item in jsonObject)
{
var names = item.Name.Trim().Split(' ', '-');
var name = "";
var code = item.Code.Replace("&#x", "\\u").Replace(";", "");
for (int i = ; i < names.Length; i++)
{
if (names[i] == " " || names[i] == "") continue;
name += names[i].Substring(, ).ToUpper() + names[i].Substring();
}
count++;
//{ IconType.SafetyCertificate, "\ue7f5"}
Console.WriteLine($"{{ IconType.{name},\"{code}\"}},");
}
#endregion
IconDatas.cs:
namespace Rubyer
{
internal class IconDatas
{
public static Dictionary<IconType, string> GetAll() =>
new Dictionary<IconType, string>
{
{ IconType.BookMinus,"\ue6db"},
{ IconType.Cookie,"\ue7db"},
{ IconType.FormatBold,"\ue8db"},
{ IconType.LedOutline,"\ue9db"},
{ IconType.Pin,"\ueadb"},
{ IconType.Speedometer,"\uebdb"},
{ IconType.Web,"\uecdb"},
{ IconType.BookMultiple,"\ue6dc"},
{ IconType.Copyright,"\ue7dc"},
...
}
}
}
4.修改模板
Icon.xaml:WPF 没有 Icon 控件,自己定义一个模板样式
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:rubyer="clr-namespace:Rubyer">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/Rubyer;component/Themes/BaseStyle.xaml" />
</ResourceDictionary.MergedDictionaries> <Style TargetType="{x:Type rubyer:Icon}">
<Setter Property="Height" Value="20"/>
<Setter Property="Width" Value="20"/>
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="VerticalAlignment" Value="Top"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type rubyer:Icon}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Viewbox>
<TextBlock FontFamily="{StaticResource IconFont}"
Text="{Binding Code,RelativeSource={RelativeSource TemplatedParent}}"
Foreground="{TemplateBinding Foreground}"/>
</Viewbox>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
主要图标应用位置,Text 绑定 iconfont 图标的编码:
<TextBlock FontFamily="{StaticResource IconFont}" Text="{Binding Code,RelativeSource={RelativeSource TemplatedParent}}" Foreground="{TemplateBinding Foreground}"/>
Icon.cs : 自定义控件 的内容;
public class Icon : Control
{
// 所有图标键值对
private static readonly Lazy<Dictionary<IconType, string>> _codes = new Lazy<Dictionary<IconType, string>>(IconDatas.GetAll()); static Icon()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(Icon), new FrameworkPropertyMetadata(typeof(Icon)));
} public override void OnApplyTemplate()
{
base.OnApplyTemplate();
UpdateIcon();
} // 图标类型
public IconType Type
{
get { return (IconType)GetValue(TypeProperty); }
set { SetValue(TypeProperty, value); }
} public static readonly DependencyProperty TypeProperty =
DependencyProperty.Register("Type", typeof(IconType), typeof(Icon), new PropertyMetadata(default(IconType), TypePropertyChangedCallBack)); private static void TypePropertyChangedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((Icon)d).UpdateIcon();
} // 图标编码
public string Code
{
get { return (string)GetValue(CodeProperty); }
set { SetValue(CodeProperty, value); }
} public static readonly DependencyProperty CodeProperty =
DependencyProperty.Register("Code", typeof(string), typeof(Icon), new PropertyMetadata("")); // 更新图标
private void UpdateIcon()
{
string code = null;
_codes.Value?.TryGetValue(Type, out code);
Code = code;
}
}
5.应用
在 Rubyer,引用 Icon.xaml
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/Rubyer;component/Themes/Button.xaml" />
<ResourceDictionary Source="pack://application:,,,/Rubyer;component/Themes/Icon.xaml" />
</ResourceDictionary.MergedDictionaries>
回到 RubyerDemo ,尝试使用 Icon 控件,Type 属性 可以提示I con 枚举所有类型
<Button Style="{DynamicResource CircleMidButton}">
<rubyer:Icon Type="Qqchat"/>
</Button>
<Button Style="{DynamicResource CircleLightButton}" rubyer:ButtonHelper.CircleDima="40">
<rubyer:Icon Type="Wechat" Height="30" Width="30"/>
</Button>
<Button Style="{DynamicResource CircleDarkButton}" rubyer:ButtonHelper.CircleDima="50">
<rubyer:Icon Type="GithubCircle" Height="40" Width="40"/>
</Button>
<Button Style="{DynamicResource CircleAccentButton}" rubyer:ButtonHelper.CircleDima="60">
<rubyer:Icon Type="Cookie" Height="50" Width="50"/>
</Button>
最后,附图

[WPF][Rubyer] 写一个自己的 UI 库 (二) - Icon的更多相关文章
- 自己动手写一个iOS 网络请求库的三部曲[转]
代码示例:https://github.com/johnlui/Swift-On-iOS/blob/master/BuildYourHTTPRequestLibrary 开源项目:Pitaya,适合大 ...
- WPF MVVM 写一个健壮的INotifyPropertyChanged基类
当我们用MVVM的时候要实现INotifyPropertyChanged,如果你是基于.net4.5以下的framework(.net4.5已有新特性我这里就不说了) 你很可能会这么写 public ...
- 【写一个自己的js库】 2.实现自己的调试日志
还是本着学习的目的,实现一个自己的调试日志,界面很简单,就是将调试信息显示在页面的正中央,用一个ul包裹,每条信息就是一个li. 1.新建一个myLogger.js文件,将需要的方法声明一下.其中va ...
- 【写一个自己的js库】 1.搭个架子先
最近在看<javascript dom 高级程序设计>,想着跟着里面的代码敲一遍吧,也算是做一下学习笔记吧,所以这不是重新发明轮子,只是个学习的过程. 1.先确定自己的命名空间,并且加入几 ...
- 如何写一个自己的组件库,打成NPM包,并上传到NPM远程
1.首先使用vue create my_project 构建一个自己的Vue项目 2.vue.config.js和package.json配置如下,做了些修改 const path = require ...
- 【写一个自己的js库】 5.添加修改样式的方法
1.根据id或class或tag修改样式,样式名是-连接格式的. function setStyleById(elem, styles){ if(!(elem = $(elem)) return fa ...
- 【写一个自己的js库】 3.添加几个处理字符串的方法
1.生成重复的字符串 if(!String.repeat){ String.prototype.repeat = function (count){ return new Array(count + ...
- 【写一个自己的js库】 4.完善跨浏览器事件操作
1.阻止冒泡. function stopPropagation(event){ event = event || getEvent(event); if(event.stopPropagation) ...
- Cocos2D iOS之旅:如何写一个敲地鼠游戏(二):Cocos2D中的高清支持
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 免责申明:本博客提供的所有翻译文章原稿均来自互联网,仅供学习交流 ...
随机推荐
- 曹工说Spring Boot源码(30)-- ConfigurationClassPostProcessor 实在太硬核了,为了了解它,我可能debug了快一天
写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...
- python关于字符编码的基本操作
字符编码 (注意:关于字符编码,如果没有特殊业务要求,请牢记仅使用UTF-8编码) 由于Python的字符串类型是str,在内存中以Unicode表示,一个字符对应若干个字节.如果要在网络上传输,或者 ...
- 详解 awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}每个字段的意思
用这个列子说好了如果NF代表字段 那最后应该是7 才对啊 还有最后怎么都是1呢?END前面的是查看并发吧 后面是查看 tcp连接数 是这样吗? awk下标采用字符串来表示可能你在其它语言见 ...
- Python模块_import语句_from...import 函数名_from ... import *
Python模块:包含了所有定义的函数和变量的文件,后缀名为 .py 将某些方法存放在文件中,当某些脚本 或 交互式需要使用的时候,导入进去. 导入的文件,就称为模块.导入之后就可以使用导入的文件的函 ...
- recv & recvfrom
#include <sys/types.h> #include <sys/socket.h> ssize_t recv(int sockfd, void *buf, size_ ...
- luogu P4887 模板 莫队二次离线 莫队 离线
LINK:模板莫队二次离线 很早以前学的知识点 不过 很久了忘了. 考虑暴力 :每次莫队更新的时候 尝试更新一个点到一个区间的答案 可以枚举二进制下位数为k的数字 看一下区间内的这种数字有多少个. 不 ...
- 4.15 省选模拟赛 编码 trie树 前缀和优化建图 2-sat
好题 np. 对于20分 显然可以爆搜. 对于50分 可以发现每个字符串上的问号要么是0,要么是1.考虑枚举一个字符串当前是0还是1 这会和其他字符串产生矛盾. 所以容易 发现这是一个2-sat问题. ...
- JS——变量提升和函数提升
一.引入 在了解这个知识点之前,我们先来看看下面的代码,控制台都会输出什么 var foo = 1; function bar() { if (!foo) { var foo = 10; } aler ...
- 浅谈树形结构的特性和应用(上):多叉树,红黑树,堆,Trie树,B树,B+树...
上篇文章我们主要介绍了线性数据结构,本篇233酱带大家康康 无所不在的非线性数据结构之一:树形结构的特点和应用. 树形结构,是指:数据元素之间的关系像一颗树的数据结构.我们看图说话: 它具有以下特点: ...
- Rest接口加Https单向认证
背景: 接到一个需求,客户要求某个模块的rest接口都得通过https访问,客户提供证书. 步骤: Server端证书生成 刚开始还没拿到客户的证书,所以通过jdk自带的keytools自己先生成了一 ...