C#实现Everything——UI与查询附源码
前⾔
    发现实习了以后⾃⼰就变懒了,每天回到宿舍只想打游戏,看剧。要是能有⼈家考研的⼀半劲头就好了。
    写完Everything的C#实现之后呢,我想写⼀些⼯作期间遇到的问题。⼀来当作笔记,⼆来加深学习。
UI
磁盘图标
    ⾸先呢,我们先做⼀个可以显⽰各磁盘空间的控件。这⾥其实是⼀个个使⽤了GDI绘图后的Panel,我采⽤FlowLayoutPanel作为它的容器。容器的宽度作为参数之⼀,⽤它来决定Panel的⼤⼩,绘图的尺⼨。绘制也很简单,先画⼀个绿⾊的⼤圆,根据⽐例,在其之上再画⼀个红⾊的扇形,然后再覆盖⼀个⽩⾊的⼩圆,三者同⼼,这样就是⼀个可以展⽰磁盘空间占⽤⽐例的圆环了。最后在中间写上⽂字即可,很简单吧!
    我还⽤GDI+Winform做过很多⼩游戏,例如贪吃蛇,五⼦棋,你画我猜等等,觉得很好玩。后来接触到WPF,⼀时间接受不了。它的动画效果怎么这么棒!写起来怎么怎么⽅便!再后来,见识到了眼花缭乱的前端技术,我便不再对UI设计抱有什么梦想了,还是后端⽐较单纯。
过滤器图标
    再说过滤器控件,Everything中的过滤器是⼀条菜单项,我将其可视化为了UI图形。它由⼀个PictureBox,⼀个CheckBox,以及两个Label组成。同样采⽤FlowLayoutPanel作为它的容器。与上⾯那个磁盘圆环⼀样,我将它们上⾯的事件,属性封装成了⼀个UI库⽂件。
    过滤器控件相对来说复杂⼀些,为了可以让⽤户⾃由选择图标,并且控件本⾝要记录代表的⽂件类
型,它的三个组成部分还要表现的像⼀个整体⼀样。封装时,我给这个控件添加了四个public属性,分别为Name,FileNumber,IsCheck,以及图⽚的path, 并且完善了点击事件联动代码,图⽚显⽰,出错处理等代码。
查询
    让我们先来明确⼀下查询的条件是什么。
需要⽀持按照⽂件名称模糊查询。
需要⽀持按照⽂件类型进⾏查询,系统肯定不能定义出所有的⽂件类别,因此还需要让⽤户可以⾃定义查询类型。
需要⽀持正则表达式查询。
需要⽀持特定的⽬录下查询。
    ⽂件名模糊查询很简单,我这⾥使⽤Contains函数来完成。⽂件类型查询怎么做到呢?我们通过观察Everything可以发现它是按照⽂件扩展名来做的。那我们就⽤⼀个List集合来保存多个扩展名,并⽤它代表某⼀类⽂件,做成⽂件过滤器吧!为了能够让⽤户的配置可以保存下来,我使⽤到了XML。并且在程序中定义了⼀个与其对应的Model,叫做Filter。
<?xml version="1.0" encoding="UTF-8"?>
<filters>
<filter>
<name>实验⽂档</name>
<url>E:\图⽚\壁纸\《ARC X Windows 10 Theme》简约⿊⽩风景壁纸_彼岸图⽹.jpg</url>
<param>.DOC</param>
<param>.DOCX</param>
</filter>
</filters>
public class Filter
{
public Filter(string name, List<string> param, string url)
{
this.name = name;
this.param = new List<string>();
foreach (string p in param)
{
if (p.StartsWith("."))
{
this.param.Add(p.ToUpper());asp查看源码配置ui
}
else
{
this.param.Add(string.Concat(".", p).ToUpper());
}
}
this.url = url;
}
private string name;
public string Name { get=>name; set=>name=value; }
private List<string> param;
public List<string> Param {
get =>param;
set
{
foreach (string p in value)
{
if (p.StartsWith("."))
{
this.param.Add(p.ToUpper());
}
else
{
this.param.Add(string.Concat(".", p).ToUpper());
}
}
}
}
private string url;
public string Url { get=>url; set=>url=value; }
}
    上⾯介绍到的磁盘UI控件的构造函数接受传⼊⼀个DriveInfo对象,我封装好的GDI⽅法会完成绘图。
    过滤器控件则不同。我会将⽤户⾃定义的过滤器从xml中解析出来,保存⾄List中,过滤器控件依据Filter的个数⽽创建。其中,过滤器的Name就取⾃该Filter在List中的Index。这样,当我们进⾏查询时,可以遍历每⼀个过滤器控件,将被选中的(IsCheck=true)过滤器控件的名字转换成Index,到List中对应的Filter,取出它们的List Param,拼接成⼀个List,作为查询条件之⼀。
    这样便实现了多种类组合查询的功能。为了能够让⽤户对过滤器进⾏必要的增删改查操作,我们需要书写⼀个包含各种⽅法的xml⼯具类。当然使⽤xpath就很简单。
判断⽂件是否存在,不存在则创建⼀个
存在则创建XmlDocument对象。取出根节点
root = xmlfilter.SelectSingleNode("filters");
public List<Filter> ReadXml()
{
List<Filter> filters = new List<Filter>();
foreach (XmlNode item in root)
{
XmlElement xm = (XmlElement)item;
string name = xm.SelectSingleNode("name").InnerText;
string url = xm.SelectSingleNode("url").InnerText;
List<string> param = new List<string>();
foreach (XmlNode c in xm.SelectNodes("param"))
{
param.Add(c.InnerText.ToString().ToLower());
}
Filter filter = new Filter(name, param, url);
filters.Add(filter);
}
return filters;
}
添加⼦节点
private void CreateNode(XmlDocument xmlDoc, XmlNode parentNode, string name, string value)
{
XmlNode node = xmlDoc.CreateNode(XmlNodeType.Element, name, null);
node.InnerText = value;
parentNode.AppendChild(node);
}
    其他的功能就不再介绍了。
    再来看剩下的两个查询需求,正则查询和指定⽂件⽬录查询。这两个功能就很简单了。指定⽬录也就是⽂件路径以什么字符串开头 ;正则查询⼜不需要我们⾃⼰写正则,在界⾯上添加个CheckBox,让⽤户⾃⼰选择是正则查询,还是普通查询就好了,使⽤C#中的Regex 类即可完成。
    因此,虽然我们的提供查询功能很丰富,实际上只需要写⼀个重载的查询函数即可——正则查询和普通查询。
/// <summary>
/// 查询⽂件
/// </summary>
/// <param name="startWith"></param>
/// <param name="inputs"></param>
/// <param name="filters"></param>
/// <returns></returns>
public IEnumerable<FileStruct> SearchMatchFileMethod(string startWith,string inputs, List<string> filters)
{
if (string.IsNullOrEmpty(inputs) && string.IsNullOrEmpty(startWith))
return _fileSource.Files;
if (filters.Contains(".*"))
return _fileSource.Files.AsParallel().WithDegreeOfParallelism(Environment.ProcessorCount).
Where<FileStruct>(r => r.Path.StartsWith(startWith) && r.Name.Contains(inputs)) ;
return _fileSource.Files.AsParallel().WithDegreeOfParallelism(Environment.ProcessorCount).
Where<FileStruct>(r => r.Path.StartsWith(startWith) && r.Name.Contains(inputs) && filters.Contains(r.ExpandedName));
}
/// <summary>
/// 根据正则表达式查询⽂件
/// </summary>
/// <param name="startWith"></param>
/// <param name="regex"></param>
/// <param name="filters"></param>
/// <returns></returns>
public IEnumerable<FileStruct> SearchMatchFileMethod(string startWith, Regex regex, List<string> filters)
{
if (filters.Contains(".*"))
return _fileSource.Files.AsParallel().WithDegreeOfParallelism(Environment.ProcessorCount).
Where<FileStruct>(r => r.Path.StartsWith(startWith) && regex.IsMatch(r.Name));
return _fileSource.Files.AsParallel().WithDegreeOfParallelism(Environment.ProcessorCount).
Where<FileStruct>(r => r.Path.StartsWith(startWith) && regex.IsMatch(r.Name) && filters.Contains(r.ExpandedName));                }
数据可视化
    为了使⽤HighChart画饼图,Winform原⽣web控件不好⽤。安装CefSharp包,使⽤ChromiumWebBrowser。
ChromiumWebBrowser CWebBrowser;
private void AnalysisView_Load(object sender, EventArgs e)
{
CWebBrowser = new ChromiumWebBrowser(Environment.CurrentDirectory + "\\view.html");//
this.panel1.Controls.Add(CWebBrowser);
CWebBrowser.Dock = DockStyle.Fill;
CWebBrowser.ContextMenu = new ContextMenu();
CWebBrowser.FrameLoadEnd += new EventHandler<FrameLoadEndEventArgs>(FrameLoadEnd_Event);
}
    执⾏js脚本也超级简单!
    CWebBrowser.EvaluateScriptAsync(script)即可

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。