[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 ;) 免责申明:本博客提供的所有翻译文章原稿均来自互联网,仅供学习交流 ...
随机推荐
- Java事务解析(事务的基本操作+隔离的等级+事务的四大特性+事务的概念)
Java事务解析(事务的基本操作+隔离的等级+事务的四大特性+事务的概念) 什么是事务? 如果一个包含多个步骤的业务操作,这些操作被事务管理,那么这些操作要么同时成功要么同时失败 事务的四大特性(必须 ...
- 16 . Go之网络编程
互联网的本质 两台计算机之间的通信与两个人打电话原理是一样的. # 1. 首先要通过各种物理连接介质连接 # 2. 找准确对方计算机(准确到软件)的位置 # 3. 通过统一的标准(一般子协议)进行数据 ...
- Git文件合并
两个分支:主分支master,分支pre 1.将pre分支文件合并到master分支: 切换到master分支下操作: 合并文件夹[如果是文件则为a.text b.text]: git checkou ...
- 面试(JS篇)
1.js基本类型 Boolean,Number,String,Null,Undefined,Symbol. 2.null非对象,但是typeof null 返回的是Object,原因遗留下来的一个bu ...
- Django学习路11_向数据库中添加 和 获取指定条件数据
在 views.py 中添加函数 向数据库中添加数据 def add_persons(request): for i in range(15): person = Person() flag = ra ...
- Python里的目录方法
Python里的目录_文件.目录相关的方法: mkdir(目录名): 在当前目录下创建新的目录 程序: import os # 创建新的目录-包结构 os.mkdir('新目录-test') getc ...
- Python第一次实验
''' 计算 1.输入半径,输出面积和周长 2.输入面积,输出半径及周长 3.输入周长,输出半径及面积 ''' # # 1.输入半径,输出面积和周长 # from math import pi # # ...
- 7.12 NOI模拟赛 探险队 期望 博弈 dp 最坏情况下最优策略 可并堆
LINK:探险队 非常难的题目 考试的时候爆零了 完全没有想到到到底怎么做 (当时去刚一道数论题了. 首先考虑清楚一件事情 就是当前是知道整张地图的样子 但是不清楚到底哪条边断了. 所以我们要做的其实 ...
- OpenVINO学习系列1
OpenVINO介绍 OpenVINO是英特尔推出一套基于深度学习的计算机视觉加速优化框架,支持其它机器学习平台模型的压缩优化.加速计算等功能. 自发布以后就得到开发者的青睐,其强大的模型优化与压缩能 ...
- 当asp.net core偶遇docker一(模型验证和Rabbitmq 二)
上一篇我们说到构建了一个Rabbitmq容器 现在我们说说如何在一个悄悄传输消息到队列 我们现在设计一个Rabbitmq发送消息部分的模块 先设计一个远程发送的接口 public interface ...