转:[Silverlight入门系列]使用MVVM模式(9): 想在ViewModel中控制TreeView节点展开?

很多童鞋看了我的博客以后也去实践MVVM,但却发现Silverlight实践中的MVVM很难实现,比纯粹的CodeBehind难度大很多。首先是原来在xaml.cs的CodeBehind部分很容易控制界面逻辑,现在这部分逻辑移到ViewModel里面去了以后,就很难调用CodeBind的部分;其次是很多View和ViewModel、或者一个ViewModel多个View,他们之间如何通

  

  很多童鞋看了我的博客以后也去实践MVVM,但却发现Silverlight实践中的MVVM很难实现,比纯粹的CodeBehind难度大很多。首先是原来在xaml.cs的CodeBehind部分很容易控制界面逻辑,现在这部分逻辑移到ViewModel里面去了以后,就很难调用CodeBind的部分;其次是很多View和ViewModel、或者一个ViewModel多个View,他们之间如何通信?这些问题貌似非常复杂。其实很简单,就是分割、分工、协同。搞清楚谁应该负责什么,如何抽象和隔离、然后如何用适合的技术来实现。这些问题想清楚了搞清楚了就不难了。

  提出问题:MVVM的TreeView不能在ViewModel中按需展开TreeNode节点

  今天要讲的就是一个很常见的问题:你的TreeView已经用MVVM模式实现了(参见这一篇:[Silverlight入门系列]Prism中TreeView真正实现MVVM模式和Expanded发生时异步动态加载子节点(WCFRiaService)),但你在ViewModel的业务逻辑加载了节点以后要自动展开第一个节点怎么办?你发现现在不能直接调用Node.Expand()方法了,因为你在ViewModel中。怎么办?本文的方法其实很简单,也是Silverlight中MVVM消除CodeBehind的万能膏药:DataTrigger + Behavior。(其它方法参见我的上一篇:[Silverlight入门系列]使用MVVM模式(9): 想在ViewModel中控制Storyboard动画?)

  解决思路:Silverlight中MVVM消除CodeBehind的万能膏药:DataTrigger + Behavior

  首先实现一个Behavior,这个行为就是展开TreeView的Root节点喽。然后这个Behavior什么时候执行呢?我们需要是按需执行。呼叫它的时候它才执行。那就在ViewModel里面加一个属性,这个属性实现了INotifyPropertyChanged接口,当ViewModel里面一段逻辑执行完毕需要呼叫它展开节点了,那就设置这个属性为True,它就会因为绑定自动通知界面。而Behavior和这个属性怎么联系起来?那就是通过Trigger,监控这个属性变化,当值变为需要的值就自动执行你的Behavior。思路就是这样。

  实现代码

  

  上面那个图是最后的XAML代码了。先来看看展开根节点的Behavior:

   1: using System.Windows.Controls;
   2: using System.Windows.Interactivity;
   3: using System.ComponentModel;
   4: using System;
   5:  
   6: namespace SilverlightApplication1
   7: {
   8:     [System.ComponentModel.Description("Expands Tree Root Node")]
   9:     public class TreeRootExpandBehavior : TargetedTriggerAction<LazyTreeView>, INotifyPropertyChanged
  10:     {
  11:         #region "Initialization"
  12:  
  13:         private LazyTreeView objTreeView;
  14:  
  15:         /// <summary>
  16:         /// Called after the action is attached to an AssociatedObject.
  17:         /// </summary>
  18:         protected override void OnAttached()
  19:         {
  20:             base.OnAttached();
  21:  
  22:             objTreeView = (LazyTreeView)(AssociatedObject);
  23:         }
  24:  
  25:         /// <summary>
  26:         /// Invokes the action.
  27:         /// </summary>
  28:         /// <param name="parameter">The parameter to the action. If the action does not require a parameter, the parameter may be set to a null reference.</param>
  29:         protected override void Invoke(object parameter)
  30:         {
  31:             ExpandRoot();
  32:         }
  33:  
  34:         #endregion
  35:  
  36:         #region "Expands the root"
  37:  
  38:         /// <summary>
  39:         /// Expands the root.
  40:         /// </summary>
  41:         private void ExpandRoot()
  42:         {
  43:             objTreeView.UpdateLayout();
  44:  
  45:             var vm = (MyViewModel)objTreeView.DataContext; //MyViewModel是你的TreeView的ViewModel
  46:             if (vm == null) return;
  47:  
  48:             var root = vm.Root;//这个是ViewModel的一个公共属性,你的可能不一样,知道原理就行了
  49:             if (vm.Root == null || vm.Root.Count == 0) return;
  50:  
  51:             var objTreeViewItem = (TreeViewItem)objTreeView.ItemContainerGenerator.ContainerFromItem(root[0]);
  52:             if (objTreeViewItem != null)
  53:             {
  54:                 objTreeViewItem.IsExpanded = true;
  55:                 objTreeView.UpdateLayout();
  56:             }
  57:         }
  58:  
  59:         #endregion
  60:  
  61:         #region "INotifyPropertyChanged Implementation"
  62:  
  63:         public event PropertyChangedEventHandler PropertyChanged;
  64:  
  65:         /// <summary>
  66:         /// Notifies the property changed.
  67:         /// </summary>
  68:         /// <param name="info">The info.</param>
  69:         private void NotifyPropertyChanged(String info)
  70:         {
  71:             if (PropertyChanged != null)
  72:             {
  73:                 PropertyChanged(this, new PropertyChangedEventArgs(info));
  74:             }
  75:         }
  76:         #endregion
  77:     }
  78: }

  在ViewModel里面加个属性

  

  当ViewModel里面一段逻辑执行完毕需要呼叫它展开节点了,那就设置这个属性为True,它就会因为绑定自动通知界面。而Behavior和这个属性怎么联系起来?那就是通过Trigger,监控这个属性变化,当值变为需要的值就自动执行你的Behavior。注意引用几个命名空间:

   1: //引用下面命名空间:
   2: System.Windows.Interactivity
   3: Microsoft.Expression.Interactions
   4:  
   5: //在Xaml中:
   6: xmlns:ei="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions"
   7: xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 

  源代码下载

  本文来自Mainz的博客,原文地址:http://www.cnblogs.com/Mainz/archive/2011/09/20/2182267.html

时间: 2024-10-05 22:09:22

转:[Silverlight入门系列]使用MVVM模式(9): 想在ViewModel中控制TreeView节点展开?的相关文章

MVVM模式解析和在WPF中的实现(三) 命令绑定

MVVM模式解析和在WPF中的实现(三) 命令绑定 0x00 命令绑定要达到的效果 命令绑定要关注的核心就是两个方面的问题,命令能否执行和命令怎么执行.也就是说当View中的一个Button绑定了ViewModel中一个命令后,什么时候这个Button是可用的,按下Button后执行什么操作.解决了这两个问题基本就实现了命令绑定.另外一个问题就是执行过程中需要的数据(参数)要如何传递.本次主要探讨这几个问题. 0x01 命令绑定的实现 自定义一个能够被绑定的命令需要实现ICommand接口.该接

WPF快速入门系列(8)——MVVM快速入门

一.引言 在前面介绍了WPF一些核心的内容,其中包括WPF布局.依赖属性.路由事件.绑定.命令.资源样式和模板.然而,在WPF还衍生出了一种很好的编程框架,即WVVM,在Web端开发有MVC,在WPF客户端开发中有MVVM,其中VM就相当于MVC中C(Control).在Web端,微软开发了Asp.net MVC这样的MVC框架,同样在WPF领域,微软也开发了Prism这样的MVVM框架.Prism项目地址是:http://compositewpf.codeplex.com/SourceCont

MVVM模式解析和在WPF中的实现(一)

MVVM模式简介 MVVM是Model.View.ViewModel的简写,这种模式的引入就是使用ViewModel来降低View和Model的耦合,说是降低View和Model的耦合.也可以说是是降低界面和逻辑的耦合,理想情况下界面和逻辑是完全分离的,单方面更改界面时不需要对逻辑代码改动,同样的逻辑代码更改时也不需要更改界面.同一个ViewModel可以使用完全不用的View进行展示,同一个View也可以使用不同的ViewModel以提供不同的操作. 1.Model Model就是一个clas

【Spring入门系列】代理模式和AOP

代理模式概述 代理是一种设计模式,提供了对目标对象另外的访问方式,通过代理对象访问目标对象.这样可以在目标对象功能实现的基础上,增加额外的功能,从而达到扩展目标对象功能的效果.简言之,代理模式就是设置一个中间代理来控制访问原目标对象,以达到增强原对象的功能和简化访问方式. 静态代理 这种代理方式需要代理对象和目标对象实现一样的接口. 优点:可以在不修改目标对象的前提下扩展目标对象的功能. 缺点:1.冗余,由于代理对象要实现与目标对象一致的接口,会产生过多的代理类.2.不易维护,一旦接口增加方法,

笔记03 wpf 在MVVM模式下怎样在Viewmodel里面获得view的控件对象

 转自http://blog.csdn.net/qing2005/article/details/6601199http://blog.csdn.net/qing2005/article/details/6601475 MVVM中轻松实现Command绑定(二)传递Command参数 属性栏里去设置的.语句应该是CommandParameter="{Binding ElementName=控件名}" 我们如果需要在Command中传递参数,实现也很简单.DelegateCommand还

企业级架构 MVVM 模式指南 (WPF 和 Silverlight 实现) 译(2)

本书包含的章节内容 第一章:表现模式,以一个例子呈献给读者表现模式的发展历程,我们会用包括MVC和MVP在内的各种方式实现一个收费项目的例子.沿此方向,我们会发现每一种模式的问题所在,这也是触发设计模式发展的原因.本章还会说明如果应用不当,MVC和MVP这些依赖.Net事件的表现模式是怎么导致内存泄漏的.本章会谈论各种表现模式的优缺点,并且留给读者自我思考的问题,如为什么用MVVM设计模式来代替MVP或是MVC.第二章:介绍MVVM,包括使MVVM魅力四射的WPF和Silverlight的各种特

企业级架构 MVVM 模式指南 (WPF 和 Silverlight 实现) 译(1)

前言对于WPF和Silverlight来讲,MVVM是微软设计师和业内专家高度推荐的非常棒的一种设计模式.本书会探讨MVVM设计模式的一些自身缺陷以及为什么MVVM还不能成为行业内的标准设计模式.这会帮助WPF和Silverlight开发者更加理解MVVM模式. 本书会通过介绍工具,编程技术来帮助你找到最适合你项目的MVVM设计方式.实现MVVM设计模式是一个不小的挑战,本书还会帮你在企业级应用项目中解决很多常见问题. 本书会使你提高WPF和Silverlight水平,处理在编程中遇到的许多具有

WPF MVVM从入门到精通1:MVVM模式简介

刚开始接触和使用MVVM模式的时候,就有一种感觉:哇,实现这么一丁点的功能,竟然要写这么多代码,太麻烦了吧!但是后来当我熟悉了这种模式之后,感觉就变成了:哇,还是这么麻烦. 没错,使用MVVM模式的确要在项目中增加很多代码.不过MVVM设计模式是有它的优点的,不然就不会存在.把界面和业务逻辑分离,这是MVVM的根本目的.WPF的依赖属性.数据绑定等机制,很好地帮助我们实现MVVM模式,基本可以做到在界面层不出现业务逻辑代码. 我们先来看一下MVVM模式的基本结构: View就是界面,可以理解为X

angular中的MVVM模式

在开始介绍angular原理之前,我们有必要先了解下mvvm模式在angular中运用.虽然在angular社区一直将angular统称为前端MVC框架,同时angular团队也称它为MVW(Whatever)框架,但angular框架整体上更接近MVVM模式.下面是Igor Minar发布在Google+ https://plus.google.com/+IgorMinar/posts/DRUAkZmXjNV的文章内容: MVC vs MVVM vs MVP. What a controver