<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://geeks.ms/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Burbujas en .NET : prism, patrones</title><link>http://geeks.ms/blogs/etomas/archive/tags/prism/patrones/default.aspx</link><description>Etiquetas: prism, patrones</description><dc:language /><generator>CommunityServer 2008.5 SP1 (Build: 31106.3070)</generator><item><title>Caliburn… ¿sientes el poder de MVVM en tus manos?</title><link>http://geeks.ms/blogs/etomas/archive/2010/02/12/caliburn-191-sientes-el-poder-de-mvvm-en-tus-manos.aspx</link><pubDate>Fri, 12 Feb 2010 16:22:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:167258</guid><dc:creator>Eduard Tomàs i Avellana</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/etomas/rsscomments.aspx?PostID=167258</wfw:commentRss><comments>http://geeks.ms/blogs/etomas/archive/2010/02/12/caliburn-191-sientes-el-poder-de-mvvm-en-tus-manos.aspx#comments</comments><description>&lt;p&gt;Los m&amp;aacute;s frikis de por aqu&amp;iacute;, sabr&amp;eacute;is que Caliburn (&lt;em&gt;&lt;a target="_blank" href="http://la.wikipedia.org/wiki/Caliburnus"&gt;Caliburnus&lt;/a&gt;&lt;/em&gt; para ser exactos) era el nombre de una poderosa espada que luego alguien decidi&amp;oacute; rebautizar como &lt;a target="_blank" href="http://es.wikipedia.org/wiki/Excalibur"&gt;&lt;em&gt;Excalibur&lt;/em&gt;&lt;/a&gt;&amp;hellip; Como frikis hay en todas partes y en eso de la inform&amp;aacute;tica pues quiz&amp;aacute;s m&amp;aacute;s, &lt;a target="_blank" href="http://caliburn.codeplex.com/"&gt;Caliburn&lt;/a&gt; tambi&amp;eacute;n resulta ser el nombre de un framework para aplicaciones Silverlight y WPF. Dicho as&amp;iacute; parece ser lo mismo que &lt;a target="_blank" href="http://www.codeplex.com/CompositeWPF/"&gt;PRISM&lt;/a&gt; y en cierta manera ambos frameworks tienen el mismo objetivo y comparten muchas caracter&amp;iacute;sticas. Por ejemplo ambos frameworks se abstraen del contendor IoC a utilizar (es decir requieren uno, pero no se atan a ninguno), ambos dan soporte a vistas compuestas y ambos tienen el concepto de m&amp;oacute;dulo&amp;hellip; entonces &amp;iquest;en que se diferencian? Pues en como se enfocan para llegar al objetivo. El objetivo de este post es &lt;strong&gt;iniciar una serie de posts&lt;/strong&gt; (no se de cuantos :P) para hablar sobre Caliburn y compararlo con PRISM. Hoy, pero vamos a empezar por lo m&amp;aacute;s b&amp;aacute;sico&amp;hellip; :)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. Preparando el entorno&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;No es muy complicado preparar el entorno para trabajar con Caliburn: basta con &lt;a target="_blank" href="http://caliburn.codeplex.com/releases/view/34985"&gt;descargarse el framework (actualmente est&amp;aacute; en v1 RTW)&lt;/a&gt;. Caliburn (de nuevo al igual que PRISM) existe en dos sabores: Silverlight y WPF. Ambas versiones son esencialmente la misma salvando las diferencias t&amp;eacute;cnol&amp;oacute;gicas que existen entre Silverlight y WPF. Vamos a optar en este caso por una aplicaci&amp;oacute;n WPF.&lt;/p&gt;
&lt;p&gt;Abrimos VS2008 y creamos una nueva aplicaci&amp;oacute;n WPF. El siguiente paso es a&amp;ntilde;adir referencias a los ensablados de Caliburn que estar&amp;aacute;n en el directorio Bin/NET-3.5/debug (o release, hay ambas versiones). &lt;strong&gt;Nota:&lt;/strong&gt; Yo os recomiendo que os descargueis el codigo fuente y compileis Caliburn&amp;hellip; As&amp;iacute; ser&amp;aacute; m&amp;aacute;s f&amp;aacute;cil depurar! &lt;/p&gt;
&lt;p&gt;Si en lugar de WPF nuestra aplicaci&amp;oacute;n fuese Silverlight entonces debemos ir al directorio Bin/Silverlight-2.0 o Silverlight-3.0 seg&amp;uacute;n sea necesario. Para empezar vamos a usar Caliburn.Core.dll, Caliburn.PresentationFramework.dll y Microsoft.Practices.ServiceLocation.dll.&lt;/p&gt;
&lt;p&gt;Ahora s&amp;iacute;! Ya estamos listos para desenvainar la espada &amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. Empezando con Caliburn&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Caliburn tiene una idea muy clara sobre como se debe organizar la IU de tu aplicaci&amp;oacute;n: usando MVVM. Eso significa que vamos a tener un grupo de clases llamadas &lt;em&gt;ViewModels&lt;/em&gt; que van a ser los que tengan &lt;strong&gt;toda&lt;/strong&gt; la informaci&amp;oacute;n sobre los datos a mostrar. A cada &lt;em&gt;ViewModel&lt;/em&gt; le corresponder&amp;aacute; una vista (&lt;em&gt;View&lt;/em&gt;). El enlace entre las vistas y los &lt;em&gt;ViewModels&lt;/em&gt; ser&amp;aacute; a trav&amp;eacute;s de Bindings&amp;hellip; por supuesto que todo esto se puede hacer sin Caliburn, pero Caliburn nos da herramientas para que sea un poco m&amp;aacute;s f&amp;aacute;cil.&lt;/p&gt;
&lt;p&gt;Para empezar vamos a crear un ViewModel y una vista y vamos a dejar que la magia de Caliburn nos lo una. Para ello, &lt;strong&gt;creamos una carpeta llamada ViewModel&lt;/strong&gt; en nuestro proyecto. Es importante el nombre de esta carpeta, puesto que Caliburn asume que lo que en ella est&amp;eacute; son ViewModels o vistas. Dentro de dicha carpeta creamos una clase tal y como sigue:&lt;/p&gt;
&lt;div id="codeSnippetWrapper" style="text-align:left;line-height:12pt;background-color:#f4f4f4;margin:20px 0px 10px;width:97.5%;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;max-height:200px;font-size:8pt;overflow:auto;cursor:text;border:silver 1px solid;padding:4px;"&gt;
&lt;pre id="codeSnippet" style="text-align:left;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;padding:0px;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; UserViewModel&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; Nombre { get; set; }&lt;br /&gt;    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; Foto { get; set; }&lt;br /&gt;}&lt;/pre&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;Ya tenemos el ViewModel de un usuario: su nombre y su foto. Ahora el siguiente paso es crear una vista. Para ello a&amp;ntilde;adid un &lt;em&gt;User Control&lt;/em&gt; que se llame UserView. El nombre de nuevo es importante: Caliburn asumir&amp;aacute; que UserView es la vista para los &lt;em&gt;ViewModels&lt;/em&gt; de tipo UserViewModel. Poned el user control &lt;strong&gt;fuera&lt;/strong&gt; de la carpeta ViewModel. El c&amp;oacute;digo xaml puede ser algo parecido a:&lt;/p&gt;
&lt;div id="codeSnippetWrapper" style="text-align:left;line-height:12pt;background-color:#f4f4f4;margin:20px 0px 10px;width:97.5%;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;max-height:200px;font-size:8pt;overflow:auto;cursor:text;border:silver 1px solid;padding:4px;"&gt;
&lt;pre id="codeSnippet" style="text-align:left;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;padding:0px;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;UserControl&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;x:Class&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;CaliburnDemo.UserView&amp;quot;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color:#ff0000;"&gt;xmlns&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&amp;quot;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color:#ff0000;"&gt;xmlns:x&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml&amp;quot;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color:#ff0000;"&gt;Height&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;300&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Width&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;300&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Grid&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Label&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Height&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;28&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Margin&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;25,47,28,0&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;VerticalAlignment&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Top&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Content&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;{Binding Nombre}&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Label&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Image&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Margin&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;109,81,127,0&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Stretch&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Fill&amp;quot;&lt;/span&gt;  &lt;span style="color:#ff0000;"&gt;Width&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;64&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Height&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;64&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;VerticalAlignment&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Top&amp;quot;&lt;/span&gt; &lt;br /&gt;               &lt;span style="color:#ff0000;"&gt;Source&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;{Binding Foto}&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Label&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Height&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;28&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Margin&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;85,13,101,0&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;VerticalAlignment&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Top&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;Datos del Usuario:&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Label&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Grid&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;UserControl&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;Finalmente s&amp;oacute;lo nos queda un paso: modificar nuestra aplicaci&amp;oacute;n para que derive de &lt;em&gt;CaliburnApplication&lt;/em&gt;. Para ello, en App.cs modificad la clase para que derive de CaliburnApplication:&lt;/p&gt;
&lt;div id="codeSnippetWrapper" style="text-align:left;line-height:12pt;background-color:#f4f4f4;margin:20px 0px 10px;width:97.5%;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;max-height:200px;font-size:8pt;overflow:auto;cursor:text;border:silver 1px solid;padding:4px;"&gt;
&lt;pre id="codeSnippet" style="text-align:left;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;padding:0px;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;partial&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; App : CaliburnApplication&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color:#0000ff;"&gt;protected&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;override&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;object&lt;/span&gt; CreateRootModel()&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; UserViewModel();&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;Fijaos que redefinimos el m&amp;eacute;todo CreateRootModel: Este m&amp;eacute;todo (definido en CaliburnApplication) es el punto de entrada de nuestra aplicaci&amp;oacute;n. El tipo de ViewModel que creemos determinar&amp;aacute; el tipo de vista a utilizar y los datos iniciales a mostrar. Un detalle: Fijaos que &lt;strong&gt;no&lt;/strong&gt; vamos a crear una ventana nunca (nuestra vista UserView es un UserControl). No hay problema, porque si el ViewModel inicial no es una ventana, Caliburn la va a crear para nosotros.&lt;/p&gt;
&lt;p&gt;Hemos modificado la clase base de la aplicaci&amp;oacute;n en el fichero .cs y debemos hacer lo mismo en App.xaml:&lt;/p&gt;
&lt;div id="codeSnippetWrapper" style="text-align:left;line-height:12pt;background-color:#f4f4f4;margin:20px 0px 10px;width:97.5%;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;max-height:200px;font-size:8pt;overflow:auto;cursor:text;border:silver 1px solid;padding:4px;"&gt;
&lt;pre id="codeSnippet" style="text-align:left;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;padding:0px;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;caliburn:CaliburnApplication&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;x:Class&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;CaliburnDemo.App&amp;quot;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color:#ff0000;"&gt;xmlns&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&amp;quot;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color:#ff0000;"&gt;xmlns:x&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml&amp;quot;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color:#ff0000;"&gt;xmlns:caliburn&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;clr-namespace:Caliburn.PresentationFramework.ApplicationModel;assembly=Caliburn.PresentationFramework&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Application.Resources&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Application.Resources&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;caliburn:CaliburnApplication&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;No hay secreto: Declaro el namespace &lt;em&gt;caliburn&lt;/em&gt; y modifico el tag raiz para que en lugar de Application sea CaliburnApplication que es nuestra nueva clase base. Tambi&amp;eacute;n elimino el StartupUri ya que no es necesario.&lt;/p&gt;
&lt;p&gt;Y listos&amp;hellip; ya podemos ejecutar!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. Plaf! La primera en la frente!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Si has seguido mis indicaciones te vas a encontrar algo parecido a esto (si no has compilado Caliburn quiz&amp;aacute; simplemente te salga una excepci&amp;oacute;n en lugar de esta &amp;ldquo;preciosa&amp;rdquo; ventana).&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/etomas/image_5F00_46BB08FA.png"&gt;&lt;img height="149" width="345" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/etomas/image_5F00_thumb_5F00_761951F9.png" alt="image" border="0" title="image" style="border-bottom:0px;border-left:0px;display:inline;border-top:0px;border-right:0px;" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Hombre&amp;hellip; no es muy bonito que digamos&amp;hellip; cual es el problema? F&amp;aacute;cil: la vista no est&amp;aacute; situada en el lugar que toca&amp;hellip; Record&amp;aacute;is que os dije que la pusierais &lt;em&gt;&lt;strong&gt;fuera&lt;/strong&gt; &lt;/em&gt;de la carpeta ViewModel? Pues debe ir dentro&amp;hellip; As&amp;iacute;, que moved UserView &lt;em&gt;dentro&lt;/em&gt; de la carpeta ViewModel y &lt;strong&gt;modificad&lt;/strong&gt; el namespace para que incluya ViewModel:&lt;/p&gt;
&lt;div id="codeSnippetWrapper" style="text-align:left;line-height:12pt;background-color:#f4f4f4;margin:20px 0px 10px;width:97.5%;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;max-height:200px;font-size:8pt;overflow:auto;cursor:text;border:silver 1px solid;padding:4px;"&gt;
&lt;pre id="codeSnippet" style="text-align:left;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;padding:0px;"&gt;&lt;span style="color:#0000ff;"&gt;namespace&lt;/span&gt; CaliburnDemo.&lt;strong&gt;&lt;span style="text-decoration:underline;"&gt;ViewModel&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;}&lt;/pre&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;De hecho lo importante es el namespace, no la ubicaci&amp;oacute;n f&amp;iacute;sica del archivo xaml, as&amp;iacute; que si no quereis moverlo no lo hag&amp;aacute;is per el namespace de la clase UserView debe ser el mismo que el de UserViewModel.&lt;/p&gt;
&lt;p&gt;Ahora s&amp;iacute; que s&amp;iacute;! Si ejecutamos vemos una triste ventana&amp;hellip; pero es &lt;em&gt;nuestra&lt;/em&gt; ventana:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/etomas/image_5F00_092A58D9.png"&gt;&lt;img height="244" width="228" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/etomas/image_5F00_thumb_5F00_63C0656A.png" alt="image" border="0" title="image" style="border-bottom:0px;border-left:0px;display:inline;border-top:0px;border-right:0px;" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Est&amp;aacute; vac&amp;iacute;a porque el ViewModel que hemos creado lo est&amp;aacute;, pero eso tiene f&amp;aacute;cil arreglo modificando el m&amp;eacute;todo &lt;em&gt;CreateRootModel&lt;/em&gt; para que el UserViewModel creado tenga datos:&lt;/p&gt;
&lt;div id="codeSnippetWrapper" style="text-align:left;line-height:12pt;background-color:#f4f4f4;margin:20px 0px 10px;width:97.5%;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;max-height:200px;font-size:8pt;overflow:auto;cursor:text;border:silver 1px solid;padding:4px;"&gt;
&lt;pre id="codeSnippet" style="text-align:left;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;padding:0px;"&gt;&lt;span style="color:#0000ff;"&gt;protected&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;override&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;object&lt;/span&gt; CreateRootModel()&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; UserViewModel()&lt;br /&gt;    {&lt;br /&gt;        Nombre = &lt;span style="color:#006080;"&gt;&amp;quot;Edu&amp;quot;&lt;/span&gt;,&lt;br /&gt;        Foto = &lt;span style="color:#006080;"&gt;&amp;quot;/CaliburnDemo;component/avatar.png&amp;quot;&lt;/span&gt;&lt;br /&gt;    };&lt;br /&gt;}&lt;/pre&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;(La foto est&amp;aacute; a&amp;ntilde;adida como Resource en el proyecto, de ah&amp;iacute; esta ruta).&lt;/p&gt;
&lt;p&gt;Ahora si que vemos ya nuestros datos:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/etomas/image_5F00_06A1271B.png"&gt;&lt;img height="167" width="244" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/etomas/image_5F00_thumb_5F00_0C0F97BF.png" alt="image" border="0" title="image" style="border-bottom:0px;border-left:0px;display:inline;border-top:0px;border-right:0px;" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;&amp;iexcl;Mola! Que es lo que ha hecho Caliburn por nosotros? Pues a partir de un ViewModel ha creado la vista correspondiente y ha asignado el ViewModel como DataContext de la vista&amp;hellip; &lt;/p&gt;
&lt;p&gt;Ok&amp;hellip; no es nada que no podamos hacer nosotros mismos con pocas l&amp;iacute;neas de c&amp;oacute;digo&amp;hellip; pero esto es s&amp;oacute;lo el principio! En sucesivos posts iremos viendo otras cosillas de Caliburn. Obviamente si alguien ha trabajado con Caliburn y/o con PRISM y quiere contar sus opiniones&amp;hellip; adelante!&lt;/p&gt;
&lt;p&gt;Un saludo a todos!&lt;/p&gt;
&lt;p&gt;PD: Dejo el &lt;a target="_blank" href="http://cid-6521c259e9b1bec6.skydrive.live.com/self.aspx/BurbujasNet/ZipsPosts/CaliburnDemo1.zip"&gt;c&amp;oacute;digo del proyecto en este ficherillo zip!&lt;/a&gt; (en mi skydrive)&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=167258" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/etomas/archive/tags/wpf/default.aspx">wpf</category><category domain="http://geeks.ms/blogs/etomas/archive/tags/patrones/default.aspx">patrones</category><category domain="http://geeks.ms/blogs/etomas/archive/tags/prism/default.aspx">prism</category><category domain="http://geeks.ms/blogs/etomas/archive/tags/caliburn/default.aspx">caliburn</category></item><item><title>La sencillez de una interfaz compleja</title><link>http://geeks.ms/blogs/etomas/archive/2009/03/12/la-sencillez-de-una-interfaz-compleja.aspx</link><pubDate>Thu, 12 Mar 2009 10:11:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:144749</guid><dc:creator>Eduard Tomàs i Avellana</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/etomas/rsscomments.aspx?PostID=144749</wfw:commentRss><comments>http://geeks.ms/blogs/etomas/archive/2009/03/12/la-sencillez-de-una-interfaz-compleja.aspx#comments</comments><description>&lt;p&gt;Hace alg&amp;uacute;n tiempecillo escrib&amp;iacute; un art&amp;iacute;culo para el e-zine de &lt;a href="http://www.raona.com/"&gt;raona&lt;/a&gt;, que enviamos a distintos clientes. En el art&amp;iacute;culo esbozaba los patrones b&amp;aacute;sicos para dise&amp;ntilde;ar interfaces de usuario compuestas. Posteriormente me surgi&amp;oacute; la idea de que una ampliaci&amp;oacute;n de dicho art&amp;iacute;culo, donde se mostrasen ejemplos en &lt;a href="http://www.codeplex.com/CompositeWPF"&gt;PRISM&lt;/a&gt; y WPF de estos conceptos podr&amp;iacute;a ser interesante. Afortunadamente en &lt;a href="http://www.dotnetmania.com/"&gt;DotNetMania&lt;/a&gt; pensaron lo mismo y es por ello que en la revista de este marzo hay un art&amp;iacute;culo con este mismo t&amp;iacute;tulo.&lt;/p&gt;
&lt;p&gt;Lo que ahora sigue &amp;eacute;s el &lt;strong&gt;&lt;span style="text-decoration:underline;"&gt;art&amp;iacute;culo original&lt;/span&gt;&lt;/strong&gt;, el que escrib&amp;iacute; para el e-zine. Aunque el de DotNetMania describe las mismas ideas, ambos art&amp;iacute;culos tienen poco a ver (tanto en contenido, como en enfoque como en extensi&amp;oacute;n). Como creo que el art&amp;iacute;culo del e-zine tambi&amp;eacute;m tiene su inter&amp;eacute;s, me he tomado la libertad de postearlo aqu&amp;iacute; :)&lt;/p&gt;
&lt;p&gt;PD: Por si os interesa, los distintos e-zines que vamos sacando en raona, los podeis consultar en la &lt;a href="http://www.raona.com/Not&amp;iacute;cies/ezine/tabid/110/Default.aspx"&gt;secci&amp;oacute;n de ezines de raona&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;La sencillez de una interfaz compleja (versi&amp;oacute;n e-zine).&lt;/h3&gt;
&lt;p&gt;Cada vez las aplicaciones son m&amp;aacute;s y m&amp;aacute;s complejas, y los usuarios son m&amp;aacute;s y m&amp;aacute;s exigentes. Los desarrolladores debemos afrontar este doble reto siendo capaces de proporcionar mejores y m&amp;aacute;s complejas aplicaciones, en cada vez menos tiempo. Evidentemente este es un proceso global, que afecta a todo el desarrollo de una soluci&amp;oacute;n de software, pero me gustar&amp;iacute;a centrarme en los retos concretos que esto implica cuando hablamos de interfaces de usuario. No en vano, la interfaz de usuario es el punto de conexi&amp;oacute;n entre el usuario y la aplicaci&amp;oacute;n. Es un elemento cr&amp;iacute;tico y de su implementaci&amp;oacute;n depende en buena medida el &amp;eacute;xito final de toda la aplicaci&amp;oacute;n.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Interfaces complejas&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Las aplicaciones actuales demandan interfaces de usuario complejas a nivel t&amp;eacute;cnico pero que a la vez sean sencillas de utilizar y de mantener. Que se adapten a cualquier tipo de usuario, que tanto usuarios expertos como inexpertos se sientan a gusto utiliz&amp;aacute;ndola. En resumen que la experiencia del usuario al utilizar la interfaz sea plena y que nuestra aplicaci&amp;oacute;n sea usable por cualquier usuario.&lt;/p&gt;
&lt;p&gt;El t&amp;eacute;rmino &lt;i&gt;interfaz compleja&lt;/i&gt;, no quiere referirse al aspecto visual o usable si no al hecho de que cada vez es m&amp;aacute;s complejo y dif&amp;iacute;cil realizar interfaces que permitan conjugar las crecientes posibilidades de la aplicaci&amp;oacute;n con la sencillez de uso y la usabilidad. Este es el reto que debemos solucionar.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Nuevas tecnolog&amp;iacute;as, nuevas posibilidades&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Con la aparici&amp;oacute;n de WPF, Microsoft ha dotado a los desarrolladores de un mont&amp;oacute;n de nuevas posibilidades para la construcci&amp;oacute;n de interfaces. El hecho de disponer de un lenguaje declarativo (XAML) para definir las interfaces permite la separaci&amp;oacute;n entre dos roles b&amp;aacute;sicos hoy en d&amp;iacute;a: los dise&amp;ntilde;adores y los desarrolladores. Pero separar desarrolladores y dise&amp;ntilde;adores es s&amp;oacute;lo un primer paso (un primer gran paso) pero no soluciona la problem&amp;aacute;tica de fondo: el modo en c&amp;oacute;mo est&amp;aacute;n dise&amp;ntilde;adas y desarrolladas las interfaces de usuario.&lt;/p&gt;
&lt;p&gt;El mecanismo habitual de desarrollar interfaces de usuario en .NET, viene influenciado de los tiempos de Visual Basic. Es un patr&amp;oacute;n que consiste en una clase contenedora (llamada com&amp;uacute;nmente formulario) que contiene a los controles y toda la l&amp;oacute;gica asociada a dichos controles. Por norma general el formulario se suscribe a los eventos de los controles a los que contiene y realiza la l&amp;oacute;gica apropiada en las funciones gestoras de dichos eventos. La ventaja de este modelo de programaci&amp;oacute;n es que es sencillo, intuitivo y f&amp;aacute;cil de aprender. Las desventajas son que al tener unidas la l&amp;oacute;gica con la presentaci&amp;oacute;n se vuelve m&amp;aacute;s complejo el mantenimiento tendiendo a &lt;i&gt;colapsar&lt;/i&gt; en grandes proyectos y se dificulta la separaci&amp;oacute;n del desarrollo entre varios equipos.&lt;/p&gt;
&lt;p&gt;Una de las claves para desarrollar interfaces de usuario complejas y que resulten mantenibles es desacoplar la presentaci&amp;oacute;n de la l&amp;oacute;gica de dicha presentaci&amp;oacute;n. WPF presenta algunas novedades que ayudan a conseguir dicho desacople:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Commands: Permite desacoplar los eventos de los controles de la gesti&amp;oacute;n de dichos eventos y unificar en un mismo punto la gesti&amp;oacute;n de distintos eventos de distintos controles pero que realizan la misma acci&amp;oacute;n (p.ej. un bot&amp;oacute;n de una toolbar y una entrada de men&amp;uacute;). &lt;/li&gt;
&lt;li&gt;Routed Events: Permiten tratar en un solo contenedor cualquier evento generado por cualquier de los controles &amp;ldquo;hijos&amp;rdquo; (est&amp;eacute;n en el nivel de profundidad que est&amp;eacute;n). &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Estas novedades aunque interesantes, por si solas no son suficientes para desacoplar totalmente la presentaci&amp;oacute;n y su l&amp;oacute;gica. Para ello hace falta un cambio de paradigma, un nuevo modelo.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Composite Application Library&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Composite Application Library (CAL) tambi&amp;eacute;n conocida por su nombre en c&amp;oacute;digo PRISM, es un framework lanzado por la gente de &amp;ldquo;Patterns &amp;amp; Practices&amp;rdquo; para ayudar en la construcci&amp;oacute;n de aplicaciones complejas utilizando WPF.&lt;/p&gt;
&lt;p&gt;CAL se basa en varios patrones para ayudar a conseguir un desacople total entre la presentaci&amp;oacute;n y la l&amp;oacute;gica de presentaci&amp;oacute;n. A continuaci&amp;oacute;n comentaremos tres de los patrones m&amp;aacute;s relevantes de CAL.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Inversion of Control (IoC)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Este patron desacopla una clase en concreto de otra clase de las clases que utiliza, es decir de sus referencias:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/etomas/clip_5F00_image002_5F00_5C4307ED.jpg"&gt;&lt;img border="0" width="244" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/etomas/clip_5F00_image002_5F00_thumb_5F00_02A77BEA.jpg" alt="Dependencias entre clsases" height="181" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" title="Dependencias entre clsases" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;La clase ClassA utiliza dos servicios (ServiceA y ServiceB) y por lo tanto tiene referencias directas a ellos. Esto implica, entre otras cosas, que si queremos modificar las referencias debemos modificar el c&amp;oacute;digo fuente de ClassA. Para desacoplar la clase de sus referencias la soluci&amp;oacute;n es a&amp;ntilde;adir un componente externo que se encargue de encontrar y gestionar las referencias de la clase ClassA. En funci&amp;oacute;n de c&amp;oacute;mo dise&amp;ntilde;emos este elemento externo hablaremos de un patr&amp;oacute;n &lt;i&gt;ServiceLocator&lt;/i&gt; o de &lt;i&gt;Dependency Injection&lt;/i&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/etomas/clip_5F00_image0024_5F00_2B45E7F1.jpg"&gt;&lt;img border="0" width="491" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/etomas/clip_5F00_image0024_5F00_thumb_5F00_68D5D66B.jpg" alt="Service locator &amp;amp;  Dependency Injection" height="174" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" title="Service locator &amp;amp;  Dependency Injection" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Con ServiceLocator la clase ClassA s&amp;oacute;lo contiene una referencia al &lt;i&gt;Locator&lt;/i&gt; siendo esta clase la que obtiene y devuelve la referencia adecuada a la clase. El &lt;i&gt;Locator&lt;/i&gt; NO instancia los servicios, simplemente los localiza (los servicios han estado instanciados previamente por alguien): mientras un servicio est&amp;eacute; registrado, el &lt;i&gt;Locator&lt;/i&gt; lo encontrar&amp;aacute;. CAL utiliza Unity para ofrecer un Service Locator, lo que nos permite instanciar y registrar servicios que luego ser&amp;aacute;n utilizados en cualquier parte de la aplicaci&amp;oacute;n.&lt;/p&gt;
&lt;p&gt;Con Dependency Injection, existe un &lt;i&gt;Builder&lt;/i&gt; que crea el objeto del servicio y lo &amp;ldquo;incrusta&amp;rdquo; en alguna propiedad espec&amp;iacute;fica de la clase ClassA (o bien en alg&amp;uacute;n par&amp;aacute;metro del constructor). CAL utiliza Unity para proporcionar Dependency Injection.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Separated Presentation&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Si IoC nos permite desacoplar nuestras clases de las referencias que necesitan, el conjunto de patrones conocidos como &amp;ldquo;separated presentation&amp;rdquo;, nos permiten separar la presentaci&amp;oacute;n de la parte de la l&amp;oacute;gica que gestiona la presentaci&amp;oacute;n.&lt;/p&gt;
&lt;p&gt;Existen varios patrones que implementan &amp;ldquo;separated presentation&amp;rdquo; siendo los m&amp;aacute;s concidos MVP (Model &amp;ndash; View &amp;ndash; Presenter) o MVVM (Model &amp;ndash; View- ViewModel). Debido a las capacidades de WPF se tiende a utilizar m&amp;aacute;s MVVM (mientras que MVP es m&amp;aacute;s frecuente en aplicaciones Windows forms p.ej), debido a que MVVM se basa en uno de los aspectos m&amp;aacute;s potentes de WPF: su data binding.&lt;/p&gt;
&lt;p&gt;El patr&amp;oacute;n MVVM se basa en tres elementos:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Vista (View): Contiene los elementos visuales (controles). En el caso de WPF suele estar creada por un dise&amp;ntilde;ador e implementada v&amp;iacute;a XAML &lt;/li&gt;
&lt;li&gt;Modelo (Model): Contiene los datos que muestra la vista. En este punto es cuando se utiliza b&amp;aacute;sicamente el data binding, para enlazar los valores de los controles de la vista a valores de distintos elementos del modelo. &lt;/li&gt;
&lt;li&gt;Modelo de Vista (ViewModel): En interfaces sencillas, la vista se puede enlazar directamente con el modelo, pero en interfaces complejas no suele ser posible. En muchos casos el Modelo puede tener multitud de informaci&amp;oacute;n que no se puede mapear a valores de los controles o bien nuestra vista debe realizar y mantener valores &amp;ldquo;temporales&amp;rdquo; que no forman parte estricta del modelo. Es en estos casos donde entra en escena el &amp;ldquo;ViewModel&amp;rdquo;, actuando de &lt;i&gt;puente&lt;/i&gt; proporcionando transformadores para poder enlazar los controles de la vista y commands para que la vista pueda interactuar con el modelo. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;De esta manera no existe m&amp;aacute;s una clase &amp;ldquo;formulario&amp;rdquo; que contiene los controles y toda la l&amp;oacute;gica asociada a ellos.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Event Aggregator&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Un &lt;i&gt;Event Aggregator&lt;/i&gt; es la implementaci&amp;oacute;n de un modelo de eventos publish and subscribe, donde cuando alquien quiere recibir un evento se &lt;i&gt;suscribe&lt;/i&gt; a este tipo de evento en particular. Cuando alguien quiere enviar un evento lo &lt;i&gt;publica&lt;/i&gt; y el &lt;i&gt;event aggregator&lt;/i&gt; se ocupa de que todos los que se hayan suscrito a este tipo de evento lo reciban. De esta manera se desacoplan totalmente los publicadores de eventos de sus suscriptores.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Conclusiones&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Para desarrollar interfaces complejas que a la vez sean amigables para el usuario y mantenibles para el desarrollador es necesario involucrar a los dise&amp;ntilde;adores por un lado y desacoplar la presentaci&amp;oacute;n de la l&amp;oacute;gica que la gestiona por otro. Gracias a XAML, WPF permite que los dise&amp;ntilde;adores se integren totalmente en el ciclo de desarrollo, y el uso de determinados patrones permite desacoplar los distintos elementos que conforman la inferfaz de usuario. CAL es un framework y una gu&amp;iacute;a de estilo que bas&amp;aacute;ndose en dichos patrones y en las funcionalidades inherentes a WPF nos permite desarrollar aplicaciones complejas que sean mantenibles y amigables a la vez.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Referencias&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Command pattern in WPF (&lt;a href="http://www.microsoft.com/belux/msdn/nl/community/columns/jdruyts/wpf_commandpattern.mspx"&gt;http://www.microsoft.com/belux/msdn/nl/community/columns/jdruyts/wpf_commandpattern.mspx&lt;/a&gt;) &lt;/li&gt;
&lt;li&gt;Routed Events overview (&lt;a href="http://msdn.microsoft.com/en-us/library/ms742806.aspx"&gt;http://msdn.microsoft.com/en-us/library/ms742806.aspx&lt;/a&gt;) &lt;/li&gt;
&lt;li&gt;Model &amp;ndash; View &amp;ndash; Presenter pattern (&lt;a href="http://msdn.microsoft.com/en-us/magazine/cc188690.aspx"&gt;http://msdn.microsoft.com/en-us/magazine/cc188690.aspx&lt;/a&gt;) &lt;/li&gt;
&lt;li&gt;Model &amp;ndash; View &amp;ndash; ViewModel pattern (&lt;a href="http://blogs.msdn.com/johngossman/archive/2005/10/08/478683.aspx"&gt;http://blogs.msdn.com/johngossman/archive/2005/10/08/478683.aspx&lt;/a&gt;) &lt;/li&gt;
&lt;li&gt;Inversion of Control (&lt;a href="http://msdn.microsoft.com/en-us/library/cc707904.aspx"&gt;http://msdn.microsoft.com/en-us/library/cc707904.aspx&lt;/a&gt;) &lt;/li&gt;
&lt;li&gt;Service Locator Pattern (&lt;a href="http://msdn.microsoft.com/en-us/library/cc707905.aspx"&gt;http://msdn.microsoft.com/en-us/library/cc707905.aspx&lt;/a&gt;) &lt;/li&gt;
&lt;li&gt;Dependency Injection (&lt;a href="http://msdn.microsoft.com/en-us/library/cc707845.aspx"&gt;http://msdn.microsoft.com/en-us/library/cc707845.aspx&lt;/a&gt;) &lt;/li&gt;
&lt;li&gt;Dependency Injection on Martin Fowler&amp;rsquo;s site (&lt;a href="http://www.martinfowler.com/articles/injection.html"&gt;http://www.martinfowler.com/articles/injection.html&lt;/a&gt;) &lt;/li&gt;
&lt;li&gt;Event Aggregator (&lt;a href="http://martinfowler.com/eaaDev/EventAggregator.html"&gt;http://martinfowler.com/eaaDev/EventAggregator.html&lt;/a&gt;) &lt;/li&gt;
&lt;li&gt;Event Aggregator (&lt;a href="http://msdn.microsoft.com/en-us/library/cc707867.aspx"&gt;http://msdn.microsoft.com/en-us/library/cc707867.aspx&lt;/a&gt;) &lt;/li&gt;
&lt;/ul&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=144749" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/etomas/archive/tags/patrones/default.aspx">patrones</category><category domain="http://geeks.ms/blogs/etomas/archive/tags/IoC/default.aspx">IoC</category><category domain="http://geeks.ms/blogs/etomas/archive/tags/opinion/default.aspx">opinion</category><category domain="http://geeks.ms/blogs/etomas/archive/tags/prism/default.aspx">prism</category></item></channel></rss>