zoukankan      html  css  js  c++  java
  • 动态【配置文件】之实现 (二)

      前一篇,我们定义并实现了配置文件的读写功能,这次我们来实现配置文件的界面展示。之前我们设计的时候,就要求界面能够动态展现,比如在界面定义文件中新增一个CheckBox定义,那么要求界面能够反映出来。

    本次界面还原技术,我们采用SharpDev的方式,利用xml文件对界面进行描述,然后利用反射将界面展示出来。(PS:如果你用过Delphi,你同样会发现Delphi的frm文件也是采用这样的思路),这里有个问题需要暂时搁置一下,对于界面中用到的图像资源的处理,目前暂时不用管。

    好了,我们先来看一下设计思路

    总界面管理类定义

    代码
        /// <summary>
        
    /// 界面管理类
        
    /// </summary>
        public interface IConfigUiManager
        {
            
    /// <summary>
            
    /// 默认界面文件路径
            
    /// </summary>
            string DefaultFloder
            {
                
    get;
                
    set;
            }
            
    /// <summary>
            
    /// 界面描述文件的后缀
            
    /// </summary>
            string DefaultExt
            {
                
    get;
                
    set;
            }
            
    /// <summary>
            
    /// 扫描默认目录下的界面文件并加载
            
    /// </summary>
            void Load();
            
    /// <summary>
            
    /// 定位某个界面
            
    /// </summary>
            
    /// <param name="pName"></param>
            
    /// <returns></returns>
            IConfigSectionUi FindUi(string pName);
            
    /// <summary>
            
    /// 展示总配置界面
            
    /// </summary>
            void ShowUi();
        }

     当个配置程序节的界面定义

    代码
        /// <summary>
        
    /// 单个配置程序节的界面
        
    /// </summary>
        public interface IConfigSectionUi
        {
            
    /// <summary>
            
    /// 是否集成到总界面中
            
    /// </summary>
            bool LazyLoad
            {
                
    get;
                
    set;
            }
            
    /// <summary>
            
    /// 界面名称
            
    /// </summary>
            string Name
            {
                
    get;
                
    set;
            }
            
    /// <summary>
            
    ///从配置文件中加载选项
            
    /// </summary>
            void LoadFromConfig();
            
    /// <summary>
            
    ///  将设置保存到配置文件中
            
    /// </summary>
            void SaveToConfig();
            
    /// <summary>
            
    /// 从xml文件中提取的界面
            
    /// </summary>
            System.Windows.Forms.Control Ui
            {
                
    get;
                
    set;
            }
            
    /// <summary>
            
    /// 展示当前的配置界面
            
    /// </summary>
            void ShowUi();
            
    void LoadFromFile(string pFileName);
            
    string Caption
            {
                
    get;
                
    set;
            }
            Control FindControl(
    string pCtlName);

        }

    在这里,我们需要声明一下,对于界面定义文件,我们支持两种方式,一种是Form形式定义,这样的方式允许程序在运行期弹出独立界面跟用户交互;其二,是UserControl方式,这样的方式运行两种模式运行,第一集成到配置总界面中集中管理,第二,单独的弹出界面跟用户交互;基于这样的考虑,所以,我在接口IConfigSectionUi中定义了标识LazyLoad。

    基本类的定义就是上面两个,但是辅助类还没有定义,这里,我不妨直接借用SharpDev的代码来实现

    这里用到了其中核心的一个类XmlLoader(具体实现可以参考其源代码)

      好了,这样一来,界面的还原功能就实现了。但还是没有达到我们之前制定的目标。好吧,我们来实现IConfigSectionUi.LoadFromFile方法

    代码
            XmlLoader xmlLoader = null;

            
    void IConfigSectionUi.LoadFromFile(string pFileName)
            {
                
    using (FileStream pStream = new FileStream(pFileName, FileMode.Open))
                {
                    AppConfig.Ui.FakeForm FakeForm 
    = new AppConfig.Ui.FakeForm();
                    
    object FakeObj = null;

                    
    if (pStream == null)
                    {
                        
    throw new System.ArgumentNullException("stream");
                    }
                    FakeForm.SuspendLayout();
                    xmlLoader 
    = new XmlLoader();
                    SetupXmlLoader();
                    
    if (pStream != null)
                    {
                        FakeObj 
    = xmlLoader.LoadObjectFromStream(FakeForm, pStream);
                    }
                    
    if (FakeForm.Controls.Count > 0)
                    {
                        
    this._Ui = FakeForm;
                        
    this._Name = FakeForm.Name;
                        
    this._LazyLoad = true;
                        
    this._Caption = FakeForm.Caption;
                        FakeForm.ResumeLayout(
    false);
                    }
                    
    else
                    {
                        
    this._Ui = (Control)FakeObj;
                        
    this._Name = _Ui.Name;
                        
    this._Caption = ((Ui.FakeUserControl)_Ui).Caption;
                    }
                    pStream.Close();
                }
            }

      嗯,我们按照两种方式,将界面Form和UserControl区分开了,那么在展现的做一下手脚就可以了。

    看一下总界面的展现方法实现

    代码
            void IConfigUiManager.ShowUi()
            {
                Ui.FormConfigMain FormConfigMain 
    = new AppConfig.Ui.FormConfigMain();
                TabControl pTab 
    = FormConfigMain.pcCtl;
                
    foreach (KeyValuePair<string, IConfigSectionUi> pUi in _List)
                {
                    
    if (pUi.Value.LazyLoad)
                    {
                        
    // pUi.Value.ShowUi();
                    }
                    
    else//加入总界面
                    {
                        TabPage pPage 
    = new TabPage();
                        pPage.Text 
    = pUi.Value.Caption;
                        pPage.Controls.Add(pUi.Value.Ui);
                        pUi.Value.Ui.Dock 
    = DockStyle.Fill;
                        pTab.TabPages.Add(pPage);
                    }
                }
                FormConfigMain.ShowDialog();
            }

    如果发现此界面为单独界面即Form类型,则不加载到总界面中;

    嗯,那么单个界面展示如何展示呢?看一下吧

    代码
            void IConfigSectionUi.ShowUi()
            {
                
    if (this._Ui == nullreturn;
                
    if (_LazyLoad)
                    
    this._Ui.Show();
                
    else
                {
                    Ui.FormConfigDynamic frm 
    = new AppConfig.Ui.FormConfigDynamic();
                    frm.pnlCtl.Controls.Add(
    this._Ui);
                    frm.Show();
                }
            }

    如果此界面为单独界面,直接Show出来,如果是个UserControl,则用内置的ormConfigDynamic界面包装一下然后Show出来。

    好了,到此为止,基本实现了我们之前定义的需求。

    展示一下几个测试界面

    好了,到此,界面的动态展示基本完成。下次,我们将解决界面内选项的动态展示,也就是涉及到脚本技术跟C#的互动。

    (未完待续...)

  • 相关阅读:
    接口和抽象类的区别
    MFC之ListCtrl动态添加按钮
    C++类间转换之dynamic_cast
    字符串提取
    C++实现快速排序
    MFC中CListCtrl类依靠CImageList贴图并显示不同图像
    北工大耿丹学院16级计科院3班C语言课程助教学期总结
    C语言课程2——我们交流的工具:Coding.net
    salt-minion安装脚本
    zabbix邮件报警脚本
  • 原文地址:https://www.cnblogs.com/feedback/p/1736949.html
Copyright © 2011-2022 走看看