WF4设计器数据模型:ModelItem和ModelProperty

简介:

下面是WF设计器结构的基本概述。如下:

image

这里有几个重要组成部分:

  • Source:在VS中,就是XAML,但是这代表了我们正在编辑的持久存储。
  • Instance:代表在内存中正在编辑的条目,对于vs2010中的WF设计器,对应一个System.Activities实例(对象树层次结构)。
  • Model Item Tree :作为View和Instance之间的媒介,并负责对更改通知和跟踪比如撤消状态。
  • Design View:呈现给用户的可视化的编辑视图,这个设计器是用WPF编写的。
  • Metadata Store:类型和设计器之间的映射的一个属性表。

在看上面的图的时候你可能会认为,可以将DesignView直接绑定到Instance,这种方式可以工作,但会有很多问题,最明显的问题是我们的活动类型不会从DependencyObject继承或实现INotifyPropertyChanged的接口。我们也不能指定所有集合都是ObservableCollection(ObservableCollection 已从 WindowsBase.dll 移到 System.dll)。另外,我们要考虑支持一些设计时服务比如撤销/重复,而且在跨越许多对象类型的过程中我们需要确保始终能够处理这些,包括那些不是被我们写的类型。如果我们直接从View到Instance,就将二者仅仅的耦合在一起,会给我们将来做更有趣的事带来不便。例如,我们想要增加更新对象实例的重构支持,我们需要做的不仅仅是对象图,model item tree也需要跟踪很多变化。

The ModelItem tree 

来看一个例子,这个例子和WF的设计器并没有直接的关系,只是来模拟这种方式:

public class Animal
{
    // simple property
    public string Name { get; set; }
    // complex property 
    public Location Residence { get; set; } 
    // list 
    public List<Animal> CloseRelatives { get; set; }
    // dictionary
    public Dictionary<string, object> Features { get; set; } 
}

public class Location
{
    public string StreetAddress { get; set; }
    public string City { get; set; }
    public string State { get; set; } 
}
 
EditingContext ec = new EditingContext();
var companion1 = new Animal { Name = "Houdini the parakeet" };
var companion2 = new Animal { Name = "Groucho the fish" };
var animal = new Animal 
                 {
                       Name = "Sasha the pug",
                       Residence = new Location 
                       {
                           StreetAddress = "123 Main Street",
                           City = "AnyTown",
                           State = "Washington"
                       },
                       Features = { 
                          {"noise", "snort" },
                          {"MeanTimeUntilNaps", TimeSpan.FromMinutes(15) }
                       },
                       CloseRelatives = { companion1, companion2 } 
               };
ModelTreeManager mtm = new ModelTreeManager(ec);  mtm.Load(animal);
ModelItem mi = mtm.Root;
 

下图是Animal与ModelItem和ModelProperty的对应关系:

IMAG0111
 
下图可以看到一些具体的属性情况:
image
 
可以通过下面方式来获得相关属性值:
root.Properties["Residence"].
                Value.
                Properties["StreetAddress"].
                Value.GetCurrentValue()
你可能觉得上面的方式比较丑陋,但是在XAML中可以ModelItem.Location.StreetAddress自动路由过来,而其WF团队还承诺正式版会增加Dynamic的支持。
下面是一些测试:

   1:  ModelItem root = mtm.Root;
   2:  Assert.IsTrue(root.GetCurrentValue() == animal, "GetCurrentValue() returns same object");
   3:  Assert.IsTrue(root.ItemType == typeof(Animal),"ItemType describes the item");
   4:  Assert.IsTrue(root.Parent == null,"root parent is null");
   5:  Assert.IsTrue(root.Source == null, "root source is null");
   6:  Assert.IsTrue(((List<Animal>)root.Properties["CloseRelatives"].ComputedValue)[0] == companion1, 
   7:             "ComputedValue of prop == actual object");
   8:  Assert.IsFalse(((List<Animal>)root.Properties["CloseRelatives"].ComputedValue)[0] == companion2, 
   9:             "ComputedValue of prop == actual object");
  10:  Assert.AreEqual(root.Properties["Residence"].
  11:      Value.
  12:      Properties["StreetAddress"].
  13:      Value.GetCurrentValue(), "123 Main Street", "get actual value back out");
  14:  Assert.AreEqual(root, root.Properties["Residence"].Parent, "property points to owner");
  15:  ModelItem location = root.Properties["Residence"].Value;
  16:  Assert.AreEqual(root.Properties["Residence"], location.Source, "sources point to the right place");
 

   1:  EditingContext ec = new EditingContext();
   2:  ModelTreeManager mtm = new ModelTreeManager(ec);
   3:  mtm.Load(new Sequence());
   4:  mtm.Root.Properties["Activities"].Collection.Add(new WriteLine());
本文转自生鱼片博客园博客,原文链接:http://www.cnblogs.com/carysun/archive/2009/11/20/WF4-ModelItem.html,如需转载请自行联系原作者
相关文章
|
11月前
|
Ubuntu Linux 编译器
linux下交叉编译licensecc
通过本文的步骤,您可以在Linux环境下成功交叉编译LicenseCC。本文详细介绍了环境准备、工具链安装、源代码下载、CMake配置、编译和验证的全过程。希望这些内容对您的学习和工作有所帮助。
388 62
|
4天前
|
人工智能 JavaScript Linux
【Claude Code 全攻略】终端AI编程助手从入门到进阶(2026最新版)
Claude Code是Anthropic推出的终端原生AI编程助手,支持40+语言、200k超长上下文,无需切换IDE即可实现代码生成、调试、项目导航与自动化任务。本文详解其安装配置、四大核心功能及进阶技巧,助你全面提升开发效率,搭配GitHub Copilot使用更佳。
|
6天前
|
存储 人工智能 自然语言处理
OpenSpec技术规范+实例应用
OpenSpec 是面向 AI 智能体的轻量级规范驱动开发框架,通过“提案-审查-实施-归档”工作流,解决 AI 编程中的需求偏移与不可预测性问题。它以机器可读的规范为“单一真相源”,将模糊提示转化为可落地的工程实践,助力开发者高效构建稳定、可审计的生产级系统,实现从“凭感觉聊天”到“按规范开发”的跃迁。
819 12
|
2天前
|
云安全 安全
免费+限量+领云小宝周边!「阿里云2026云上安全健康体检」火热进行中!
诚邀您进行年度自检,发现潜在风险,守护云上业务连续稳健运行
1162 1
|
5天前
|
消息中间件 人工智能 Kubernetes
阿里云云原生应用平台岗位急招,加入我们,打造 AI 最强基础设施
云原生应用平台作为中国最大云计算公司的基石,现全面转向 AI,打造 AI 时代最强基础设施。寻找热爱技术、具备工程极致追求的架构师、极客与算法专家,共同重构计算、定义未来。杭州、北京、深圳、上海热招中,让我们一起在云端,重构 AI 的未来。
|
4天前
|
人工智能 JavaScript 前端开发
【2026最新最全】一篇文章带你学会Cursor编程工具
本文介绍了Cursor的下载安装、账号注册、汉化设置、核心模式(Agent、Plan、Debug、Ask)及高阶功能,如@引用、@Doc文档库、@Browser自动化和Rules规则配置,助力开发者高效使用AI编程工具。
646 4
|
10天前
|
存储 JavaScript 前端开发
JavaScript基础
本节讲解JavaScript基础核心知识:涵盖值类型与引用类型区别、typeof检测类型及局限性、===与==差异及应用场景、内置函数与对象、原型链五规则、属性查找机制、instanceof原理,以及this指向和箭头函数中this的绑定时机。重点突出类型判断、原型继承与this机制,助力深入理解JS面向对象机制。(238字)
|
8天前
|
IDE 开发工具 C语言
【2026最新】VS2026下载安装使用保姆级教程(附安装包+图文步骤)
Visual Studio 2026是微软推出的最新Windows专属IDE,启动更快、内存占用更低,支持C++、Python等开发。推荐免费的Community版,安装简便,适合初学者与个人开发者使用。
929 11
|
4天前
|
存储 人工智能 测试技术
【Claude Skills】从原理到实战的完全指南
Claude Skills通过模块化设计,将AI变为领域专家,实现工作流标准化。它支持指令封装、自动触发与脚本集成,提升复用性与协作效率,适用于个人提效与团队协同,是AI定制化的新范式。