zoukankan      html  css  js  c++  java
  • [WPF] MVVM Plugin模式

    动机 :

    Plugin是在软件系统内增加功能的功能。
    如果在软件系统加入Plugin功能,能提高软件系统的重用性。

    加入Plugin功能的软件系统在开发完成之后。
    如果需要额外加入功能,不用变更已完成的软件系统就能加入新功能。
    并且因为不用变更已完成的软件系统,也就避免了修改软件系统会产生的风险。

    在MVVM的架构下View跟ViewModel各自独立,做Plugin功能也就变得比较复杂。
    必须要View跟ViewModel各自都有Plugin功能然后再互相组合,才能完成MVVM Plugin的功能。

    本篇文章记录在WPF上,如何实做MVVM Plugin。
    为自己做个纪录,也希望能帮助到有需要的开发人员。

    结构 :

    首先我们来看下图,说明了MVVM Plugin的结构。
    图中说明了整个结构包含的项目,并且也可以看到它们之间的相依关系。
    而MvvmPlugin.dll是整个Plugin的主要系统,MvvmPlugin.View与MvvmPlugin.ViewModel则是,主要系统之外要挂载的部份。

    接着看看下面两张图,说明了MvvmPlugin.dll的对象跟画面。
    由图中可以看出来,整个项目里的对象。
    可以分成两大类,分别代表MVVM的View跟ViewModel。
    代表View的部份负责实做,画面如何呈现的功能。
    代表ViewModel的部份是实做,画面要呈现甚么。
    在View跟ViewModel之间,则是用WPF的Binding功能来做连接。
    而在ViewModel里面,也可以看到是由AnchorViewModel来负责建立IWorkspaceViewModel。
    并且窗体画面会划分为两个区块,

    左边区块里的<<WPF ItemsControl>>
    -显示所系结的所有<<class>>AnchorViewModel。
    -只要增加<<class>>AnchorViewModel的数量,就会增加画面上的按钮数量。
    -使用<<WPF ItemTemplate>>来显示系结的<<class>>AnchorViewModel。

    右边区块里的<<WPF ContentControl>>
    -则会显示所系结的一个<<inteface>>IWorkspaceViewModel。
    -只要换掉<<inteface>>IWorkspaceViewModel的对象,就会变更画面上的窗体。

    回头看上一段落右边区块的说明,会发现没有描述<<inteface>>IWorkspaceViewModel采用甚么Template来显示。
    我们另外再参考下一张的图片说明,
    可以看到<<WPF ContentControl>>,使用外部Template来显示系结的<<inteface>>IWorkspaceViewModel。
    至于系统里有哪些外部Template、<<inteface>>IWorkspaceViewModel要用外部Template来显示,则是由<<xaml>>MainWindow.view.config.xaml所设定。
    而有哪些外部用来生成<<inteface>>IWorkspaceViewModel的<<class>>AnchorViewModel要显示,则是由<<xaml>>MainWindow.viewmodel.config.xaml来设定。
    在这两个档案数据内加入新增功能的数据,就可以完成MVVM Plugin要加入功能的功能。

    实做 :

    范列下载 :

    范例的程序代码较多,实做说明请参照范例程序内容。
    范例程序点此下载

    MvvmPlugin.dll :

    MvvmPlugin.dll是整个系统的主要结构。
    提供了可执行的应用程序外壳,并且也开放Plugin的功能用来挂载系统。
    主要参与者有:

    MainWindowViewModel
    -整个系统的主要ViewModel。
    -提供AnchorCollection及Workspace,给MainWindowView.xaml做Binding。
    -收到AnchorViewModel发出的WorkspaceViewModel事件时,用新的WorkspaceViewModel替换旧的。
    -使用XamlReader颇析外部MainWindow.viewmodel.config.xaml档案,当作AnchorCollection内容的来源。

    //使用XamlReader颇析外部MainWindow.viewmodel.config.xaml档案,当作AnchorCollection内容的来源。
    private IEnumerable<AnchorViewModel> CreateAnchorCollection(string anchorConfigFile)
    {
            #region Require
    
        if (string.IsNullOrEmpty(anchorConfigFile) == true) throw new ArgumentNullException();
    
        #endregion
    
        // Result
        List<AnchorViewModel> anchorList = new List<AnchorViewModel>();
    
        // Create
        ResourceDictionary resourceDictionary = this.CreateResourceDictionary(anchorConfigFile);
        foreach (object resource in resourceDictionary.Values)
        {
            AnchorViewModel anchorViewModel = resource as AnchorViewModel;
            if (anchorViewModel != null)
            {
                anchorViewModel.WorkspaceOpened += delegate(IWorkspaceViewModel workspace)
                {
                    IWorkspaceViewModel oldWorkspace = this.Workspace;
                    this.Workspace = workspace;
                    if (oldWorkspace != null) oldWorkspace.Dispose();
                };
                anchorList.Add(anchorViewModel);
            }
        }
    
        // return
        return anchorList;
    }
    
    private ResourceDictionary CreateResourceDictionary(string resourceDictionaryFile)
    {
        #region Require
    
        if (string.IsNullOrEmpty(resourceDictionaryFile) == true) throw new ArgumentNullException();
    
        #endregion
    
        // Require
        if (File.Exists(resourceDictionaryFile) == false) throw new ArgumentException(string.Format("File is not existed : {0}", resourceDictionaryFile));
    
        // Create ResourceDictionary            
        FileStream fileStream = new FileStream(resourceDictionaryFile, FileMode.Open);
        ResourceDictionary resourceDictionary = XamlReader.Load(fileStream) as ResourceDictionary;
    
        // Return
        return resourceDictionary;
    }
    

    MainWindow.xaml
    -整个系统的主要View。
    -直接在xaml内,建立MainWindowViewModel并且绑定。
    -与MainWindowViewModel提供的AnchorCollection及Workspace,做Binding。
    -参考外部ResourceDictionary的方式,读取MainWindow.view.config.xaml,作为Binding WorkspaceViewModel的Template。

    <!--参考外部ResourceDictionary的方式,读取MainWindow.view.config.xaml-->
    <Window.Resources>
        <ResourceDictionary Source="pack://siteoforigin:,,,/MainWindow.view.config.xaml" />
    </Window.Resources>
    
    <!--直接在xaml内,建立MainWindowViewModel并且绑定-->
    <Window.DataContext>
        <MvvmPlugin:MainWindowViewModel />
    </Window.DataContext>
    

    IWorkspaceViewModel
    -挂载进MvvmPlugin.dll的外部WorkspaceViewModel,要实做的接口。
    -与外部Template做Binding来显示。

    AnchorViewModel
    -挂载进MvvmPlugin.dll的外部AnchorViewModel,要实做的接口。
    -提供Title、ExecuteCommand,给MainWindowView.xaml做Binding。
    -触发时建立新的WorkspaceViewModel,发出事件通知MainWindowViewModel。

    MvvmPlugin.ViewModel.dll、MvvmPlugin.View.dll :

    MvvmPlugin.ViewModel.dll是要挂载的ViewModel实做,职责除了提供要挂载进系统的功能之外也负担了如何生成的职责。
    MvvmPlugin.ViewModel.dll是要挂载的View实做,职责主要是提供Binding的ViewModel的外观。
    之所以没有将这两个项目做合并,是为了突显在MVVM架构下View是可以独立做抽换的。
    主要参与者有:

    AAnchorViewModel
    -负责生成要挂载的ViewModel

    AWorkspaceViewModel
    -实际要挂载的ViewModel

    AWorkspaceView.xaml
    -实际要挂载的View

    后记 :

    在这个模式里,其实还少了一块Model的Plugin功能。
    因为Model的Plugin这个功能,相对于MVVM Plugin是比较独立的模式。
    在后续的文章里,将会有Model Plugin的独立介绍。

  • 相关阅读:
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    汉字转拼音2
    汉字转拼音
  • 原文地址:https://www.cnblogs.com/clark159/p/2339030.html
Copyright © 2011-2022 走看看