【请注意:此文已过期,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. Gradle中的buildScript代码块

    在编写Gradle脚本的时候,在build.gradle文件中经常看到这样的代码: build.gradle 1 2 3 4 5 6 7 8 9 buildScript { repositories ...

  2. [Linux]Linux下安装和配置solr/tomcat/IK分词器 详细实例二.

    为了更好的排版, 所以将IK分词器的安装重启了一篇博文,  大家可以接上solr的安装一同查看.[Linux]Linux下安装和配置solr/tomcat/IK分词器 详细实例一: http://ww ...

  3. React(一)基础点

    prop实例 <div id="app"></div> <script src="bower_components/react/react. ...

  4. mysql关键字与自己设置的字段冲突

    当我们设置字段大意的使用数据库关键字,会报与数据库有关错误,原因就是字段误与数据库关键字冲突造成. 解决办法:1.修改字段名字. 2.采用数组的方式进行调用.例如:thinkphp3.2手册中orde ...

  5. 通过shape-outside来设置文字环绕时的形状

    现在真是越来越注重用户体验了,而"shape-outside"就是其中一个能让网页排版更友好的一个属性. 默认文字是根据图片的边进行的. 但现在我们完全有能力去改变这一行为,下面是 ...

  6. Android开发之注册登录

    昨天给大家介绍了一下关于Android端向服务器端发送数据的方法,不过貌似有一点瑕疵,今天经过调试已经解决,在这里给大家介绍一下 貌似Android4.0以后版本的对于网络权限要求变得严格,导致昨天编 ...

  7. codeforces B. Pasha and String(贪心)

    题意:给定一个长度为len的字符序列,然后是n个整数,对于每一个整数ai, 将字符序列区间为[ai,len-ai+1]进行反转.求出经过n次反转之后的序列! /* 思路1:将区间为偶数次的直接去掉!对 ...

  8. Oracle之DBMS_RANDOM包详解

    DBMS_RANDOM是Oracle提供的一个PL/SQL包,用于生成随机数据和字符.它具有以下函数. 其中,initialize,random,terminate函数在Oracle11g中已不推荐使 ...

  9. Js杂谈-DOM

    前言 对jQuery的依赖.导致js的原生方法的淡忘,如果是封装自己的库,那势必要用到js的许多原生方法.从Jquery强大的dom处理开始,我们开始回顾javascript那些古老而坚挺的DOM方法 ...

  10. 使用 CSS3 & jQuery 制作漂亮的书签动画

    今天的教程是关于创建使用 CSS 旋转变换和 JavaScript 制作动画书签效果.我们的想法是展现出样书状结构,使单一的色板或列表点击切换.当点击其中一项,我们就会旋转以显示所选择的项目. 在线演 ...