zoukankan      html  css  js  c++  java
  • 积极响应博客园友的开源号召,开源自己几年前创建的一个客户关系管理CRM系统 分享美观漂亮的的界面框架

    有园友号召博客园组织一些开源项目,得到大家的积极认可。来博客园五年多,学习到了很多技术,也认识了很多朋友。为感谢大家的帮助,从硬盘的一个角落里,把自己几年前的一个客户关系管理(CRM)项目开源出来。因为涉及到版权原因,已经对实现的业务逻辑和核心部分作了屏蔽处理,主要贡献是它的界面框架,美观实用的界面框架。

    image

    如上图所示,窗体标题是CRM,主体采用淡蓝色的背景,包含标准的菜单,工具栏,左边是Navigation Bar,右边是显示界面的主体框架。这种布局也是模拟Outlook的做法,目前还是比较受欢迎的。

    界面的语言是英语的,窗体的界面直接手写在界面中,源程序包含英简繁三种语言,在这里做了简化处理,只包含英语的界面。左边的Navigation Bar中的菜单,原来也是在菜单设计器中设计的,这里直接改成在树型中设计,没有实现菜单动态加载。因为我要向您分享的是它的界面框架,而不是它的各个细节的处理,你知道这样做很容易侵犯版权。

    进入到代码里面,来分析一下它的实现。请看下图,Visual Studio中的设计效果

    image

    为了实现类似Office界面一样的效果框架,请继承于KryptonForm窗体,代码看起来是这样的

    public partial class FrmMain : KryptonForm
    {             
            public FrmMain()
            {
                InitializeComponent();          
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
                FrmStart frm = new FrmStart();
                frm.TopLevel = false;
                frm.Parent = kryptonMainPanel;
                frm.Dock = DockStyle.Fill;         
                frm.Show();
             }
    }

    如你所看到的代码,主窗体启动时,加载起始页。右边是个Panel,把窗体加载到Panel里面,需要设置Form.TopLevel=false。

    这个软件实现的基本功能是客户关系管理。客户区域,客户信息,用户角色权限,数据导入导出,这几个基本的功能,还实现有报表,采用SQL Server Reporting Services的轻量级RDLC报表技术,浏览客户报表

    image

    对于显示RDLC报表,主要的实现代码如下

    rpt.LocalReport.ReportPath = AppDomain.CurrentDomain.BaseDirectory + "CustomerReport.rdlc";
    BaseOperate boperate = new BaseOperate();
    DataTable tbl = boperate.getds("  SELECT ClientID, CName, CStep, CRoot, CType, CTrade, CArea, 
    CPhone, CFax, CPostCode, CAddress, CEmail, CRemark FROM dbo.tb_ClientInfo "
    , "tb_ClientInfo").Tables[0]; if (tbl != null) { rpt.LocalReport.DataSources.Clear(); rpt.LocalReport.DataSources.Add(new Microsoft.Reporting.WinForms.ReportDataSource(
    "db_CrmDataSet_tb_ClientInfo", tbl)); rpt.LocalReport.Refresh(); } rpt.RefreshReport();

    把写好的SQL代码传送到SQL Server,返回数据集DataSet,传到报表中,即可显示RDLC报表的内容。

    数据访问技术,采用基本的SQL+DAO实现,没有使用ORM,也没有使用数据绑定技术,所以代码看起来会有些臃肿,而且不必要。如果你对下面的代码感觉到厌恶,请参考我的这篇文章《知识管理系统Data Solution研发日记之十一 数据绑定技术的应用》,它可大大简化把数据绑定到界面,再从界面中写回到数据库中。

    private void frmUserManage_Load(object sender, EventArgs e)
    {
         DataSet myds = boperate.getds(M_str_sql,M_str_table);
         dgvUInfo.DataSource = myds.Tables[0];
         if (myds.Tables[0].Rows.Count > 0)
               tsbtnDel.Enabled = true;
         else
              tsbtnDel.Enabled = false;
    }
    
    private void tsbtnAdd_Click(object sender, EventArgs e)
    {
         opAndvalidate.autoNum("select UserID from tb_User", "tb_User", "UserID", "YH", "1000001", txtUserID);
         tsbtnSave.Enabled = true;
         M_int_judge = 0;
         txtUserName.Text = "";
         txtUserPwd.Text = "";
    
    }

    如果你有数据绑定的经验,这些代码是不必要的。限制于当时我的技术水平,只做到了这样,的确只有不断的学习才有进步。如果一直停留在初始的技术经验上,可能工作五年和工作一年没有什么区别。这句话有些尖锐,面试的时候经常被面试官提到,经常的对自己说这句话,反思自己技术上的收获,不断进步。

    CRM系统的代码的可读价值不高,基本上就是DAO+SQL的组合,业务逻辑和界面混淆,数据访问与业务逻辑混淆,所以不推荐你直接阅读它的代码。我的目标是,你只要从代码中获取你需要的界面框架即可,我要达表达的重点也在于它的界面框架。如果你想把它改良一下,下面我提供的思路可以帮助你做这件事。

    1. 界面实现为多国语言,简体中文,英语,繁体。推荐用数据库表的形式来保存多国语言的资源文件。因为系统部署到客户那边后,客户可能需要修改界面的语言。举例说明,关于中心,中央的英语表示,在英国用Centre,美国用常Centre,这是两种文化的文字差异。CRM系统要允许用户修改界面的默认语言定义。存到数据库,再提供一个表操作程序,更新语言资源。

    2. 关于实现多国语言的代码,下面的例子很值得你借鉴运用。

    private void ApplyLanguageResource()
     {        
                foreach (Control ctl in Controls)
                {
                   if(ctrl is Label)
                    {
                          Label  lable=ctrl as Label;
                          label.Text=LanguageHelper.GetTranslation(label.Text)
                     }
    
                    if(ctrl is ToolStripMenuItem)
                    {
                           ToolStripMenuItem strip=ctrl as ToolStripMenuItem
                           strip.Text=LanguageHelper.GetTranslation(label.Text)
                     }
                   
                     //tab control,button...
                }        
            }
            this.Text=LanguageHelper.GetTranslation(this.Text)
     }

    再把这个方法放到BaseForm类型中,让其它的类型继承于这个BaseForm类型,于是乎,任何新创建的窗体,都可以获取改变界面语言的能力。这也是我见到的最好的实现多国语言的方案。

    这里有一点代码重复的味道,应该是简写成这样才是没有坏味道(重复)的代码

    private void ApplyLanguageResource()
    {        
           foreach (Control ctl in Controls)
           {
                   //对于设置文字都是Text属性的控件(Label,Button,ToolStripMenuItem),都可以这样写
                  string originalText=ReflectionHelper.GetProperty(ctrl,"Text");
                  string tranlatedText=LanguageHelper.GetTranslation(originalText);
                  ReflectionHelper.SetProperty(ctrl,"Text", translatedText);                 
            }
            this.Text=LanguageHelper.GetTranslation(this.Text)
    }

    运用反射技术,实现通用的设置文字语言的属性。代码比上面的简洁很多。

    3  经过几年的积累,对于访问SQL Server更多认识理解。相对于使用ORM框架,即使要手写SQL语句访问数据库,也要制作一个SQL代码生成器,以减少键盘的敲打次数。手写SQL最怕的就是增加和减少字段,可能所有的SQL Script都要重新调试一遍。使用ORM框架则几乎可以不改动任何代码。把SQL Script封装到DAO类型中,还应该提供一个DAO的类型工厂,缓存DAO类型,提高性能。我以为这两条经验,可以改善SQL Script+DAO类型项目的效率和可维护性。

    4 MIS类型的系统,通常就是主要资料输入,数据查询和报表查询。为三种类型的窗体,可以制作成标准的界面框架。资料输入,包含新增,修改,删除,导入功能,报表查询则只呈现指定的报表(Reporting Service,Crystal Rport)即可,数据查询针对于已经过帐或是以往的历史记录,只读不可修改。这三个窗体做可以做成标准的MIS窗体,以提高开发速度。请参考文章《信息化基础建设 窗体特性》和《信息化基础建设 窗体开发》来了解我是如何实现这三类标准窗体的。

    5. 对于左边的Navigation Bar的内容,需要提供一个Menu Designer,以设计它的内容。实用的系统,一般都要考虑到用户的喜好,对界面的定制能力。用户不会轻易认可我们设计的界面,它还需要在此基础上做一些小小的改动,或是个性化设置。个性化源自于ASP.NET 2.O,后来Windows 7操作系统也引入了这个概念,可以定制你喜欢的部分。

    6 对于界面的方案的演化,一直以来都有一个规律,跟随的微软的步伐就没有错。Visual C++ 5/6创建了标准的SDI/MDI应用框架,这时间的大量的程序都是模仿WORD/EXCEL的MDI风格。甚至还会给自己的产品名称后面加一个XP,以表示很符合潮流。当Office 2007出世以后,Ribbon界面的风格跟进,一时间许多程序又演化成Ribbon风格的界面样子,第三方控件厂商也都提供Ribbon风格的窗体控件。而现在的,TAB-MDI应该是流行的趋势

    image

    这种风格的界面框架,用户操作方便,程序实现上,把以前的SDI/MDI迁移(Migration,Upgrade)到这种TAB-MID界面上来也简单容易。我观察到,有几个公司的上市产品都是这种界面模式,更加坚定了我对这种界面模式的信心。

    在今年的上半年,我写过一篇文章,讲解这种界面模式的实现及其源码,请参考文章《Management Console 工具管理类软件通用开发框架(开放源码)》获取它的实现。

    请到epn.codeplex.com下载最新的源代码和数据库,代码名称是Paradox CRM。

  • 相关阅读:
    Hadoop集群(第3期)_VSFTP安装配置
    Hadoop集群(第5期)_Hadoop安装配置
    Hadoop集群(第6期)_WordCount运行详解
    Hadoop集群(第8期)_HDFS初探之旅
    Hadoop集群(第10期)_MySQL关系数据库
    Hadoop集群(第5期副刊)_JDK和SSH无密码配置
    Hadoop集群(第4期)_SecureCRT使用
    Hadoop集群(第9期)_MapReduce初级案例
    [winform]Value Object property expects either null/nothing value or int type
    【Winform】单元格的Formatted值的类型错误
  • 原文地址:https://www.cnblogs.com/JamesLi2015/p/2252108.html
Copyright © 2011-2022 走看看