【请注意:此文已过期,0.6版NanUI实现方式不同!!!】

经过了这一个多星期的调整与修复,NanUI for .NET Winform的稳定版已经发布。应广大群友的要求,现已将NanUI的全部代码开源。

GitHub: https://github.com/NetDimension/NanUI

Release: https://github.com/NetDimension/NanUI/releases

这次发布的是一个相对稳定的版本,解决和改善了如下问题:

  • 页面随机白屏问题(主要原因是GC自动回收后,造成内存地址不可读)
  • NanUI编译版本改为.NET 4.0 Client Profile
  • 托上面那条改进的福,NanUI现在支持Windows XP了
  • 不再支持本地CEF运行支持文件,现在支持文件都需要在线下载安装,当然也可以手动下载离线包安装,但是不论那种方式,CEF都安装到一个共享的位置。CEF运行库只需下载安装一次,不会多次下载。

欢迎下载把玩,也欢迎进群讨论,群号241088256。

下面,进入我们的正题,使用NanUI以及手边的各种开源库制作一个所见即所得的Markdown编辑器。

NanUI系列目录

NanUI for Winform 使用示例【第二集】

做一个所见即所得的Markdown编辑器

在本集中,使用了如下开源技术来方便的组建我们的“所见即所得Markdown编辑器”:

  • bootstrap
  • codeMirror
  • jquery
  • jquery.splitter.js
  • markdown-js
  • github-markdown.css

利用Nuget,获取上列的各种库不是难题。如效果图所示,我们可以方便的利用这些开源库来设计出心仪的页面。在此着重讲解网页前端和后台C#通信的技术。后面的文章里,凡是HTML、CSS和JS的内容我将称他们为“前端”、涉及C#编程的地方我会称他们为“后端”。

如图所示,软件将要与C#后端交互的几个地方有:

  • 代码编辑框
  • 新建文件按钮
  • 打开文件按钮
  • 保存文件按钮

在C#后端,建立HostEditor类来处理由前端发送回来的按钮事件。该类继承自基类JSObject,这个类负责与CEF的V8环境处理各种数据和对象。

 class HostEditor:JSObject
{
frmMain MainFrame;
internal HostEditor(frmMain main)
{
MainFrame = main; AddFunction("setCleanState").Execute += SetCleanState; AddFunction("newFile").Execute += NewFile; AddFunction("openFile").Execute += OpenFile; AddFunction("saveFile").Execute += SaveFile;
} private void SaveFile(object sender, Chromium.Remote.Event.CfrV8HandlerExecuteEventArgs e)
{
var contents = e.Arguments.FirstOrDefault(p => p.IsString);
var result = false;
if (contents != null)
{
result = MainFrame.SaveFile(contents.StringValue); } if (result)
{
e.SetReturnValue(this.GetCfrObject(new
{
success = true,
fileName = MainFrame.CurrentFile.Name
}));
}
else
{
e.SetReturnValue(this.GetCfrObject(new
{
success = false
}));
}
} private void OpenFile(object sender, Chromium.Remote.Event.CfrV8HandlerExecuteEventArgs e)
{
var contents = e.Arguments.FirstOrDefault(p => p.IsString);
string result = null;
if (contents != null)
{
result = MainFrame.OpenFile(contents.StringValue);
} if (!string.IsNullOrEmpty(result))
{
e.SetReturnValue(this.GetCfrObject(new
{
success = true,
fileName = MainFrame.CurrentFile.Name,
contents = result
})); }
else
{
e.SetReturnValue(this.GetCfrObject(new
{
success = false
}));
}
} private void NewFile(object sender, Chromium.Remote.Event.CfrV8HandlerExecuteEventArgs e)
{
var contents = e.Arguments.FirstOrDefault(p => p.IsString);
var result = false;
result = MainFrame.NewFile(contents.StringValue); e.SetReturnValue(CfrV8Value.CreateBool(result));
} private void SetCleanState(object sender, Chromium.Remote.Event.CfrV8HandlerExecuteEventArgs e)
{
if(e.Arguments.Length> && e.Arguments[].IsBool)
{
MainFrame.isClean = e.Arguments[].BoolValue;
}
}
}

在主窗体的构造函数中,将上面的HostEditor类注册到NanUI的JS环境中,并命名为hostEditor,这样在前端的JS中就可以调用hostEditor对象以及对象中内置的C#方法了:

GlobalObject.Add("hostEditor", new HostEditor(this));

在JS环境中hostEditor对象提供了以下几个方法来实现对当前代码编辑器里的内容进行新增、打开和保存的操作。

  • hostEditor.newFile(string)
  • hostEditor.openFile(string)
  • hostEditor.saveFile(string)
  • hostEditor.setCleanState(bool)

同时,将HostEditor中需要用到的新建文件、保存文件、打开文件等操作的方法放在主窗体中,方便前端JS调用。

        /// <summary>
/// 标记文档是否被修改
/// </summary>
internal bool isClean = true;
/// <summary>
/// 当前文档的存储路径,如果为空则说明该文档是新文档
/// </summary>
internal string currentFilePath = string.Empty; /// <summary>
/// 当前文档的FileInfo
/// </summary>
internal System.IO.FileInfo CurrentFile
{
get
{
return new System.IO.FileInfo(currentFilePath);
}
} /// <summary>
/// 获得一个标识当前文档是否为新建文档
/// </summary>
private bool IsNewFile
{
get
{
return string.IsNullOrEmpty(currentFilePath);
}
}
/// <summary>
/// 新建文件
/// </summary>
/// <param name="contents">当前文档中的内容</param>
/// <returns>如果新建成功则返回true</returns>
internal bool NewFile(string contents)
{
var continueFlag = true; if (!isClean)
{
var ret = MessageBox.Show(this, "文件已经更改,是否保存下先?", "提示", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question); if (ret == DialogResult.Yes)
{
if (!SaveFile(contents))
{
continueFlag = false;
}
}
else if (ret == DialogResult.Cancel)
{
continueFlag = false;
} } if (!continueFlag)
{
return false;
} currentFilePath = null;
isClean = true; return true;
}
/// <summary>
/// 打开文档
/// </summary>
/// <param name="contents">当前文档中的内容</param>
/// <returns>如果新建成功则返回打开文档的内容</returns>
internal string OpenFile(string contents)
{
var continueFlag = true;
if (!isClean)
{
var ret = MessageBox.Show(this, "文件已经更改,是否保存下先?", "提示", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question); if (ret == DialogResult.Yes)
{
if (!SaveFile(contents))
{
continueFlag = false;
}
}
else if (ret == DialogResult.Cancel)
{
continueFlag = false;
} } if (!continueFlag)
{
return null;
} var content = string.Empty; var openDialog = new OpenFileDialog()
{
AddExtension = true,
Filter = "Markdown文件|*.md"
}; if (openDialog.ShowDialog() == DialogResult.OK)
{
currentFilePath = openDialog.FileName; var fileInfo = new System.IO.FileInfo(currentFilePath); content = System.IO.File.ReadAllText(fileInfo.FullName); }
else
{
content = null;
} return content; }
/// <summary>
/// 保存文档
/// </summary>
/// <param name="contents">当前文档中的内容</param>
/// <returns>如果保存成功则返回true</returns>
internal bool SaveFile(string contents) { if (!IsNewFile) {
if (isClean) return true; System.IO.File.WriteAllText(currentFilePath, contents, Encoding.UTF8);
isClean = true;
return true;
} var saveFileDialog = new SaveFileDialog()
{
AddExtension = true,
Filter = "Markdown文件|*.md",
OverwritePrompt = true
}; if (saveFileDialog.ShowDialog(this) == DialogResult.OK)
{
currentFilePath = saveFileDialog.FileName; System.IO.File.WriteAllText(currentFilePath, contents, Encoding.UTF8); isClean = true; return true;
} return false; }

如此这般,一个所见即所得的Markdown编辑器就制作完成了。有了这个小工具编辑GitHub的README文档就不会那么痛苦了。有兴趣的朋友可以自行到GitHub下载代码来把玩。

那么,NanUI的第二集示例就这么讲完了。最后还是欢迎大家留言,或者进群讨论。当然能在github够提供pull request是最好的。

附件

MarkdownDotNet.zip - 编译好的Markdown编辑器,欢迎下载体验,代码已上传到GitHub


NanUI for .NET Winform系列目录


经过了这一个多星期的调整与修复,NanUI for .NET Winform的稳定版已经发布。应广大群友的要求,现已将NanUI的全部代码开源。

GitHub: https://github.com/NetDimension/NanUI

Release: https://github.com/NetDimension/NanUI/releases


如果你喜欢NanUI项目,你可以参与到NanUI的开发中来,当然你也可以更直接了当的支持我的工作,使用支付宝或微信扫描下面二维码请我喝一杯热腾腾的咖啡。

支付宝转账

微信转账


另外,打个广告,承接NanUI界面设计与接口开发(收费)。

案例展示

某聊天应用

某公司内部办公系统

NanUI for Winform 使用示例【第二集】——做一个所见即所得的Markdown编辑器的更多相关文章

  1. NanUI for Winform 使用示例【第一集】——山寨个代码编辑器

    NanUI for Winform从昨天写博客发布到现在获得了和多朋友的关注,首先感谢大家的关注和支持!请看昨天本人的博文<NanUI for Winform发布,让Winform界面设计拥有无 ...

  2. '用Roslynpad做一个轻量级的C#编辑器'

    博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:'用Roslynpad做一个轻量级的C#编辑器'.

  3. Winform窗体用对象数组做一个小项目

    首先我我们看一下需求:我们要做的是显示员工信息,实现项目经理给员工评分的功能! 首先项目经理是评分的人所以没有用,因为我们自己写,评分的就是我们自己.所以我们要做的是先在vs也就是我们的环境里建一个项 ...

  4. 使用Vue自己做一个简单的MarkDown在线编辑器

    1.首先要下载mark组件. npm install marked --save 2.在Vcontent.vue中简单写一些样式. <template> <div class=&qu ...

  5. 做一个所见即所得的CSS效果

    style 也是标签(在非ie内核的浏览器中支持),我们将style设置成 contenteditable的时候,那么那的内容就可以编辑了.仔细的体验下,如果我们将背景修改成红色的.那么只要书写完,立 ...

  6. NanUI for Winform发布,让Winform界面设计拥有无限可能

    如今,尽管WPF.UWP大行其道,大有把Winform打残干废的趋势.但是还是有那么一波顽固不化的老家伙们固守着Winform,其中就包括我. 好吧,既然都说Winform做得软件不如WPF界面美观效 ...

  7. Windows Phone开发(44):推送通知第二集——磁贴通知

    原文:Windows Phone开发(44):推送通知第二集--磁贴通知 前面我们说了第一个类型--Toast通知,这玩意儿不知大家是不是觉得很新鲜,以前玩.NET编程应该没接触过吧? 其实这东西绝对 ...

  8. SpringBoot第二集:注解与配置(2020最新最易懂)

    2020最新SpringBoot第二集:基础注解/基础配置(2020最新最易懂) 一.Eclipse安装SpringBoot插件 Eclipse实现SpringBoot开发,为便于项目的快速构建,需要 ...

  9. PB中用oracle的存储过程返回记录集做数据源来生成数据窗口,PB会找不到此存储过程及不能正常识别存储过程的参数问题(转)

    (转)在PB中用oracle的存储过程返回记录集做数据源来生成数据窗口 首先oracle的存储过程写法与MSSQL不一样,差别比较大. 如果是返回数据集的存储过程则需要利用oracle的包来定义游标. ...

随机推荐

  1. NanoProfiler - 适合生产环境的性能监控类库 之 基本功能篇

    背景 NanoProfiler是一个EF Learning Labs出品的免费性能监控类库(即将开源).它的思想和使用方式类似于MiniProfiler的.但是,设计理念有较大差异. MiniProf ...

  2. Lucene系列-搜索

    Lucene搜索的时候就要构造查询语句,本篇就介绍下各种Query.IndexSearcher是搜索主类,提供的常用查询接口有: TopDocs search(Query query, int n); ...

  3. MYSQL-用户操作

    说明:本文主要写了,MYSQL对于用户的一些操作,有:查看用户,创建用户,权限的赋予,收回,用户的密码修改和删除. MySql的用户管理是通过 User表来实现的,添加新用户常用的方法有两个,一是在U ...

  4. AngularJS 源码分析1

    AngularJS简介 angularjs 是google出品的一款MVVM前端框架,包含一个精简的类jquery库,创新的开发了以指令的方式来组件化前端开发,可以去它的官网看看,请戳这里 再贴上一个 ...

  5. iOS开发——高级技术精选OC篇&Runtime之字典转模型实战

    Runtime之字典转模型实战 如果您还不知道什么是runtime,那么请先看看这几篇文章: http://www.cnblogs.com/iCocos/p/4734687.html http://w ...

  6. css3使用box-sizing布局

    css3增添了盒模型box-sizing,属性值有下面三个: content-box:默认值,让元素维持W3C的标准盒模型.元素的宽度/高度(width/height)(所占空间)等于元素边框宽度(b ...

  7. KnockoutJS 3.X API 第四章 表单绑定(6) click绑定

    目的 click绑定主要作用是用于DOM元素被点击时调用相关JS函数.最常见用于button.input.a元素. 例如: You've clicked timesClick me var viewM ...

  8. 每天学点前端——基础篇1:css盒子模型,绝对定位和相对定位

    什么是css盒子模型(Box Model)? W3C中解释为:规定了元素框处理元素内容.内边距.边框和外边距的方式: MDN:文档中的每个元素被描绘为矩形盒子.渲染引擎的目的就是判定大小,属性--比如 ...

  9. 开源项目IPProxys的使用

    前几天看了一下github上,IPProxys开源项目(https://github.com/qiyeboy/IPProxys)快100star了,看来大家对这个项目还是比较感兴趣的.最近一直没更新文 ...

  10. 一次SSIS Package的调试经历

    SSIS Package的调试有时是一个非常艰难的过程,由于SSIS 编译器给出的错误信息,可能并不完善,需要程序员根据错误信息抽丝拨茧,寻找错误的根源,进而解决问题. 第一部分:SSIS提供的调试工 ...