Plato is a MVVM compliant 2D on-canvas graphics framework I've been designing and implementing for developing Windows Store apps.

The major functionalities of the framework have been implemented. But they are yet to go through a more thorough testing and further verification through usage. The library is shared open source on codeplex at https://plato2d.codeplex.com/

The framework is designed to be

  • based on Canvas and potentially able to handle any 2D graphics interactions
  • providing coarse cropping of views as one of its major purposes.
  • fully embracing MVVM pattern (by either using data template or dynamic user control creation) and able to targetting non-MVVM settings (such as Direct2D directly) and making the UI programming easier, maintainable and highly flexible
  • loosely coupled using dependency resolver (Trollveggen, another library I created for resolving Windows Store app runtime module dependencies)
  • friendly with undo/redo/(animation)recording framework Herodotus
  • with minimum modification it can also be ported to WPF which is pretty much an extended version of Windows Store environment

The framework is mainly composed of the following components,

Core Pipeline

The major purpose of the pipeline, which is also that of the whole Plato framework, is to determine which models (data objects) should have their view models and models added to the system and therefore displayed on the screen whereas which shouldn't.

  • IModelProvider, which collects visible models from model manager (which can be the same entity that implements this interface) determined by the methods exposed by the Visual department, organises them linearly in display order and feeds them through a collection and a collection change notification event to the renderer
  • Renderer, which in case of MVVM pattern is set of view model and model manager and in others could be simply a model drawer/renderer, is tied up with IModelProvider, receives the collection updates from IModelProvider and is responsible for displaying them on the screen as in the best way as it can. In MVVM case, it mainly consists of a view model manager that is directly fed by IModelProvider and organises a view models (may use view model builder to create new view models) collection accordingly and a view manager that is listening on the changes of the view models collection and in turn organises views accordingly on the canvas.

Any model change whether it be

  • caused by model data change
  • visual perspective change

will fire an event to the entity(entites) that eventually implements IModelProvider to get it to update the visible list as well as pass the event on to for instance the view model to update the appearance of the view accordingly.

Visual

The Visual department is responsible for

- view world conversion (ISightManager)

- hit and rectangular selection management

- various visual object dimension measuring for the Core Pipeline department and others (like FitAll)

- ...

Now the particular problem I was facing and this article is discussing is how to fit into this framework the case where the visual size of the object cannot be deduced from the model side of the pipeline which is a natural assumption of this framework.

A concrete example is how we deal with text elements. The scenario is like below

  • In the model part: the Text class that has a TextString property and a few others related to font information all of which can potentially change the size of its visual representation. And since it leaves the visual side to determine the size of the object based on the actual size of the text rendered, it has no way to provide the visual size for either a whether-on-screen check or bounds check for hit/selection.
  • The view model part: originally it should comfortably receive updates from the model and interpret them to view update as it normally does. However now it is encumbered with the duty to give feedback to the model and what's worse is it needs to wait for what's wanted from the view before it can do that.

To address this is issue now we need to enrich the Visual department with the functionalities other than the sight management listed above which if no such complexity is involved we can live without.
Before integrating this machanism the frame work is like

o IModelProvider 
      ModelChangedEvent                   |

Model --------------------> ModelManager  ------------ >  ViewModelManager ------> ViewManager

|                             ^                             |...|      Binding    |...| 
   |                             |                           ViewModel  -----------> View (on Canvas)
   |                             |  -----o ISightManager            (Update dimensions etc)  
   | VisualBounds                |                                
   ---------------------->  VisualTraits

NOTE the events propagation and processing in this framework (except the View/ViewModel interactions) are entirely synchronous and on-stack. Because as far as this can work this is the most efficient. Ensuring this can work means endless recursive calls are avoided and dependencies are resolved.

The whole framework becomes

o IModelProvider
      ModelChangedEvent (a)                |

Model --------------------> ModelManager  ------------ >  ViewModelManager ------> ViewManager

^  |                             ^                             |...|      Binding    |...|
|  |                             |                           ViewModel <-----------> View  (on Canvas)
|  |  VisualToMeasure            |  -----o ISightManager         |   (Update dimensions etc)
|  |  request                    |                               |
|  ---------------------->  VisualTraits <-----------------------| 
|                                       reset VisualToMeasure(c) |
|                                                                |
------------------------------------------------------------------
 Reinitiate ModelChange for invalid bounds with/without VisualToMeasure(b)

(a) Model initiates VisualToMeasure flagged change event whenever a bounds changing condition happens and bounds become invalid

(b) The view model updates the visual bounds of the model on it; whether or not it should cancel the VisualToMeasure depending on if it's certain that it has got the final results. But it should eventually resets it to give the object the chance to be taken off from the pipeline as appropriate. And it is the only legimitate entity to do so.

(c) One easy and safe way to do so is -

Every time the dimension updater in the view model is invoked normally by either the model update handler or view layout change handler,

  • Update the visual bounds of the model (therefore VisualBoundsValid is set to true accordingly)
  • Fire a VisualToMeasure flagged model change event
  • Reset the VisualToMeasure flag right after on VisualTraits

Implementation-wise, it's been found that one needs to be cautious with tying up the feedback handler with the LayoutUpdated event of the view as it's easy to create suspicious cyclic calls, which would be detected by the system first.

The only apparent defect is that the view and viewmodel will remain in the pipeline until the next time it's interogated, which happens when the view changes. However this happens quite often and is almost a perfectly justifiable time to decide whether the object should be swapped out of the pipeline. (The major unlikely scenario this could become an issue is when a large number of such objects outside the view scope are changing with view scope not changing at all, which is most likely caused by undo/redo operations, in which case the creation and retention of the unnecessary view/view model objects continue until a view change is made)

Reviews and Criticisms

One of the major downsides/limitations of this framework is that to make the visual adjustment feedback work it still has to have strong coupling between visual/view sections and the model management which potentially restricts or complicates the extension of the archecture to a distributed setting. This will be discussed in the follow up article The design of a distributed variant of Plato framework to support collaborated editing

Posterior visual bounds retrieval for the Plato framework的更多相关文章

  1. Visual Studio 2015上安装Entity Framework Power Tools

    Entity Framework Power Tools是个非常好用的EF Code First插件.通过它能够非常简单地生成和数据库结构匹配的model和dbcontext代码.使用的方法,这里有介 ...

  2. Configure Visual Studio 2013 for debugging .NET framework

    https://referencesource.microsoft.com/ In order to configure Visual Studio 2013 do the following in ...

  3. Visual Studio Debugger AutoExp.dat & Visualization Framework

    bing.com搜索: autoexp.dat 参考资料: AutoExp.dat http://www.virtualdub.org/blog/pivot/entry.php?id=120 http ...

  4. Visual Studio2017中如何让Entity Framework工具【ADO.NET实体数据模型】支持MYSQL数据源

    熟悉Entity Framework应该对以下图片不陌生,他就是ADO.NET实体数据模型向导:可以将数据库的表自动生成模型类,或者创建Code First的模型文件. 但是这个模型向导默认只显示微软 ...

  5. The design of a distributed variant of Plato framework to support collaborated editing

    A first thought system architecture (pulling mode) is one that the server doesn't keep client inform ...

  6. 如何在 Visual Studio 2013 中调试.NET Framework 4.5.1 代码

    版本需求如标题,在 工具->选项->调试->常规 中,更改以下设置: 禁用:启用“仅我的代码”.逐过程执行属性和运算符(仅限托管).要求源文件与原始版本完全匹配 启用:启用 .NET ...

  7. visual studio 2010 C#编程时 没有.NET framework 2.0目标框架的解决办法

    解决办法是安装Framework .NET 3.5 Sp1 因为visual studio 2010是依赖.NET Framework 3.5 Sp1来识别其它版本的.NEt framework的. ...

  8. ASP .NET MVC 之Entity Framework入门教程及源码

    本文主要的目的是 1. 说明Entity Framework Power Tools如何使用. 2. Entity Framework  快速门 实验环境: OS: Windows Server 20 ...

  9. 【极力分享】[C#/.NET]Entity Framework(EF) Code First 多对多关系的实体增,删,改,查操作全程详细示例【转载自https://segmentfault.com/a/1190000004152660】

      [C#/.NET]Entity Framework(EF) Code First 多对多关系的实体增,删,改,查操作全程详细示例 本文我们来学习一下在Entity Framework中使用Cont ...

随机推荐

  1. Clr Via C#读书笔记---程序集的加载和反射

    #1 加载程序集 Assembly.Load: public class Assembly { public static Assembly Load(AssemblyName assemblyRef ...

  2. CLR via C#(02)-基元类型、引用类型、值类型

    http://www.cnblogs.com/qq0827/p/3281150.html 一. 基元类型 编译器能够直接支持的数据类型叫做基元类型.例如int, string等.基元类型和.NET框架 ...

  3. WMI测试

    https://social.msdn.microsoft.com/Forums/windowshardware/zh-CN/c5af7959-95d3-4e1b-ab40-96a2a31c2af2/ ...

  4. 【JAVA与DOM4J实现对XML文档的CRUD操作】

    一.简介 1.网上下载DOM4J 1.6.1压缩包,解压开之后,发现几个目录和一个jar文件,jar文件是必须的文件其它目录: docs目录:帮助文档的目录,单击index.html: Quick s ...

  5. C#调用ArcGIS REST服务

    ArcGIS REST API提供了简单.开放的接口来访问和使用ArcGIS Server发布的服务.使用ArcGIS REST API通过URL可以获取和操作每一个服务中的所有资源和操作. 1.使用 ...

  6. JSON资料汇总

    网络入门学习资料 1.W3School的JSON教程:http://www.w3school.com.cn/json/index.asp 2.Introducing JSON[介绍JSON]:http ...

  7. Build better apps: Windows 10 by 10 development series

    http://blogs.windows.com/buildingapps/2015/08/05/build-better-apps-windows-10-by-10-development-seri ...

  8. LoadRunner常用函数列表

    LoadRunner常用函数列表 Web相关函数 函 数 功  能  描  述 web_custom_request 用户可以通过该函数自行创建一个HTTP请求的函数 web_image 模拟用户单击 ...

  9. hdu 1003 MAX SUM 简单的dp,测试样例之间输出空行

    测试样例之间输出空行,if(t>0) cout<<endl; 这样出最后一组测试样例之外,其它么每组测试样例之后都会输出一个空行. dp[i]表示以a[i]结尾的最大值,则:dp[i ...

  10. BZOJ 2342 回文串-Manacher

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2342 思路:先跑一遍Manacher求出p[i]为每个位置为中心的回文半径,因为双倍回文串 ...