前言
制作 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>
最后,附图