NanUI for Winform 使用示例【第二集】——做一个所见即所得的Markdown编辑器
【请注意:此文已过期,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发布,让Winform界面设计拥有无限可能
 - NanUI for Winform 使用示例【第一集】——山寨个代码编辑器
 - NanUI for Winform 使用示例【第二集】——做一个所见即所得的Markdown编辑器
 
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 Winform发布,让Winform界面设计拥有无限可能
 - NanUI for Winform 使用示例【第一集】——山寨个代码编辑器
 - NanUI for Winform 使用示例【第二集】——做一个所见即所得的Markdown编辑器
 
经过了这一个多星期的调整与修复,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编辑器的更多相关文章
- NanUI for Winform 使用示例【第一集】——山寨个代码编辑器
		
NanUI for Winform从昨天写博客发布到现在获得了和多朋友的关注,首先感谢大家的关注和支持!请看昨天本人的博文<NanUI for Winform发布,让Winform界面设计拥有无 ...
 - '用Roslynpad做一个轻量级的C#编辑器'
		
博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:'用Roslynpad做一个轻量级的C#编辑器'.
 - Winform窗体用对象数组做一个小项目
		
首先我我们看一下需求:我们要做的是显示员工信息,实现项目经理给员工评分的功能! 首先项目经理是评分的人所以没有用,因为我们自己写,评分的就是我们自己.所以我们要做的是先在vs也就是我们的环境里建一个项 ...
 - 使用Vue自己做一个简单的MarkDown在线编辑器
		
1.首先要下载mark组件. npm install marked --save 2.在Vcontent.vue中简单写一些样式. <template> <div class=&qu ...
 - 做一个所见即所得的CSS效果
		
style 也是标签(在非ie内核的浏览器中支持),我们将style设置成 contenteditable的时候,那么那的内容就可以编辑了.仔细的体验下,如果我们将背景修改成红色的.那么只要书写完,立 ...
 - NanUI for Winform发布,让Winform界面设计拥有无限可能
		
如今,尽管WPF.UWP大行其道,大有把Winform打残干废的趋势.但是还是有那么一波顽固不化的老家伙们固守着Winform,其中就包括我. 好吧,既然都说Winform做得软件不如WPF界面美观效 ...
 - Windows Phone开发(44):推送通知第二集——磁贴通知
		
原文:Windows Phone开发(44):推送通知第二集--磁贴通知 前面我们说了第一个类型--Toast通知,这玩意儿不知大家是不是觉得很新鲜,以前玩.NET编程应该没接触过吧? 其实这东西绝对 ...
 - SpringBoot第二集:注解与配置(2020最新最易懂)
		
2020最新SpringBoot第二集:基础注解/基础配置(2020最新最易懂) 一.Eclipse安装SpringBoot插件 Eclipse实现SpringBoot开发,为便于项目的快速构建,需要 ...
 - PB中用oracle的存储过程返回记录集做数据源来生成数据窗口,PB会找不到此存储过程及不能正常识别存储过程的参数问题(转)
		
(转)在PB中用oracle的存储过程返回记录集做数据源来生成数据窗口 首先oracle的存储过程写法与MSSQL不一样,差别比较大. 如果是返回数据集的存储过程则需要利用oracle的包来定义游标. ...
 
随机推荐
- 知方可补不足~SQL2008中的发布与订阅模式
			
回到目录 作用:完成数据库与数据库的数据同步 原理:源数据库发布需要同时的表,存储过程,或者函数:目标数据库去订阅它,当源发生变化时,目标数据库自己同步,注意,由于这个过程是SQL自动完成的,所以要求 ...
 - Oracle使用小记
			
windows下Oracle必须要启动的服务 Oracle ORCL VSS Writer Service:Oracle卷映射拷贝写入服务,VSS(Volume Shadow Copy Service ...
 - MongoDB 简介
			
MongoDB 简介 介绍:MongoDB是一个基于分布式文件存储的数据库.由C++语言编写.旨在为WEB应用提供可扩展的高性能数据存储解决方案.特点:高性能.易部署.易使用,存储数据非常方便.主要功 ...
 - 接触Matlab10年后的一个总结,随时使用Matlab要掌握的一些要点
			
不记得上一次写超过20行的matlab程序是什么时候了,大概是2013年吧,那个时候写过2篇文章,实际用到了 一些matlab的内容,超过200行的matlab程序应该要追溯到2011年了,最近为了帮 ...
 - 理解Docker容器的进程管理
			
摘要: Docker在进程管理上有一些特殊之处,如果不注意这些细节中的魔鬼就会带来一些隐患.另外Docker鼓励"一个容器一个进程(one process per container)&qu ...
 - Docker 有什么优势?
			
1.什么是容器? 依托与linux 内核功能的虚拟化技术 2. docker 是什么? 能够把应用程序自动部署到容器的开源引擎 3. docker 跟原有的工具有何区别? 传统的部署模式是:安装(包管 ...
 - tomcat触发ServletContext初始化监听事件的源码(原创)
			
tomcat 8.0.36 知识点: 动态监听器的好处可以根据环境条件进行选择性添加. 静态监听器有七类. ServletContextAttributeListener ServletRequest ...
 - Visual C++ 6.0使用教程
			
Visual C++它大概可以分成三个主要的部分: 3. Platform SDK.这才是Visual C++和整个Visual Studio的精华和灵魂,虽然我们很少能直接接触到它.大致说来,Pla ...
 - [转载]PhotoShop性能优化
			
现在随着Photoshop版本越来越高功能也越来越强大,而往往强大的功能需要电脑有好的配置运行,比如HDR.图像合成或者3D和视频等类似的功能,还有处理比较大尺寸的图像时,如果电脑配置不够强往往非常卡 ...
 - Deep learning:四十四(Pylearn2中的Quick-start例子)
			
前言: 听说Pylearn2是个蛮适合搞深度学习的库,它建立在Theano之上,支持GPU(估计得以后工作才玩这个,现在木有这个硬件条件)运算,由DL大牛Bengio小组弄出来的,再加上Pylearn ...