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#的互动。

    (未完待续...)

  • 相关阅读:
    mac上python3安装HTMLTestRunner
    双目深度估计传统算法流程及OpenCV的编译注意事项
    深度学习梯度反向传播出现Nan值的原因归类
    1394. Find Lucky Integer in an Array
    1399. Count Largest Group
    1200. Minimum Absolute Difference
    999. Available Captures for Rook
    509. Fibonacci Number
    1160. Find Words That Can Be Formed by Characters
    1122. Relative Sort Array
  • 原文地址:https://www.cnblogs.com/feedback/p/1736949.html
Copyright © 2011-2022 走看看