动态【配置文件】之实现 (二)

  前一篇,我们定义并实现了配置文件的读写功能,这次我们来实现配置文件的界面展示。之前我们设计的时候,就要求界面能够动态展现,比如在界面定义文件中新增一个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#的互动。

(未完待续...)

原文地址:https://www.cnblogs.com/feedback/p/1736949.html