<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="https://www.w3.org/2005/Atom" xmlns:sy="https://purl.org/rss/1.0/modules/syndication/" xmlns:dc="https://purl.org/dc/elements/1.1/" xmlns:content="https://purl.org/rss/1.0/modules/content/" xmlns:wfw="https://wellformedweb.org/CommentAPI/" xmlns:slash="https://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Ryan Tremblay's Blog</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/ryantrem/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/ryantrem/feed.xml</link>
    <description />
    <lastBuildDate>Tue, 16 Apr 2019 05:28:51 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Simplifying hierarchical ViewModels with collection transforms</title>
      <link>https://docs.microsoft.com/archive/blogs/ryantrem/simplifying-hierarchical-viewmodels-with-collection-transforms</link>
      <pubDate>Sat, 28 Aug 2010 16:46:00 GMT</pubDate>
      <dc:creator><![CDATA[ryantrem]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/ryantrem/2010/08/28/simplifying-hierarchical-viewmodels-with-collection-transforms/</guid>
      <description><![CDATA[Under the Model-View-ViewModel (MVVM) design pattern, the ViewModel typically provides a...]]></description>
      <content:encoded><![CDATA[<p>Under the Model-View-ViewModel (MVVM) design pattern, the ViewModel typically provides a programmatic interface to backend state (the Model) and state changes to which the View can easily be bound, effectively separating the view logic from the actual presentation. With its powerful data binding system and the declarative presentation markup made possible by Xaml, MVVM is particularly useful when developing with WPF. In such a scenario, the ViewModel typically exposes the Model (a data model, a service, etc.) state through CLR properties and state changes through the PropertyChanged event of INotifyPropertyChanged.&nbsp; State is affected via ICommands also exposed by CLR properties on the ViewModel. Creating such a ViewModel for a Model with a simple structure is usually rather straight forward. However, without some careful planning, creating a ViewModel for a Model that is hierarchical in nature can become relatively complex. Issues such as maintaining consistency between the Model&rsquo;s structure and the ViewModel&rsquo;s structure in the midst of changes being made to both the Model and the ViewModel quickly arise.</p>
<p>Fortunately, various approaches exist to help mitigate this complexity in different situations. Often, the Model&rsquo;s hierarchical structure is formed by Model elements having collections of child Model elements. For example, an address book might have a collection of contacts, which in turn have collections of addresses and phone numbers. In the approach I describe here, the complexity of such a hierarchical Model is managed through collection transforms. A collection transform &ldquo;transforms&rdquo; a source collection into a readonly target collection and keeps itself up-to-date based on collection change notifications from the source collection. In a sense, this is similar to the Select extension method provided by Linq, except that future changes to the source collection are reflected in the target (transformed) collection. When this approach is applied to hierarchical ViewModels, the individual ViewModel elements (the address book, the individual contacts, and the individual addresses) can be changed through the ViewModel, but the overall structure of the ViewModel hierarchy can only be affected by the structure of the Model hierarchy. In practice, this is both functional and simple to implement.</p>
<p>The first thing needed is the TransformedCollection class. This is a readonly collection that supports change notifications:</p>
<table border="1">
<tbody>
<tr>
<td><span style="line-height: 115%; font-family: Consolas; color: blue; font-size: 9.5pt; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA;">public</span><span style="line-height: 115%; font-family: Consolas; font-size: 9.5pt; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA;"> <span style="color: blue;">class</span> <strong><span style="color: navy;">TransformedCollection</span></strong>&lt;TSource, TTarget&gt; : <strong><span style="color: navy;">ReadOnlyCollection</span></strong>&lt;TTarget&gt;, <span style="color: #2b91af;">INotifyCollectionChanged</span>, <span style="color: #2b91af;">IDisposable<br /></span>{<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">public</span> TransformedCollection(<span style="color: #2b91af;">IEnumerable</span>&lt;TSource&gt; sourceCollection, <span style="color: #2b91af;">Func</span>&lt;TSource, TTarget&gt; setup, <span style="color: #2b91af;">Action</span>&lt;TTarget&gt; teardown = <span style="color: blue;">null</span>)<br />&nbsp;&nbsp;&nbsp; ...<br />}</span></td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>This is a generic, ReadOnlyCollection with type parameters for the type of element in the source collection (the Model in our case) and the type of element in the target collection (the ViewModel in our case). The constructor takes the source collection, a delegate that transforms a source element into a target element, and an optional delegate that cleans up target elements when they are removed (such as disposing them, if necessary). The sample code has the full implementation.</p>
<p>The simplest way to use this class is to use it directly (do not subclass it). This scenario can further be simplified with an extension method:</p>
<table border="1">
<tbody>
<tr>
<td>
<p><span style="line-height: 115%; font-family: Consolas; color: blue; font-size: 9.5pt; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA;">public</span><span style="line-height: 115%; font-family: Consolas; font-size: 9.5pt; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA;"> <span style="color: blue;">static</span> <strong><span style="color: navy;">TransformedCollection</span></strong>&lt;TSource, TTarget&gt; Transform&lt;TSource, TTarget&gt;(<span style="color: blue;">this</span> <span style="color: #2b91af;">IEnumerable</span>&lt;TSource&gt; sourceCollection, <span style="color: #2b91af;">Func</span>&lt;TSource, TTarget&gt; setup, <span style="color: #2b91af;">Action</span>&lt;TTarget&gt; teardown = <span style="color: blue;">null</span>)<br />{<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">return</span> <span style="color: blue;">new</span> <strong><span style="color: navy;">TransformedCollection</span></strong>&lt;TSource, TTarget&gt;(sourceCollection, setup, teardown);<br />}</span></p>
</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>Using the TransformedCollection directly works well when the ViewModel classes do not have corresponding interfaces. For example, consider the following (simplified) data model:</p>
<table border="1">
<tbody>
<tr>
<td>
<p><span style="line-height: 115%; font-family: Consolas; color: blue; font-size: 9.5pt; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA;">public</span><span style="line-height: 115%; font-family: Consolas; font-size: 9.5pt; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA;"> <span style="color: blue;">class</span> <strong><span style="color: navy;">AddressBook<br /></span></strong>{<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">private</span> <span style="color: blue;">readonly</span> <strong><span style="color: navy;">ObservableCollection</span></strong>&lt;<strong><span style="color: navy;">Contact</span></strong>&gt; contacts;<br /><br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">public</span> AddressBook()<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span>{<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">this</span>.contacts = <span style="color: blue;">new</span> <strong><span style="color: navy;">ObservableCollection</span></strong>&lt;<strong><span style="color: navy;">Contact</span></strong>&gt;();<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span>}<br /><br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">public</span> <strong><span style="color: navy;">ObservableCollection</span></strong>&lt;<strong><span style="color: navy;">Contact</span></strong>&gt; Contacts<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span>{<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">get</span><br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">return</span> <span style="color: blue;">this</span>.contacts;<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span>}<br />}</span>&nbsp;</p>
</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>A corresponding ViewModel might look like:</p>
<table border="1">
<tbody>
<tr>
<td>
<p><span style="line-height: 115%; font-family: Consolas; color: blue; font-size: 9.5pt; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA;">public</span><span style="line-height: 115%; font-family: Consolas; font-size: 9.5pt; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA;"> <span style="color: blue;">class</span> <strong><span style="color: navy;">AddressBookViewModel</span></strong><br />{<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">private</span> <span style="color: blue;">readonly</span> <strong><span style="color: navy;">TransformedCollection</span></strong>&lt;<strong><span style="color: navy;">Contact</span></strong>, <strong><span style="color: navy;">ContactViewModel</span></strong>&gt; contactViewModels;<br /><br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">public</span> AddressBookViewModel(<strong><span style="color: navy;">AddressBook</span></strong> addressBook)<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span>{<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">this</span>.contactViewModels = addressBook.Contacts.Transform(<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>contact =&gt; <span style="color: blue;">new</span> <strong><span style="color: navy;">ContactViewModel</span></strong>(contact)),<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>contactViewModel =&gt; contactViewModel.Dispose());<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span>}<br /><br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">public</span> <strong><span style="color: navy;">TransformedCollection</span></strong>&lt;<strong><span style="color: navy;">Contact</span></strong>, <strong><span style="color: navy;">ContactViewModel</span></strong>&gt; ContactViewModels<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span>{<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">get</span><br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">return</span> <span style="color: blue;">this</span>.contactViewModels;<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span>}<br />}</span></p>
</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>If the ViewModel classes have corresponding interfaces, the situation is slightly more complex, but certainly manageable:</p>
<table border="1">
<tbody>
<tr>
<td>
<p><span style="line-height: 115%; font-family: Consolas; color: blue; font-size: 9.5pt; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA;">public</span><span style="line-height: 115%; font-family: Consolas; font-size: 9.5pt; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA;"> <span style="color: blue;">interface</span> <span style="color: #2b91af;">IContactViewModelCollection</span> : <span style="color: #2b91af;">IEnumerable</span>&lt;<span style="color: #2b91af;">IContactViewModel</span>&gt;, <span style="color: #2b91af;">INotifyCollectionChanged</span> { }<br /><br /><span style="color: blue;">public</span> <span style="color: blue;">interface</span> <span style="color: #2b91af;">IAddressBookViewModel</span><br />{<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span><span style="color: #2b91af;">IContactViewModelCollection</span> ContactViewModels { <span style="color: blue;">get</span>; }<br />}<br /><br /><span style="color: blue;">public</span> <span style="color: blue;">class</span> <strong><span style="color: navy;">AddressBookViewModel</span></strong> : <span style="color: #2b91af;">IAddressBookViewModel</span><br />{<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">private</span> <span style="color: blue;">readonly</span> <strong><span style="color: navy;">ContactViewModelCollection</span></strong> contactViewModels;<span style="color: blue;"><br /></span><br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">public</span> AddressBookViewModel(<strong><span style="color: navy;">AddressBook</span></strong> addressBook)<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span>{<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">this</span>.contactViewModels = <span style="color: blue;">new</span> <strong><span style="color: navy;">ContactViewModelCollection</span></strong>(addressBook.Contacts);<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span>}<br /><br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">public</span> <span style="color: #2b91af;">IContactViewModelCollection</span> ContactViewModels<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span>{<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">get</span><br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">return</span> <span style="color: blue;">this</span>.contactViewModels;<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span>}<br /><br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">private</span> <span style="color: blue;">class</span> <strong><span style="color: navy;">ContactViewModelCollection</span></strong> : <strong><span style="color: navy;">TransformedCollection</span></strong>&lt;<strong><span style="color: navy;">Contact</span></strong>, <strong><span style="color: navy;">ContactViewModel</span></strong>&gt;, <span style="color: #2b91af;">IContactViewModelCollection</span><br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span>{<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">public</span> ContactViewModelCollection(<span style="color: #2b91af;">IEnumerable</span>&lt;<strong><span style="color: navy;">Contact</span></strong>&gt; contacts) : <span style="color: blue;">base</span>(<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>contacts,<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>contact =&gt; <span style="color: blue;">new</span> <strong><span style="color: navy;">ContactViewModel</span></strong>(contact),<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>contactViewModel =&gt; contactViewModel.Dispose())<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}<br /><br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #2b91af;">IEnumerator</span>&lt;<span style="color: #2b91af;">IContactViewModel</span>&gt; <span style="color: #2b91af;">IEnumerable</span>&lt;<span style="color: #2b91af;">IContactViewModel</span>&gt;.GetEnumerator()<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">return</span> <span style="color: blue;">this</span>.GetEnumerator();<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span>}<br />}</span></p>
</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>In both cases above, the ViewModel should dispose the TransformedCollection instance at some point, but I omitted this for clarity. The sample code properly disposes the TransformedCollections.</p>
<p>The fact that the TransformedCollection is readonly may seem like a limitation that would be difficult to work with, but in practice I&rsquo;ve found it to reduce complexity at a negligible cost. Since the ViewModel references to the Model, it&rsquo;s easy enough for the ViewModel to expose commands that affect the underlying Model which is in turn reflected in the ViewModel. For example, an AddContactCommand exposed by the AddressBookViewModel can add a Contact to the underlying AddressBook, which is then reflected in the AddressBookViewModel&rsquo;s ContactViewModelCollection. Again, this is demonstrated in the <a href="https://cid-75984f86a9f4ee72.office.live.com/self.aspx/MSDN%20Blog/TransformedCollectionSample.zip" target="_blank">sample code</a>. As always, feedback is welcome.</p>]]></content:encoded>
    </item>
    <item>
      <title>PowerShell scripting in MEF-based applications</title>
      <link>https://docs.microsoft.com/archive/blogs/ryantrem/powershell-scripting-in-mef-based-applications</link>
      <pubDate>Sat, 24 Jul 2010 21:27:00 GMT</pubDate>
      <dc:creator><![CDATA[ryantrem]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/ryantrem/2010/07/24/powershell-scripting-in-mef-based-applications/</guid>
      <description><![CDATA[In my last post, I gave an overview of an approach to making MEF-based applications scriptable....]]></description>
      <content:encoded><![CDATA[<p>In my <a href="https://blogs.msdn.com/b/ryantrem/archive/2010/07/16/python-scripting-in-mef-based-applications.aspx">last post</a>, I gave an overview of an approach to making MEF-based applications scriptable. While there are many .NET compatible scripting languages available these days, I used Iron Python in my last post since hosting it is so simple. This post builds upon the last (so read that one first), but uses PowerShell as the scripting language.</p>
<p>Hosting PowerShell is a bit more complex than hosting Iron Python, primarily due to PowerShell&rsquo;s lack of support for .NET generics and MEF&rsquo;s lack of non-generic methods on the CompositionContainer class (particularly GetExportedValue). We can overcome this by taking advantage of PowerShell&rsquo;s Extended Type System (ETS). The first thing needed though is some extension methods for CompositionContainer that provide non-generic versions of GetExportedValue and GetExportedValues:</p>
<table border="1">
<tbody>
<tr>
<td><span style="line-height: 115%; font-family: Consolas; color: blue; font-size: 9.5pt; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA;">public</span><span style="line-height: 115%; font-family: Consolas; font-size: 9.5pt; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA;"> <span style="color: blue;">static</span> <span style="color: blue;">object</span> GetExportedValue(<span style="color: blue;">this</span> <b><span style="color: navy;">CompositionContainer</span></b> compositionContainer, <b><span style="color: navy;">Type</span></b> type = <span style="color: blue;">null</span>, <span style="color: blue;">string</span> contractName = <span style="color: blue;">null</span>)<br />{<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">return</span> compositionContainer.GetExports(<b><span style="color: navy;">CompositionContainerExtensions</span></b>.GetImportDefinition(type, contractName, <span style="color: olive;">ImportCardinality</span>.ExactlyOne)).Single().Value;<br />}<br /><br /><span style="color: blue;">public</span> <span style="color: blue;">static</span> <span style="color: #2b91af;">IEnumerable</span>&lt;<span style="color: blue;">object</span>&gt; GetExportedValues(<span style="color: blue;">this</span> <b><span style="color: navy;">CompositionContainer</span></b> compositionContainer, <b><span style="color: navy;">Type</span></b> type = <span style="color: blue;">null</span>, <span style="color: blue;">string</span> contractName = <span style="color: blue;">null</span>)<br />{<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">return</span> compositionContainer.GetExports(<b><span style="color: navy;">CompositionContainerExtensions</span></b>.GetImportDefinition(type, contractName, <span style="color: olive;">ImportCardinality</span>.ZeroOrMore)).Select(export =&gt; export.Value);<br />}<br /><br /><span style="color: blue;">private</span> <span style="color: blue;">static</span> <b><span style="color: navy;">ImportDefinition</span></b> GetImportDefinition(<b><span style="color: navy;">Type</span></b> type, <span style="color: blue;">string</span> contractName, <span style="color: olive;">ImportCardinality</span> cardinality)<br />{<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">if</span> (<span style="color: blue;">string</span>.IsNullOrEmpty(contractName))<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span>{<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>contractName = <b><span style="color: navy;">AttributedModelServices</span></b>.GetContractName(type);<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span>}<br /><br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">string</span> typeIdentity = <span style="color: blue;">null</span>;<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">if</span> (type != <span style="color: blue;">null</span>)<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span>{<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>typeIdentity = <b><span style="color: navy;">AttributedModelServices</span></b>.GetTypeIdentity(type);<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span>}<br /><br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">return</span> <span style="color: blue;">new</span> <b><span style="color: navy;">ContractBasedImportDefinition</span></b>(contractName, typeIdentity, <span style="color: blue;">null</span>, cardinality, <span style="color: blue;">false</span>, <span style="color: blue;">true</span>, <span style="color: olive;">CreationPolicy</span>.Any);<br />}</span></td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>Next, we&rsquo;ll need an extension method to make it easier to get the underlying .NET object wrapped by PowerShell&rsquo;s PSObjects:</p>
<table border="1">
<tbody>
<tr>
<td><span style="line-height: 115%; font-family: Consolas; color: blue; font-size: 9.5pt; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA;">public</span><span style="line-height: 115%; font-family: Consolas; font-size: 9.5pt; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA;"> <span style="color: blue;">static</span> T Cast&lt;T&gt;(<span style="color: blue;">this</span> <b><span style="color: navy;">PSObject</span></b> psObject)<br />{<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">if</span> (psObject == <span style="color: blue;">null</span>)<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span>{<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">return</span> <span style="color: blue;">default</span>(T);<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span>}<br /><br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">if</span> (psObject.BaseObject <span style="color: blue;">is</span> T)<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span>{<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">return</span> (T)psObject.BaseObject;<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span>}<br /><br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">throw</span> <span style="color: blue;">new</span> <b><span style="color: navy;">InvalidOperationException</span></b>(<span style="color: blue;">string</span>.Format(<span style="color: #a31515;">"Cannot convert {0} to {1}."</span>, psObject, <span style="color: blue;">typeof</span>(T).FullName));<br />}</span></td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>The PowerShell scripting service takes advantage of the above extension methods and the PowerShell ETS:</p>
<table border="1">
<tbody>
<tr>
<td><span style="line-height: 115%; font-family: Consolas; font-size: 9.5pt; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA;">[<b><span style="color: navy;">Export</span></b>(<span style="color: blue;">typeof</span>(<span style="color: #2b91af;">IScriptingService</span>))]<br /><span style="color: blue;">internal</span> <span style="color: blue;">class</span> <b><span style="color: navy;">PowerShellScriptingService</span></b> : <span style="color: #2b91af;">IScriptingService</span><br />{<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span>[<b><span style="color: navy;">Import</span></b>]<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">private</span> <b><span style="color: navy;">CompositionContainer</span></b> container;<br /><br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">public</span> <span style="color: blue;">object</span> RunScript(<span style="color: blue;">string</span> script)<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span>{<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">using</span> (<b><span style="color: navy;">Runspace</span></b> runspace = <b><span style="color: navy;">RunspaceFactory</span></b>.CreateRunspace())<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">var</span> psContainer = <span style="color: blue;">new</span> <b><span style="color: navy;">PSObject</span></b>(<span style="color: blue;">this</span>.container);<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>psContainer.Members.Add(<span style="color: blue;">new</span> <b><span style="color: navy;">PSCodeMethod</span></b>(<span style="color: #a31515;">"GetExportedValue"</span>, <span style="color: blue;">this</span>.GetType().GetMethod(<span style="color: #a31515;">"GetExportedValue"</span>)));<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>psContainer.Members.Add(<span style="color: blue;">new</span> <b><span style="color: navy;">PSCodeMethod</span></b>(<span style="color: #a31515;">"GetExportedValues"</span>, <span style="color: blue;">this</span>.GetType().GetMethod(<span style="color: #a31515;">"GetExportedValues"</span>)));<br /><br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>runspace.ThreadOptions = <span style="color: olive;">PSThreadOptions</span>.UseCurrentThread;<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>runspace.Open();<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>runspace.SessionStateProxy.SetVariable(<span style="color: #a31515;">"container"</span>, psContainer);<br /><br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">using</span> (<b><span style="color: navy;">Pipeline</span></b> pipeline = runspace.CreatePipeline())<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pipeline.Commands.AddScript(script);<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><b><span style="color: navy;">PSObject</span></b> result = pipeline.Invoke().LastOrDefault();<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">return</span> result == <span style="color: blue;">null</span> ? <span style="color: blue;">null</span> : result.BaseObject;<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}<br /><span style="mso-spacerun: yes;">&nbsp;</span><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span>}<br /><br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">public</span> <span style="color: blue;">static</span> <span style="color: blue;">object</span> GetExportedValue(<b><span style="color: navy;">PSObject</span></b> psContainer, <b><span style="color: navy;">PSObject</span></b> psType, <b><span style="color: navy;">PSObject</span></b> psContractName = <span style="color: blue;">null</span>)<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span>{<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">var</span> container = psContainer.Cast&lt;<b><span style="color: navy;">CompositionContainer</span></b>&gt;();<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">var</span> type = psType.Cast&lt;<b><span style="color: navy;">Type</span></b>&gt;();<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">var</span> contractName = psContractName.Cast&lt;<span style="color: blue;">string</span>&gt;();<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">return</span> container.GetExportedValue(type, contractName);<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span>}<br /><br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">public</span> <span style="color: blue;">static</span> <span style="color: blue;">object</span>[] GetExportedValues(<b><span style="color: navy;">PSObject</span></b> psContainer, <b><span style="color: navy;">PSObject</span></b> psType, <b><span style="color: navy;">PSObject</span></b> psContractName = <span style="color: blue;">null</span>)<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span>{<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">var</span> container = psContainer.Cast&lt;<b><span style="color: navy;">CompositionContainer</span></b>&gt;();<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">var</span> type = psType.Cast&lt;<b><span style="color: navy;">Type</span></b>&gt;();<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">var</span> contractName = psContractName.Cast&lt;<span style="color: blue;">string</span>&gt;();<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">return</span> container.GetExportedValues(type, contractName).ToArray();<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span>}<br />}</span></td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>Notice that the CompositionContainer is wrapped in a PSObject. This allows us to use the PowerShell ETS to add non-generic versions of the GetExportedValue and GetExportedValues methods to the CompositionContainer, which are significantly easier to invoke from a PowerShell script. The non-generic GetExportedValue and GetExportedValues implementations use the extension methods we previously defined.</p>
<p>Also notice that the Runspace&rsquo;s ThreadOptions is explicitly set to use the current thread. This is a crucial step. Without this, PowerShell will use a separate thread for the RunSpace (not the UI thread) and therefore scripts will not be able to interact with the UI.</p>
<p>Finally, notice that we capture only the last PSObject from the Pipeline&rsquo;s Invoke method. Invoke returns all objects that are output to the host. Capturing only the last one is analogous to the way the last value output from PowerShell functions (implicitly, or explicitly by using a return statement) is the value returned from the function. Also note that only the underlying .NET object of the PSObject is returned, which is probably desirable to the caller of the RunScript method.</p>
<p>I&rsquo;ve made some <a href="https://cid-75984f86a9f4ee72.office.live.com/self.aspx/MSDN%20Blog/PowerShellScriptingSample.zip">sample code</a> available that demonstrates this approach. The focus is definitely on the PowerShell scripting, so the rest of the application is very simple and rather poorly designed. Using PowerShell's ETS to add non-generic CompositionContainer methods was the cleanest approach I could find. If anyone has an alternative approach, I'd love to hear about it.</p>]]></content:encoded>
    </item>
    <item>
      <title>Python scripting in MEF-based applications</title>
      <link>https://docs.microsoft.com/archive/blogs/ryantrem/python-scripting-in-mef-based-applications</link>
      <pubDate>Thu, 15 Jul 2010 20:14:00 GMT</pubDate>
      <dc:creator><![CDATA[ryantrem]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/ryantrem/2010/07/15/python-scripting-in-mef-based-applications/</guid>
      <description><![CDATA[Extensible applications typically allow developers to extend the application&rsquo;s functionality...]]></description>
      <content:encoded><![CDATA[<p>Extensible applications typically allow developers to extend the application&rsquo;s functionality by implementing new components. Scriptable applications typically allow power users to either extend or automate the application&rsquo;s functionality by writing scripts that can be executed in the context of the application. Examples include Visual Studio, which supports VB Script; 3ds Max, which supports Max Script; Maya, which supports Python; Photoshop, which supports Java Script; etc. Application automation via scripts can provide standard procedures within an application, such as exporting a 3D model with the particular parameters required for a particular game, or can automate a specialized but repetitive task, such as inserting a standard comment header at the top of a code file.</p>
<p>Scriptable applications require careful design that programmatically exposes components of the application to scripts. MEF (Managed Extensibility Framework), introduced in .NET 4.0 (under System.ComponentModel.Composition), promotes such a design. Typically, MEF-based applications are compositions of highly cohesive, loosely coupled components. In the approach I describe here, the entire CompositionContainer is exposed to the scripts, and therefore all components of the application are exposed. Scripts are treated as transient entities and query the CompsoitionContainer directly. These days, there are many .NET compatible scripting languages, but in this post I&rsquo;ll specifically be using Iron Python since hosting it in an application is trivial.</p>
<p>The first thing needed is an interface for components that run scripts:</p>
<p><span style="line-height: 115%; font-family: Consolas; color: blue; font-size: 9.5pt; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA;">public</span><span style="line-height: 115%; font-family: Consolas; font-size: 9.5pt; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA;"> <span style="color: blue;">interface</span> <span style="color: #2b91af;">IScriptingService</span><br />{<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">object</span> RunScript(<span style="color: blue;">string</span> script);<br />}</span></p>
<p>Eventually, some UI in the application might consume this interface to allow the user to run scripts saved on disk, or perhaps would expose an interactive console within the application. Following is an implementation of this interface that supports Python scripting:</p>
<p><span style="line-height: 115%; font-family: Consolas; font-size: 9.5pt; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA;">[<b><span style="color: navy;">Export</span></b>(<span style="color: blue;">typeof</span>(<span style="color: #2b91af;">IScriptingService</span>))]<br /><span style="color: blue;">internal</span> <span style="color: blue;">class</span> <b><span style="color: navy;">PythonScriptingService</span></b> : <span style="color: #2b91af;">IScriptingService</span><br />{<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span>[<b><span style="color: navy;">Import</span></b>]<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">private</span> <b><span style="color: navy;">CompositionContainer</span></b> container;<br /><br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">public</span> <span style="color: blue;">object</span> RunScript(<span style="color: blue;">string</span> script)<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span>{<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><b><span style="color: navy;">ScriptEngine</span></b> pythonEngine = <b><span style="color: navy;">Python</span></b>.CreateEngine();<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><b><span style="color: navy;">ScriptScope</span></b> scriptScope = pythonEngine.CreateScope();<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>scriptScope.SetVariable(<span style="color: #a31515;">"container"</span>, <span style="color: blue;">this</span>.container);<br /><br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><b><span style="color: navy;">ScriptSource</span></b> scriptSource = pythonEngine.CreateScriptSourceFromString(script);<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">return</span> scriptSource.Execute(scriptScope);<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span>}<br />}</span></p>
<p>Notice that the implementation imports the CompositionContainer. For this to work, the CompositionContainer basically needs to export itself. This can be done imperatively as follows:</p>
<p><span style="line-height: 115%; font-family: Consolas; color: blue; font-size: 9.5pt; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA;">var</span><span style="line-height: 115%; font-family: Consolas; font-size: 9.5pt; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA;"> batch = <span style="color: blue;">new</span> <b><span style="color: navy;">CompositionBatch</span></b>();<br />batch.AddExportedValue&lt;<b><span style="color: navy;">CompositionContainer</span></b>&gt;(container);<br />container.Compose(batch);</span></p>
<p>The PythonScriptingService exposes the CompositionContainer to scripts as a variable named container. Scripts can query the container for exports and use them to extend or automate the application&rsquo;s functionality. As a simple example, a Python script might look something like this:</p>
<p><span style="line-height: 115%; font-family: Consolas; color: blue; font-size: 9.5pt; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA;">import</span><span style="line-height: 115%; font-family: Consolas; font-size: 9.5pt; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA;"> clr<br />clr<span style="color: teal;">.</span>AddReference<span style="color: teal;">(</span><span style="color: #a31515;">"SampleApplication"</span><span style="color: teal;">)</span><br /><span style="color: blue;">from</span> SampleApplication <span style="color: blue;">import</span> IStatusService<br />statusService <span style="color: teal;">=</span> <strong>container<span style="color: teal;">.</span>GetExportedValue</strong><span style="color: teal;">[</span>IStatusService<span style="color: teal;">]()</span><br />statusService<span style="color: teal;">.</span>ReportStatus<span style="color: teal;">(</span><span style="color: #a31515;">"Hello from python!"</span><span style="color: teal;">)</span></span></p>
<p>If you have multiple implementations of IScriptingService for different scripting languages, it might make sense to add ExportMetadata to each implementation that describes the scripting language supported by the implementation and perhaps the file extension used for that scripting language. This will of course depend on the specific application implementing and exposing these services.</p>
<p>Also worth noting, it might be possible to use a custom MEF programming model to inject components directly into the scripts as opposed to the scripts relying on direct access to the CompositionContainer. This would certainly be more complex and require more code, but it&rsquo;d be interesting to explore regardless. &nbsp;If anyone has done something like this or has ideas around this, I&rsquo;d love to hear about it!</p>
<p>I&rsquo;ve made some <a target="_blank" href="https://cid-75984f86a9f4ee72.office.live.com/self.aspx/MSDN%20Blog/PythonScriptingSample.zip">sample code</a> available that demonstrates this approach. The focus is definitely on the Iron Python scripting, so the rest of the application is very simple and rather poorly designed. Feedback is welcome.</p>]]></content:encoded>
    </item>
    <item>
      <title>A data-driven MEF bootstrapper</title>
      <link>https://docs.microsoft.com/archive/blogs/ryantrem/a-data-driven-mef-bootstrapper</link>
      <pubDate>Sun, 27 Jun 2010 11:49:00 GMT</pubDate>
      <dc:creator><![CDATA[ryantrem]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/ryantrem/2010/06/27/a-data-driven-mef-bootstrapper/</guid>
      <description><![CDATA[Overview
MEF (Managed Extensibility Framework), introduced in .NET 4.0 (under...]]></description>
      <content:encoded><![CDATA[<p><strong>Overview</strong></p>
<p>MEF (Managed Extensibility Framework), introduced in .NET 4.0 (under System.ComponentModel.Composition), provides a powerful framework for creating extensible applications. Traditionally, extensible applications have a large and often fixed core with specific extension points to allow the application to be extended in very particular ways. While limited extensibility is sometimes preferred, it is often desirable to maximize extensibility. When used to its fullest, MEF allows an application to be almost entirely composed of loosely coupled components. With such a design, core components and extensions become one and the same. In the approach I discuss here, the only remaining fixed aspect of the application is the bootstrapper. The bootstrapper is responsible for the following:</p>
<ol>
<li>Preparing the part catalog (ComposablePartCatalog) and initializing the container (CompositionContainer)</li>
<li>Discovering and executing the pseudo entry points</li>
</ol>
<div>
<p><strong>Preparing the part catalogs</strong></p>
<p>Typical examples of MEF-based applications use an AggregateCatalog that aggregates TypeCatalogs and/or AssemblyCatalogs (which contain the fixed components of the core application) and a DirectoryCatalog (which contains the application&rsquo;s extensions, discovered from assemblies on disk). This strategy is probably sufficient if your goal is to implement a single partially extensible application and not share components between multiple applications. This strategy is probably not sufficient if your goal is to implement multiple fully extensible applications composed of generic shared components and application-specific non-shared components. To satisfy this goal, a more controlled mechanism than DirectoryCatalog is needed for specifying the parts that compose a particular application. TypeCatalog and AssemblyCatalog provide more granular control, but we need a data-driven way of defining these catalogs to satisfy the goal of extensibility.</p>
<p>The approach I take here is to simply encode various catalogs as xaml documents stored on disk next to the application executable(s). This is possible due to improvements in the xaml language and API in .NET 4.0. For example, an executable called MyApplication.exe might have xaml catalog files in the same directory called MyApplication.Core.catalog, MyApplication.Extension1.catalog, MyApplication.Extension2.catalog, etc. MyApplication.Core.catalog could look something like this:</p>
<p><span style="FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt">&lt;</span><b style="mso-bidi-font-weight: normal"><span style="FONT-FAMILY: Consolas; COLOR: #a31515; FONT-SIZE: 9.5pt">AssemblyCatalog</span></b><span style="FONT-FAMILY: Consolas; COLOR: #a31515; FONT-SIZE: 9.5pt"><br /></span><span style="FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: Consolas; COLOR: red; FONT-SIZE: 9.5pt">xmlns</span><span style="FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt">=</span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt">"<span style="COLOR: blue">clr-namespace:System.ComponentModel.Composition.Hosting;assembly=System.ComponentModel.Composition</span>"<br /><span style="COLOR: blue"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span></span><span style="COLOR: red">xmlns:x</span><span style="COLOR: blue">=<a href="https://schemas.microsoft.com/winfx/2006/xaml"><span style="color: #0000ff;">https://schemas.microsoft.com/winfx/2006/xaml</span></a></span><br /><span style="COLOR: blue"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span></span><b style="mso-bidi-font-weight: normal"><span style="COLOR: red">x:Arguments</span><span style="COLOR: blue">=</span>"<span style="COLOR: blue">MyApplication.exe</span>"</b><span style="COLOR: blue"> /&gt;</span></span></p>
<p>This catalog would expose all parts exported in the primary executable. Alternatively, MyApplication.Core.catalog could be much more selective and look more like this:</p>
</div>
<p class="MsoNormal"><span style="FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt">&lt;</span><b style="mso-bidi-font-weight: normal"><span style="FONT-FAMILY: Consolas; COLOR: #a31515; FONT-SIZE: 9.5pt">TypeCatalog</span></b><span style="FONT-FAMILY: Consolas; COLOR: #a31515; FONT-SIZE: 9.5pt"><br /></span><span style="FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: Consolas; COLOR: red; FONT-SIZE: 9.5pt">xmlns</span><span style="FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt">=</span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt">"<span style="COLOR: blue">clr-namespace:System.ComponentModel.Composition.Hosting;assembly=System.ComponentModel.Composition</span>"<br /><span style="COLOR: blue"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span></span><span style="COLOR: red">xmlns:sys</span><span style="COLOR: blue">=</span>"<span style="COLOR: blue">clr-namespace:System;assembly=mscorlib</span>"<br /><span style="COLOR: blue"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span></span><span style="COLOR: red">xmlns:x</span><span style="COLOR: blue">=</span>"<span style="COLOR: blue">https://schemas.microsoft.com/winfx/2006/xaml</span>"<span style="COLOR: blue">&gt;</span><br /><span style="COLOR: blue"><span style="mso-spacerun: yes">&nbsp; </span>&lt;</span><span style="COLOR: #a31515">x:Arguments</span><span style="COLOR: blue">&gt;</span><br /><span style="COLOR: blue"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span>&lt;</span><span style="COLOR: #a31515">x:Array</span><span style="COLOR: blue"> </span><span style="COLOR: red">Type</span><span style="COLOR: blue">=</span>"<span style="COLOR: blue">sys:Type</span>"<span style="COLOR: blue">&gt;</span><br /><span style="COLOR: blue"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;</span><span style="COLOR: #a31515">sys:Type</span><span style="COLOR: blue"> </span><span style="COLOR: red">x:FactoryMethod</span><span style="COLOR: blue">=</span>"<span style="COLOR: blue">sys:Type.GetType</span>"<span style="COLOR: blue"> </span><span style="COLOR: red">x:Arguments</span><span style="COLOR: blue">=</span>"<b style="mso-bidi-font-weight: normal"><span style="COLOR: blue">PartA, PartLibrary1</span></b>"<span style="COLOR: blue"> /&gt;</span><br /><span style="COLOR: blue"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;</span><span style="COLOR: #a31515">sys:Type</span><span style="COLOR: blue"> </span><span style="COLOR: red">x:FactoryMethod</span><span style="COLOR: blue">=</span>"<span style="COLOR: blue">sys:Type.GetType</span>"<span style="COLOR: blue"> </span><span style="COLOR: red">x:Arguments</span><span style="COLOR: blue">=</span>"<b style="mso-bidi-font-weight: normal"><span style="COLOR: blue">PartB, PartLibrary1</span></b>"<span style="COLOR: blue"> /&gt;</span><br /><span style="COLOR: blue"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;</span><span style="COLOR: #a31515">sys:Type</span><span style="COLOR: blue"> </span><span style="COLOR: red">x:FactoryMethod</span><span style="COLOR: blue">=</span>"<span style="COLOR: blue">sys:Type.GetType</span>"<span style="COLOR: blue"> </span><span style="COLOR: red">x:Arguments</span><span style="COLOR: blue">=</span>"<b style="mso-bidi-font-weight: normal"><span style="COLOR: blue">PartC, PartLibrary2</span></b>"<span style="COLOR: blue"> /&gt;</span><br /><span style="COLOR: blue"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;</span><span style="COLOR: #a31515">sys:Type</span><span style="COLOR: blue"> </span><span style="COLOR: red">x:FactoryMethod</span><span style="COLOR: blue">=</span>"<span style="COLOR: blue">sys:Type.GetType</span>"<span style="COLOR: blue"> </span><span style="COLOR: red">x:Arguments</span><span style="COLOR: blue">=</span>"<b style="mso-bidi-font-weight: normal"><span style="COLOR: blue">PartD, PartLibrary2</span></b>"<span style="COLOR: blue"> /&gt;</span><br /><span style="COLOR: blue"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span>&lt;/</span><span style="COLOR: #a31515">x:Array</span><span style="COLOR: blue">&gt;</span><br /><span style="COLOR: blue"><span style="mso-spacerun: yes">&nbsp; </span>&lt;/</span><span style="COLOR: #a31515">x:Arguments</span><span style="COLOR: blue">&gt;</span><br /><span style="COLOR: blue">&lt;/</span><b style="mso-bidi-font-weight: normal"><span style="COLOR: #a31515">TypeCatalog</span></b><span style="COLOR: blue">&gt;</span></span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="COLOR: blue"></span></span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="COLOR: blue"><o:p></o:p></span></span></p>
<p><br />Alternatively, the two might be combined with an AggregateCatalog as follows:</p>
<p><span style="line-height: 115%; font-family: Consolas; color: blue; font-size: 9.5pt; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA;">&lt;</span><b style="mso-bidi-font-weight: normal;"><span style="line-height: 115%; font-family: Consolas; color: #a31515; font-size: 9.5pt; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA;">AggregateCatalog</span></b><span style="line-height: 115%; font-family: Consolas; font-size: 9.5pt; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA;"><br /><span style="color: blue;"><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span></span><span style="color: red;">xmlns</span><span style="color: blue;">=</span>"<span style="color: blue;">clr-namespace:System.ComponentModel.Composition.Hosting;assembly=System.ComponentModel.Composition</span>"<br /><span style="color: blue;"><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span></span><span style="color: red;">xmlns:sys</span><span style="color: blue;">=</span>"<span style="color: blue;">clr-namespace:System;assembly=mscorlib</span>"<br /><span style="color: blue;"><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span></span><span style="color: red;">xmlns:mefp</span><span style="color: blue;">=</span>"<span style="color: blue;">clr-namespace:System.ComponentModel.Composition.Primitives;assembly=System.ComponentModel.Composition</span>"<br /><span style="color: blue;"><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span></span><span style="color: red;">xmlns:x</span><span style="color: blue;">=</span>"<span style="color: blue;">https://schemas.microsoft.com/winfx/2006/xaml</span>"<span style="color: blue;">&gt;</span><br /><span style="color: blue;"><span style="mso-spacerun: yes;">&nbsp; </span>&lt;</span><span style="color: #a31515;">x:Arguments</span><span style="color: blue;">&gt;</span><br /><span style="color: blue;"><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span>&lt;</span><span style="color: #a31515;">x:Array</span><span style="color: blue;"> </span><span style="color: red;">Type</span><span style="color: blue;">=</span>"<span style="color: blue;">mefp:ComposablePartCatalog</span>"<span style="color: blue;">&gt;</span><br /><br /><span style="color: blue;"><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;</span><b style="mso-bidi-font-weight: normal;"><span style="color: #a31515;">AssemblyCatalog</span></b><span style="color: blue;"> </span><span style="color: red;">x:Arguments</span><span style="color: blue;">=</span>"<b style="mso-bidi-font-weight: normal;"><span style="color: blue;">MyApplication.exe</span></b>"<span style="color: blue;"> /&gt;</span><br /><br /><span style="color: blue;"><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;</span><b style="mso-bidi-font-weight: normal;"><span style="color: #a31515;">TypeCatalog</span></b><span style="color: blue;">&gt;</span><br /><span style="color: blue;"><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;</span><span style="color: #a31515;">x:Arguments</span><span style="color: blue;">&gt;</span><br /><span style="color: blue;"><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;</span><span style="color: #a31515;">x:Array</span><span style="color: blue;"> </span><span style="color: red;">Type</span><span style="color: blue;">=</span>"<span style="color: blue;">sys:Type</span>"<span style="color: blue;">&gt;</span><br /><span style="color: blue;"><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;</span><span style="color: #a31515;">sys:Type</span><span style="color: blue;"> </span><span style="color: red;">x:FactoryMethod</span><span style="color: blue;">=</span>"<span style="color: blue;">sys:Type.GetType</span>"<span style="color: blue;"> </span><span style="color: red;">x:Arguments</span><span style="color: blue;">=</span>"<b style="mso-bidi-font-weight: normal;"><span style="color: blue;">PartA, PartLibrary1</span></b>"<span style="color: blue;"> /&gt;</span><br /><span style="color: blue;"><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;</span><span style="color: #a31515;">sys:Type</span><span style="color: blue;"> </span><span style="color: red;">x:FactoryMethod</span><span style="color: blue;">=</span>"<span style="color: blue;">sys:Type.GetType</span>"<span style="color: blue;"> </span><span style="color: red;">x:Arguments</span><span style="color: blue;">=</span>"<b style="mso-bidi-font-weight: normal;"><span style="color: blue;">PartB, PartLibrary1</span></b>"<span style="color: blue;"> /&gt;</span><br /><span style="color: blue;"><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;</span><span style="color: #a31515;">sys:Type</span><span style="color: blue;"> </span><span style="color: red;">x:FactoryMethod</span><span style="color: blue;">=</span>"<span style="color: blue;">sys:Type.GetType</span>"<span style="color: blue;"> </span><span style="color: red;">x:Arguments</span><span style="color: blue;">=</span>"<b style="mso-bidi-font-weight: normal;"><span style="color: blue;">PartC, PartLibrary2</span></b>"<span style="color: blue;"> /&gt;</span><br /><span style="color: blue;"><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;</span><span style="color: #a31515;">sys:Type</span><span style="color: blue;"> </span><span style="color: red;">x:FactoryMethod</span><span style="color: blue;">=</span>"<span style="color: blue;">sys:Type.GetType</span>"<span style="color: blue;"> </span><span style="color: red;">x:Arguments</span><span style="color: blue;">=</span>"<b style="mso-bidi-font-weight: normal;"><span style="color: blue;">PartD, PartLibrary2</span></b>"<span style="color: blue;"> /&gt;</span><br /><span style="color: blue;"><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>&lt;/</span><span style="color: #a31515;">x:Array</span><span style="color: blue;">&gt;</span><br /><span style="color: blue;"><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;/</span><span style="color: #a31515;">x:Arguments</span><span style="color: blue;">&gt;</span><br /><span style="color: blue;"><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;/</span><b style="mso-bidi-font-weight: normal;"><span style="color: #a31515;">TypeCatalog</span></b><span style="color: blue;">&gt;</span><br /><br /><span style="color: blue;"><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span>&lt;/</span><span style="color: #a31515;">x:Array</span><span style="color: blue;">&gt;</span><br /><span style="color: blue;"><span style="mso-spacerun: yes;">&nbsp; </span>&lt;/</span><span style="color: #a31515;">x:Arguments</span><span style="color: blue;">&gt;</span><br /><span style="color: blue;">&lt;/</span><b style="mso-bidi-font-weight: normal;"><span style="color: #a31515;">AggregateCatalog</span></b><span style="color: blue;">&gt;</span></span></p>
<p>These catalogs could be as simple or as complex as necessary, and catalogs could be added or removed at any time without recompiling the application. Additionally, using the <a target="_blank" href="https://blogs.msdn.com/b/ryantrem/archive/2010/06/21/generically-sharing-xaml-resources.aspx">XamlExtension MarkupExtension I blogged about previously</a>, catalogs could easily be shared as follows:</p>
<p><span style="LINE-HEIGHT: 115%; FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA">&lt;</span><b style="mso-bidi-font-weight: normal"><span style="LINE-HEIGHT: 115%; FONT-FAMILY: Consolas; COLOR: #a31515; FONT-SIZE: 9.5pt; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA">AggregateCatalog</span></b><span style="LINE-HEIGHT: 115%; FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"><br /><span style="COLOR: blue"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span></span><span style="COLOR: red">xmlns</span><span style="COLOR: blue">=</span>"<span style="COLOR: blue">clr-namespace:System.ComponentModel.Composition.Hosting;assembly=System.ComponentModel.Composition</span>"<br /><span style="COLOR: blue"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span></span><span style="COLOR: red">xmlns:sys</span><span style="COLOR: blue">=</span>"<span style="COLOR: blue">clr-namespace:System;assembly=mscorlib</span>"<br /><span style="COLOR: blue"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span></span><span style="COLOR: red">xmlns:mefp</span><span style="COLOR: blue">=</span>"<span style="COLOR: blue">clr-namespace:System.ComponentModel.Composition.Primitives;assembly=System.ComponentModel.Composition</span>"<br /><span style="mso-spacerun: yes">&nbsp;&nbsp; </span><span style="COLOR: red"><span style="mso-spacerun: yes">&nbsp;</span>xmlns</span><span style="COLOR: blue">:</span><span style="COLOR: red">xe</span><span style="COLOR: blue">="clr-namespace:XamlExtensions;assembly=XamlExtensions"</span><br /><span style="COLOR: blue"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span></span><span style="COLOR: red">xmlns:x</span><span style="COLOR: blue">=</span>"<span style="COLOR: blue">https://schemas.microsoft.com/winfx/2006/xaml</span>"<span style="COLOR: blue">&gt;</span><br /><span style="COLOR: blue"><span style="mso-spacerun: yes">&nbsp; </span>&lt;</span><span style="COLOR: #a31515">x:Arguments</span><span style="COLOR: blue">&gt;</span><br /><span style="COLOR: blue"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span>&lt;</span><span style="COLOR: #a31515">x:Array</span><span style="COLOR: blue"> </span><span style="COLOR: red">Type</span><span style="COLOR: blue">=</span>"<span style="COLOR: blue">mefp:ComposablePartCatalog</span>"<span style="COLOR: blue">&gt;</span><br /><br /><span style="COLOR: blue"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;</span><b style="mso-bidi-font-weight: normal"><span style="COLOR: #a31515">AssemblyCatalog</span></b><span style="COLOR: blue"> </span><span style="COLOR: red">x:Arguments</span><span style="COLOR: blue">=</span>"<b style="mso-bidi-font-weight: normal"><span style="COLOR: blue">MyApplication.exe</span></b>"<span style="COLOR: blue"> /&gt;</span><br /><br /><b style="mso-bidi-font-weight: normal"><span style="COLOR: blue"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;</span><span style="COLOR: #a31515">xe</span><span style="COLOR: blue">:</span><span style="COLOR: #a31515">Xaml</span><span style="COLOR: red"> Source</span><span style="COLOR: blue">="CommonExtension1.catalog" /&gt;</span></b><span style="COLOR: blue"><br /></span><br /><span style="COLOR: blue"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span>&lt;/</span><span style="COLOR: #a31515">x:Array</span><span style="COLOR: blue">&gt;</span><br /><span style="COLOR: blue"><span style="mso-spacerun: yes">&nbsp; </span>&lt;/</span><span style="COLOR: #a31515">x:Arguments</span><span style="COLOR: blue">&gt;</span><br /><span style="COLOR: blue">&lt;/</span><b style="mso-bidi-font-weight: normal"><span style="COLOR: #a31515">AggregateCatalog</span></b><span style="COLOR: blue">&gt;</span></span></p>
<p>The code to load the xaml encoded catalogs is pretty straight forward:</p>
<p><span style="LINE-HEIGHT: 115%; FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA">public</span><span style="LINE-HEIGHT: 115%; FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"> <span style="COLOR: blue">static</span> <span style="COLOR: blue">class</span> <b><span style="COLOR: navy">XamlCatalogServices</span></b><br />{<br /><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span><span style="COLOR: blue">public</span> <span style="COLOR: blue">static</span> <b><span style="COLOR: navy">ComposablePartCatalog</span></b> LoadCatalog(<span style="COLOR: blue">string</span> filePath)<br /><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span>{<br /><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: blue">var </span>catalog = <b><span style="COLOR: navy">XamlServices</span></b>.Load(filePath) <span style="COLOR: blue">as</span> <b><span style="COLOR: navy">ComposablePartCatalog</span></b>;<br /><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: blue">if</span> (catalog == <span style="COLOR: blue">null</span>)<br /><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{<br /><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: blue">throw</span> <span style="COLOR: blue">new</span> <b><span style="COLOR: navy">InvalidOperationException</span></b>(<span style="COLOR: blue">string</span>.Format(<span style="COLOR: #a31515">"{0} is not a ComposablePartCatalog"</span>, filePath));<br /><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}<br /><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: blue">return</span> catalog;<br /><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span>}<br /><br /><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span><span style="COLOR: blue">public</span> <span style="COLOR: blue">static</span> <span style="COLOR: #2b91af">IEnumerable</span>&lt;<b><span style="COLOR: navy">ComposablePartCatalog</span></b>&gt; LoadCatalogs(<span style="COLOR: blue">string</span> directory = <span style="COLOR: blue">null</span>, <span style="COLOR: blue">string</span> searchPattern = <span style="COLOR: blue">null</span>, <span style="COLOR: olive">SearchOption</span> searchOption = <span style="COLOR: olive">SearchOption</span>.TopDirectoryOnly)<br /><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span>{<br /><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: blue">if</span> (<span style="COLOR: blue">string</span>.IsNullOrEmpty(directory))<br /><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{<br /><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>directory = <b><span style="COLOR: navy">Path</span></b>.GetDirectoryName(<b><span style="COLOR: navy">Assembly</span></b>.GetEntryAssembly().Location);<br /><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}<br /><br /><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: blue">if</span> (<span style="COLOR: blue">string</span>.IsNullOrEmpty(searchPattern))<br /><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{<br /><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>searchPattern = <span style="COLOR: blue">string</span>.Format(<span style="COLOR: #a31515">"{0}*.catalog"</span>, <b><span style="COLOR: navy">Path</span></b>.GetFileNameWithoutExtension(<b><span style="COLOR: navy">Assembly</span></b>.GetEntryAssembly().Location));<br /><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}<br /><br /><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: blue">return</span> <b><span style="COLOR: navy">Directory</span></b>.EnumerateFiles(directory, searchPattern, searchOption).Select(filePath =&gt; <b><span style="COLOR: navy">XamlCatalogServices</span></b>.LoadCatalog(filePath));<br /><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span>}<br />}</span></p>
<p><strong>Discovering and executing the pseudo entry points</strong></p>
<p>Since my goal includes implementing a small, generic bootstrapper that can be used as the basis for any MEF-based application, the concept of an entry point must be abstracted. The application executable, which hosts the bootstrapper, will of course have the real entry point, but the bootstrapper will discover and execute pseudo entry points on a per-application basis. The approach I take here is to simply have the bootstrapper query the container (after the catalogs have been initialized) for an IEntryPoint and invoke it. I defined IEntryPoint as follows:</p>
<p><span style="LINE-HEIGHT: 115%; FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA">public</span><span style="LINE-HEIGHT: 115%; FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"> <span style="COLOR: blue">interface</span> <span style="COLOR: #2b91af">IEntryPoint</span><br />{<br /><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span><span style="COLOR: blue">void</span> BeginExecution();<br />}</span></p>
<p>An application could implement its own custom IEntryPoint, but I&rsquo;ve found a few generic implementations to be sufficient in most cases. The first I called PartActivatingEntryPoint, which gets startup components running. This entry point &ldquo;activates&rdquo; parts with the &ldquo;AutoActivate&rdquo; contract. Examples of such parts might be the main window of an application, background services that are not consumed by other components but provide important functionality (such an auto-save component), etc. I defined PartActivationEntryPoint as follows:</p>
<p><span style="LINE-HEIGHT: 115%; FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA">[<b><span style="COLOR: navy">Export</span></b>(<span style="COLOR: blue">typeof</span>(<span style="COLOR: #2b91af">IEntryPoint</span>))]<br /><span style="COLOR: blue">public</span> <span style="COLOR: blue">class</span> <b><span style="COLOR: navy">PartActivatingEntryPoint</span></b> : <span style="COLOR: #2b91af">IEntryPoint</span><br />{<br /><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span>[<b><span style="COLOR: navy">ImportMany</span></b>(<span style="COLOR: #a31515">"AutoActivate"</span>)]<br /><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span><span style="COLOR: blue">private</span> <span style="COLOR: #2b91af">IEnumerable</span>&lt;<b><span style="COLOR: navy">Lazy</span></b>&lt;<span style="COLOR: blue">object</span>&gt;&gt; autoActivateParts;<br /><br /><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span><span style="COLOR: blue">public</span> <span style="COLOR: blue">virtual</span> <span style="COLOR: blue">void</span> BeginExecution()<br /><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span>{<br /><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: blue">this</span>.autoActivateParts.Select(part =&gt; part.Value).ToArray();<br /><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span>}<br />}</span></p>
<p>A subclass of PartActivatingEntryPoint that I&rsquo;ve found useful is one I called WpfApplicationEntryPoint. It instantiates a System.Windows.Application class and then activates startup parts within the context of the Dispatcher. I defined WpfApplicationEntryPoint as follows:</p>
<p><span style="line-height: 115%; font-family: Consolas; font-size: 9.5pt; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA;">[<b><span style="color: navy;">Export</span></b>(<span style="color: blue;">typeof</span>(<span style="color: #2b91af;">IEntryPoint</span>))]<br /><span style="color: blue;">public</span> <span style="color: blue;">class</span> <b><span style="color: navy;">WpfApplicationEntryPoint</span></b> : <b><span style="color: navy;">PartActivatingEntryPoint</span></b><br />{<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">public</span> <span style="color: blue;">override</span> <span style="color: blue;">void</span> BeginExecution()<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span>{<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">var</span> application = <span style="color: blue;">new</span> <b><span style="color: navy;">Application</span></b>();<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>application.Startup += <span style="color: blue;">delegate</span> { <span style="color: blue;">base</span>.BeginExecution(); };<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;</span>application.Run();<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span>}<br />}</span></p>
<p><strong>Putting the pieces together</strong></p>
<p>I&rsquo;ve described my approach to preparing the part catalog and discovering and executing the pseudo entry points, and provided sample code showing basic implementations. The only remaining part is to pull these pieces together into the actual bootstrapper. This is easily done as follows:</p>
<p><span style="line-height: 115%; font-family: Consolas; color: blue; font-size: 9.5pt; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA;">public</span><span style="line-height: 115%; font-family: Consolas; font-size: 9.5pt; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA;"> <span style="color: blue;">static</span> <span style="color: blue;">class</span> <b><span style="color: navy;">MEFBootstrapper</span></b><br />{<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">public</span> <span style="color: blue;">static</span> <span style="color: blue;">void</span> Run()<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span>{<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: green;">// Discover the catalogs and create the container</span><br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">var</span> container = <span style="color: blue;">new</span> <b><span style="color: navy;">CompositionContainer</span></b>(<span style="color: blue;">new</span> <b><span style="color: navy;">AggregateCatalog</span></b>(<b><span style="color: navy;">XamlCatalogServices</span></b>.LoadCatalogs()));<br /><br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: green;">// Query the container for the entry point</span><br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">var</span> entryPoint = container.GetExportedValueOrDefault&lt;<span style="color: #2b91af;">IEntryPoint</span>&gt;();<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">if</span> (entryPoint == <span style="color: blue;">null</span>)<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">throw</span> <span style="color: blue;">new</span> <b><span style="color: navy;">InvalidOperationException</span></b>(<span style="color: #a31515;">"No entry point found. Add an IEntryPoint to the container."</span>);<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}<br /><br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: green;">// Invoke the entry point</span><br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>entryPoint.BeginExecution();<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span>}<br />}</span></p>
<p>MEFBootStrapper.Run can be invoked from the real application entry point. For example:</p>
<p><span style="line-height: 115%; font-family: Consolas; color: blue; font-size: 9.5pt; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA;">internal</span><span style="line-height: 115%; font-family: Consolas; font-size: 9.5pt; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA;"> <span style="color: blue;">static</span> <span style="color: blue;">class</span> <b><span style="color: navy;">Program</span></b><br />{<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span>[<b><span style="color: navy;">STAThread</span></b>]<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">private</span> <span style="color: blue;">static</span> <span style="color: blue;">void</span> Main()<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span>{<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><b><span style="color: navy;">MEFBootstrapper</span></b>.Run();<br /><span style="mso-spacerun: yes;">&nbsp;&nbsp;&nbsp; </span>}<br />}</span></p>
<p>In fact, the same executable containing the Main method shown above could be used as the starting point for any MEF-based application that uses the bootstrapper that I&rsquo;ve defined here (ok, a recompile of this executable would be necessary for a console application).</p>
<p>I&rsquo;ve found this simple approach to composing extensible applications from loosely coupled reusable parts to be very successful. I hope others find it useful as well. I&rsquo;ve made some <a href="https://cid-75984f86a9f4ee72.office.live.com/self.aspx/MSDN%20Blog/MEFBootstrapperSample.zip">sample code</a> available as a simplified but complete demonstration of this approach. In the sample code, I deliberately made some parts &ldquo;auto activated&rdquo; while others are not since this is what I would expect in a real application. Feedback is welcome.</p>]]></content:encoded>
    </item>
    <item>
      <title>Generically sharing Xaml resources</title>
      <link>https://docs.microsoft.com/archive/blogs/ryantrem/generically-sharing-xaml-resources</link>
      <pubDate>Mon, 21 Jun 2010 10:49:00 GMT</pubDate>
      <dc:creator><![CDATA[ryantrem]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/ryantrem/2010/06/21/generically-sharing-xaml-resources/</guid>
      <description><![CDATA[Xaml was introduced in .NET 3.0 and extensively used by WPF. A commonly used construct in WPF is the...]]></description>
      <content:encoded><![CDATA[<p>Xaml was introduced in .NET 3.0 and extensively used by WPF. A commonly used construct in WPF is the ResourceDictionary, which defines a collection of resources that can be referenced. Often, ResourceDictionaries are shared by including them in other ResourceDictionaries. When defined in xaml, we might have something like this:</p>
<p class="MsoNormal"><span style="FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt">&lt;</span><span style="FONT-FAMILY: Consolas; COLOR: #a31515; FONT-SIZE: 9.5pt">Window.Resources</span><span style="FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt">&gt;<br /></span><span style="FONT-FAMILY: Consolas; COLOR: #a31515; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt">&lt;</span><span style="FONT-FAMILY: Consolas; COLOR: #a31515; FONT-SIZE: 9.5pt">ResourceDictionary</span><span style="FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt">&gt;<br /></span><span style="FONT-FAMILY: Consolas; COLOR: #a31515; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt">&lt;</span><span style="FONT-FAMILY: Consolas; COLOR: #a31515; FONT-SIZE: 9.5pt">ResourceDictionary.MergedDictionaries</span><span style="FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt">&gt;<br /></span><strong><span style="FONT-FAMILY: Consolas; COLOR: #a31515; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt">&lt;</span><span style="FONT-FAMILY: Consolas; COLOR: #a31515; FONT-SIZE: 9.5pt">ResourceDictionary</span><span style="FONT-FAMILY: Consolas; COLOR: red; FONT-SIZE: 9.5pt"> Source</span><span style="FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt">="MyResources.xaml" /&gt;<br /></span></strong><span style="FONT-FAMILY: Consolas; COLOR: #a31515; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt">&lt;/</span><span style="FONT-FAMILY: Consolas; COLOR: #a31515; FONT-SIZE: 9.5pt">ResourceDictionary.MergedDictionaries</span><span style="FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt">&gt;<br /></span><span style="FONT-FAMILY: Consolas; COLOR: #a31515; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt">&lt;/</span><span style="FONT-FAMILY: Consolas; COLOR: #a31515; FONT-SIZE: 9.5pt">ResourceDictionary</span><span style="FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt">&gt;<br /></span><span style="FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt">&lt;/</span><span style="FONT-FAMILY: Consolas; COLOR: #a31515; FONT-SIZE: 9.5pt">Window.Resources</span><span style="FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt">&gt;</span>&nbsp;</p>
<p class="MsoNormal">&nbsp;</p>
<p>Xaml is not really helping us with the reference to the shared resources in this example. Rather, ResourceDictionary has the logic to initialize itself from a Uri pointing to another ResourceDictionary. ResourceDictionary is certainly not the only data type you can imagine wanting to share and reference from multiple xaml documents. This is especially true with the .NET 4.0 release, where xaml has been completely decoupled from WPF and is much more suitable as a general purpose serialization/deserialization technology.</p>
<p>One simple approach to sharing and referencing xaml documents from other xaml documents is to implement a custom MarkupExtension. With a custom MarkupExtension, our xaml might look something like this:</p>
<p class="MsoNormal"><span style="FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt">&lt;</span><span style="FONT-FAMILY: Consolas; COLOR: #a31515; FONT-SIZE: 9.5pt">Window.Resources</span><span style="FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt">&gt;<br /></span><span style="FONT-FAMILY: Consolas; COLOR: #a31515; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt">&lt;</span><span style="FONT-FAMILY: Consolas; COLOR: #a31515; FONT-SIZE: 9.5pt">ResourceDictionary</span><span style="FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt">&gt;<br /></span><span style="FONT-FAMILY: Consolas; COLOR: #a31515; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt">&lt;</span><span style="FONT-FAMILY: Consolas; COLOR: #a31515; FONT-SIZE: 9.5pt">ResourceDictionary.MergedDictionaries</span><span style="FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt">&gt;<br /></span><strong><span style="FONT-FAMILY: Consolas; COLOR: #a31515; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt">&lt;</span><span style="FONT-FAMILY: Consolas; COLOR: #a31515; FONT-SIZE: 9.5pt">Xaml</span><span style="FONT-FAMILY: Consolas; COLOR: red; FONT-SIZE: 9.5pt"> Source</span><span style="FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt">="MyResources.xaml" /&gt;<br /></span></strong><span style="FONT-FAMILY: Consolas; COLOR: #a31515; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt">&lt;/</span><span style="FONT-FAMILY: Consolas; COLOR: #a31515; FONT-SIZE: 9.5pt">ResourceDictionary.MergedDictionaries</span><span style="FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt">&gt;<br /></span><span style="FONT-FAMILY: Consolas; COLOR: #a31515; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt">&lt;/</span><span style="FONT-FAMILY: Consolas; COLOR: #a31515; FONT-SIZE: 9.5pt">ResourceDictionary</span><span style="FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt">&gt;<br /></span><span style="FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt">&lt;/</span><span style="FONT-FAMILY: Consolas; COLOR: #a31515; FONT-SIZE: 9.5pt">Window.Resources</span><span style="FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt">&gt;</span></p>
<p class="MsoNormal">&nbsp;</p>
<p>This looks almost exactly the same as the first ResourceDictionary example. The major difference is that it relies on a general Xaml MarkupExtension that will load any xaml document. This will work with ResourceDictionaries or any other data type in any xaml context (including WPF). Through the IServiceProvider exposed to MarkupExtensions, the necessary context is available to resolve relative Uris to absolute Uris, which are required for finding and deserializing the referenced xaml documents. A basic version of the Xaml MarkupExtension would look like this:</p>
<p class="MsoNormal"><span style="FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt">public</span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"> <span style="COLOR: blue">class</span> <b><span style="COLOR: navy">XamlExtension</span></b> : <b><span style="COLOR: navy">MarkupExtension<br /></span></b></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt">{<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span><span style="COLOR: blue">public</span> <b><span style="COLOR: navy">Uri</span></b>&nbsp;Source { <span style="COLOR: blue">get</span>; <span style="COLOR: blue">set</span>; }<br /><br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span><span style="COLOR: blue">public</span> <span style="COLOR: blue">override</span> <span style="COLOR: blue">object</span> ProvideValue(<span style="COLOR: #2b91af">IServiceProvider</span> serviceProvider)<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span>{<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: blue">if</span> (<span style="COLOR: blue">this</span>.Source == <span style="COLOR: blue">null</span>)<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: blue">throw</span> <span style="COLOR: blue">new</span> <b><span style="COLOR: navy">ArgumentNullException</span></b>(<span style="COLOR: #a31515">"Source"</span>);<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><o:p><br /></o:p></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: blue">var</span> absoluteUri = <span style="COLOR: blue">this</span>.Source;<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><o:p>&nbsp;<br /></o:p></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </span><span style="COLOR: blue">if</span> (!absoluteUri.IsAbsoluteUri)<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: blue">var</span> uriContext = (<span style="COLOR: #2b91af">IUriContext</span>)serviceProvider.GetService(<span style="COLOR: blue">typeof</span>(<span style="COLOR: #2b91af">IUriContext</span>));<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: blue">if</span> (uriContext != <span style="COLOR: blue">null</span> &amp;&amp; uriContext.BaseUri != <span style="COLOR: blue">null</span>)<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>absoluteUri = <span style="COLOR: blue">new</span> <b><span style="COLOR: navy">Uri</span></b>(uriContext.BaseUri, absoluteUri);<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}<br /><br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: blue">return</span> <b><span style="COLOR: navy">XamlServices</span></b>.Load(absoluteUri.AbsoluteUri);<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span>}<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt">}</span><o:p><span style="font-family: Calibri; font-size: small;">&nbsp;</span></o:p></p>
<p class="MsoNormal">&nbsp;</p>
<p>The first thing to note about this is the method of resolving relative Uris. The IServiceProvider is queried for an IUriContext, which in turn provides the base Uri. The base Uri will be set appropriately as long as the original xaml document was loaded in such a way that the xaml deserializer can know where it came from. For example, if the xaml document was loaded from a physical file on disk, the xaml deserializer will know the base Uri. On the other hand, if the xaml document was loaded from a stream, the xaml deserializer will have no way of knowing a base Uri for the document being loaded. The second thing to note is that the referenced xaml document is loaded using XamlServices.Load and passing in the absolute Uri as a string. Although the documentation is a bit unclear on XamlServices.Load, the overload that takes a string can in fact be a Uri string. The third thing to note is the method of loading referenced xaml documents. Since an absolute Uri is used, and since the IUriContext is correctly configured when loading from a Uri using XamlServices.Load, multiple layers of references are possible, and references are always relative to the xaml document that contains the reference. In other words, it is valid to have a xaml document that references a xaml document that references a xaml document, etc, even when the xaml documents are located at different Uris (such as in different file system directories).</p>
<p>The last thing to note about this MarkupExtension is its use in the context of pack Uris, which are used extensively in WPF applications. Specifically, the "pack" prefix and web request factory are registered relatively early in the startup of a WPF application, but may not have been registered at the point where the MarkupExtension is invoked during deserialization. When this is the case, the "pack" prefix can be registered manually:&nbsp;</p>
<p class="MsoNormal"><span style="font-family: Consolas; font-size: 9.5pt;">System.Net.<b><span style="color: navy;">WebRequest</span></b>.RegisterPrefix(<span style="color: #a31515;">"pack"</span>, <span style="color: blue;">new</span> System.IO.Packaging.<b><span style="color: navy;">PackWebRequestFactory</span></b>());</span><o:p><span style="font-family: Calibri; font-size: small;">&nbsp;<br /></span></o:p>&nbsp;</p>
<p>As always, feedback is welcome.</p>
<div></div>
<div></div>]]></content:encoded>
    </item>
    <item>
      <title>Loading DDS files as WPF ImageSources using XNA 3.1</title>
      <link>https://docs.microsoft.com/archive/blogs/ryantrem/loading-dds-files-as-wpf-imagesources-using-xna-3-1</link>
      <pubDate>Sun, 06 Jun 2010 12:57:00 GMT</pubDate>
      <dc:creator><![CDATA[ryantrem]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/ryantrem/2010/06/06/loading-dds-files-as-wpf-imagesources-using-xna-3-1/</guid>
      <description><![CDATA[WPF uses "Windows Imaging Component," or WIC,...]]></description>
      <content:encoded><![CDATA[<p>WPF uses "Windows Imaging Component," or WIC, (see&nbsp;<a href="https://msdn.microsoft.com/en-us/library/ee719655">https://msdn.microsoft.com/en-us/library/ee719655</a>) to decode images. By default, WIC supports many image formats, such as .bmp, .jpg, .png, but also can be extended to support new image formats via "codecs." Out of the box, WIC does not support DDS files. A common case for wanting to display a DDS file in a WPF application is for game content authoring tools. Arguably, the best way to display new image formats (such as DDS) in WPF is to implement a WIC codec. Commercial solutions doing exactly this are available. The benefit of this is that all applications that use WIC (Windows Explorer, Windows Live Photo Gallery, virtually all WPF-based applications, etc.) will be able to decode and display the new image format. However, this is a system wide change that must be registered with WIC, probably via an installer. An alternative approach is to provide the DDS decoding logic in the application code (or a shared library). This approach lacks the benefits of WIC, but with the help of XNA is very simple and can be implemented entirely in managed code.</p>
<p>The general idea is to use XNA's Texture2D class to load the DDS, then do a per pixel conversion to a WPF BitmapSource. First, I'll implement the core method for doing the conversion from a Stream to an ImageSource:</p>
<div class="Section1">
<p class="MsoNormal"><span style="font-size:9.5pt;line-height:115%;font-family:
Consolas;color:blue">public</span><span style="font-size:9.5pt;line-height:
115%;font-family:Consolas"> <span style="color:blue">static</span> <span style="color: #2b91af;">ImageSource</span> Convert(<span style="color:#2B91AF">Stream</span>
stream)</span><br />
<span style="font-size:9.5pt;line-height:115%;font-family:Consolas">{</span><br />
<span style="font-size:9.5pt;line-height:115%;font-family:Consolas">&nbsp;&nbsp;&nbsp;
<span style="color:green">// Create the graphics device</span></span><br />
<span style="font-size:9.5pt;line-height:115%;font-family:Consolas">&nbsp;&nbsp;&nbsp;
<span style="color:blue">using</span> (<span style="color:blue">var</span>
graphicsDevice = <span style="color:blue">new</span> <span style="color:#2B91AF">GraphicsDevice</span>(<span style="color: #2b91af;">GraphicsAdapter</span>.DefaultAdapter, <span style="color: #2b91af;">DeviceType</span>.NullReference, <span style="color:#2B91AF">IntPtr</span>.Zero,
<span style="color:blue">new</span> <span style="color:#2B91AF">PresentationParameters</span>()))</span><br />
<span style="font-size:9.5pt;line-height:115%;font-family:Consolas">&nbsp;&nbsp;&nbsp;
{</span><br />
<span style="font-size:9.5pt;line-height:115%;font-family:Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<span style="color:green">// Setup the texture creation parameters</span></span><br />
<span style="font-size:9.5pt;line-height:115%;font-family:Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<span style="color:blue">var</span> textureCreationParameters = <span style="color: blue;">new</span> <span style="color:#2B91AF">TextureCreationParameters</span>()</span><br />
<span style="font-size:9.5pt;line-height:115%;font-family:Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
{</span><br />
<span style="font-size:9.5pt;line-height:115%;font-family:Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Width = -1,</span><br />
<span style="font-size:9.5pt;line-height:115%;font-family:Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Height = -1,</span><br />
<span style="font-size:9.5pt;line-height:115%;font-family:Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Depth = 1,</span><br />
<span style="font-size:9.5pt;line-height:115%;font-family:Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
TextureUsage = <span style="color:#2B91AF">TextureUsage</span>.None,</span><br />
<span style="font-size:9.5pt;line-height:115%;font-family:Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Format = <span style="color:#2B91AF">SurfaceFormat</span>.Color,</span><br />
<span style="font-size:9.5pt;line-height:115%;font-family:Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Filter = <span style="color:#2B91AF">FilterOptions</span>.None,</span><br />
<span style="font-size:9.5pt;line-height:115%;font-family:Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
MipFilter = <span style="color:#2B91AF">FilterOptions</span>.None,</span><br />
<span style="font-size:9.5pt;line-height:115%;font-family:Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
MipLevels = 1</span><br />
<span style="font-size:9.5pt;line-height:115%;font-family:Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
};</span><br />
<span style="font-size:9.5pt;line-height:115%;font-family:Consolas">&nbsp;</span><br />
<span style="font-size:9.5pt;line-height:115%;font-family:Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<span style="color:green">// Load the texture</span></span><br />
<span style="font-size:9.5pt;line-height:115%;font-family:Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<span style="color:blue">using</span> (<span style="color:blue">var</span>
texture = <span style="color:#2B91AF">Texture2D</span>.FromFile(graphicsDevice,
stream, textureCreationParameters))</span><br />
<span style="font-size:9.5pt;line-height:115%;font-family:Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
{</span><br />
<span style="font-size:9.5pt;line-height:115%;font-family:Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<span style="color:green">// Get the pixel data</span></span><br />
<span style="font-size:9.5pt;line-height:115%;font-family:Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<span style="color:blue">var</span> pixelColors = <span style="color:blue">new</span>
Microsoft.Xna.Framework.Graphics.<span style="color:#2B91AF">Color</span>[texture.Width
* texture.Height];</span><br />
<span style="font-size:9.5pt;line-height:115%;font-family:Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
texture.GetData(pixelColors);</span><br />
<span style="font-size:9.5pt;line-height:115%;font-family:Consolas">&nbsp;</span><br />
<span style="font-size:9.5pt;line-height:115%;font-family:Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<span style="color:green">// Copy the pixel colors into a byte array</span></span><br />
<span style="font-size:9.5pt;line-height:115%;font-family:Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<span style="color:blue">var</span> bytesPerPixel = 3;</span><br />
<span style="font-size:9.5pt;line-height:115%;font-family:Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<span style="color:blue">var</span> stride = texture.Width * bytesPerPixel;</span><br />
<span style="font-size:9.5pt;line-height:115%;font-family:Consolas">&nbsp;</span><br />
<span style="font-size:9.5pt;line-height:115%;font-family:Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<span style="color:blue">var</span> pixelData = <span style="color:blue">new</span>
<span style="color:blue">byte</span>[pixelColors.Length * bytesPerPixel];</span><br />
<span style="font-size:9.5pt;line-height:115%;font-family:Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<span style="color:blue">for</span> (<span style="color:blue">var</span> i = 0;
i &lt; pixelColors.Length; i++)</span><br />
<span style="font-size:9.5pt;line-height:115%;font-family:Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
{</span><br />
<span style="font-size:9.5pt;line-height:115%;font-family:Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
pixelData[i * bytesPerPixel + 0] = pixelColors[i].R;</span><br />
<span style="font-size:9.5pt;line-height:115%;font-family:Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
pixelData[i * bytesPerPixel + 1] = pixelColors[i].G;</span><br />
<span style="font-size:9.5pt;line-height:115%;font-family:Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
pixelData[i * bytesPerPixel + 2] = pixelColors[i].B;</span><br />
<span style="font-size:9.5pt;line-height:115%;font-family:Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
}</span><br />
<span style="font-size:9.5pt;line-height:115%;font-family:Consolas">&nbsp;</span><br />
<span style="font-size:9.5pt;line-height:115%;font-family:Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<span style="color:green">// Create a bitmap source</span></span><br />
<span style="font-size:9.5pt;line-height:115%;font-family:Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<span style="color:blue">return</span> <span style="color:#2B91AF">BitmapSource</span>.Create(texture.Width,
texture.Height, 96, 96, <span style="color:#2B91AF">PixelFormats</span>.Rgb24, <span style="color: blue;">null</span>, pixelData, stride);</span><br />
<span style="font-size:9.5pt;line-height:115%;font-family:Consolas">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
}</span><br />
<span style="font-size:9.5pt;line-height:115%;font-family:Consolas">&nbsp;&nbsp;&nbsp;
}</span><br />}</p>
<p class="MsoNormal">&nbsp;</p>
</div>
<p>There are a few things worth noting here. First, note that only mip level one is being used as it is the highest resolution; the other mip levels are ignored. Second, note that alpha is being ignored entirely. There may be scenarios where this is important, but in many cases RGB data alone is sufficient and often desired. If alpha data is necessary, adding it should be a relatively minimal change.</p>
<p>Since the method above is intended for WPF applications, the DDS will likely be bound to a property of a WPF class, such as Image.Source. The DDS source may be a file path (e.g. loading from disk), may be a stream (e.g. loading from game content pack), may be a byte array (e.g. embedded resource), etc. This is another area where a WIC codec would provide a cleaner solution. The WPF ImageSource class already has a TypeConverter that handles converting from strings, streams, URIs, byte arrays, etc. by decoding the image using WIC. Since the XNA-based implementation provided here does not go through WIC, the binding must explicitly specify a converter. To support this, a custom IValueConverter can be used:</p>
<div class="Section1">
<p class="MsoNormal"><span style="font-size:9.5pt;line-height:115%;font-family:
Consolas;color:blue">public</span><span style="font-size:9.5pt;line-height:
115%;font-family:Consolas"> <span style="color:blue">class</span> <span style="color: #2b91af;">DDSConverter</span> : <span style="color:#2B91AF">IValueConverter</span><br />
{<br />
&nbsp;&nbsp;&nbsp; <span style="color:blue">private</span> <span style="color:blue">static</span>
<span style="color:blue">readonly</span> <span style="color:#2B91AF">DDSConverter</span>
defaultInstace = <span style="color:blue">new</span> <span style="color:#2B91AF">DDSConverter</span>();<br />
<br />
&nbsp;&nbsp;&nbsp; <span style="color:blue">public</span> <span style="color:blue">static</span>
<span style="color:#2B91AF">DDSConverter</span> Default<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:blue">get</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:blue">return</span> <span style="color:#2B91AF">DDSConverter</span>.defaultInstace;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; <span style="color:blue">public</span> <span style="color:blue">object</span>
Convert(<span style="color:blue">object</span> value, <span style="color:#2B91AF">Type</span>
targetType, <span style="color:blue">object</span> parameter, <span style="color: #2b91af;">CultureInfo</span> culture)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:blue">if</span> (value == <span style="color:blue">null</span>)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:blue">throw</span> <span style="color:blue">new</span>
<span style="color:#2B91AF">ArgumentNullException</span>(<span style="color: #a31515;">"value"</span>);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:blue">else</span> <span style="color:blue">if</span>
(value <span style="color:blue">is</span> <span style="color:#2B91AF">Stream</span>)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:blue">return</span> <span style="color:#2B91AF">DDSConverter</span>.Convert((<span style="color: #2b91af;">Stream</span>)value);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:blue">else</span> <span style="color:blue">if</span>
(value <span style="color:blue">is</span> <span style="color:blue">string</span>)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:blue">return</span> <span style="color:#2B91AF">DDSConverter</span>.Convert((<span style="color: blue;">string</span>)value);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:blue">else</span> <span style="color:blue">if</span>
(value <span style="color:blue">is</span> <span style="color:blue">byte</span>[])<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:blue">return</span> <span style="color:#2B91AF">DDSConverter</span>.Convert((<span style="color: blue;">byte</span>[])value);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:blue">else</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:blue">throw</span> <span style="color:blue">new</span>
<span style="color:#2B91AF">NotSupportedException</span>(<span style="color: blue;">string</span>.Format(<span style="color:#A31515">"{0}
cannot convert from {1}."</span>, <span style="color:blue">this</span>.GetType().FullName,
value.GetType().FullName));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; <span style="color:blue">public</span> <span style="color:blue">object</span>
ConvertBack(<span style="color:blue">object</span> value, <span style="color: #2b91af;">Type</span> targetType, <span style="color:blue">object</span>
parameter, <span style="color:#2B91AF">CultureInfo</span> culture)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:blue">throw</span> <span style="color:blue">new</span>
<span style="color:#2B91AF">NotSupportedException</span>(<span style="color: blue;">string</span>.Format(<span style="color:#A31515">"{0}
does not support converting back."</span>, <span style="color:blue">this</span>.GetType().FullName));<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; <span style="color:blue">public</span> <span style="color:blue">static</span>
<span style="color:#2B91AF">ImageSource</span> Convert(<span style="color:blue">string</span>
filePath)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:blue">using</span> (<span style="color:blue">var</span>
fileStream = <span style="color:#2B91AF">File</span>.OpenRead(filePath))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:blue">return</span> <span style="color:#2B91AF">DDSConverter</span>.Convert(fileStream);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; <span style="color:blue">public</span> <span style="color:blue">static</span>
<span style="color:#2B91AF">ImageSource</span> Convert(<span style="color:blue">byte</span>[]
imageData)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:blue">using</span> (<span style="color:blue">var</span>
memoryStream = <span style="color:blue">new</span> <span style="color:#2B91AF">MemoryStream</span>(imageData))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color:blue">return</span> <span style="color:#2B91AF">DDSConverter</span>.Convert(memoryStream);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; <span style="color:blue">public</span> <span style="color:blue">static</span>
<span style="color:#2B91AF">ImageSource</span> Convert(<span style="color:#2B91AF">Stream</span>
stream)<br />
&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #008000;">...</span><br />
&nbsp;&nbsp;&nbsp; }<br />
}</span></p>
<p class="MsoNormal"><span style="font-size:9.5pt;line-height:
115%;font-family:Consolas"><br /></span></p>
</div>
<p>Following is a simple usage example:</p>
<div class="Section1">
<p class="MsoNormal" style="margin-bottom:0in;margin-bottom:.0001pt;line-height:
normal;text-autospace:none"><span style="font-size:9.5pt;font-family:Consolas;
color:blue">&lt;</span><span style="font-size:9.5pt;font-family:Consolas;
color:#A31515">Image</span><span style="font-size:9.5pt;font-family:Consolas;
color:red"> Source</span><span style="font-size:9.5pt;font-family:Consolas;
color:blue">="{</span><span style="font-size:9.5pt;font-family:Consolas;
color:#A31515">Binding</span><span style="font-size:9.5pt;font-family:Consolas;
color:red"> Source</span><span style="font-size:9.5pt;font-family:Consolas;
color:blue">=Test.dds,</span><span style="font-size:9.5pt;font-family:Consolas;
color:red"> Converter</span><span style="font-size:9.5pt;font-family:Consolas;
color:blue">={</span><span style="font-size:9.5pt;font-family:Consolas;
color:#A31515">x</span><span style="font-size:9.5pt;font-family:Consolas;
color:blue">:</span><span style="font-size:9.5pt;font-family:Consolas;
color:#A31515">Static</span><span style="font-size:9.5pt;font-family:Consolas;
color:red"> local</span><span style="font-size:9.5pt;font-family:Consolas;
color:blue">:</span><span style="font-size:9.5pt;font-family:Consolas;
color:red">DDSConverter</span><span style="font-size:9.5pt;font-family:Consolas;
color:blue">.Default}}" /&gt;</span></p>
<p class="MsoNormal" style="margin-bottom:0in;margin-bottom:.0001pt;line-height:
normal;text-autospace:none"><span style="font-size:9.5pt;font-family:Consolas;
color:blue"><br /></span></p>
</div>
<p>My experience with XNA is limited (the XNA parts of the implementation above was achieved with the help of a former coworker), so it is entirely possible that the code provided could be improved. Again, the solution provided here is a quick, simple way to get DDS images displayed in WPF writing only managed code. As previously mentioned, implementing a DDS WIC codec would almost certainly be a more robust, long term solution, though also likely a heavier solution. I have no experience implementing WIC codecs, so if anyone wants to chime in on this I'd love to hear about it.</p>]]></content:encoded>
    </item>
    <item>
      <title>Globally updating binding sources in WPF</title>
      <link>https://docs.microsoft.com/archive/blogs/ryantrem/globally-updating-binding-sources-in-wpf</link>
      <pubDate>Thu, 08 Apr 2010 18:40:00 GMT</pubDate>
      <dc:creator><![CDATA[ryantrem]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/ryantrem/2010/04/08/globally-updating-binding-sources-in-wpf/</guid>
      <description><![CDATA[WPF data bindings do not always immediately update the source when the target (typically a WPF...]]></description>
      <content:encoded><![CDATA[<p>WPF data bindings do not always immediately update the source when the target (typically a WPF control, such as a TextBox) changes. An extremely common case of this is the default behavior of bindings on the Text property of a TextBox. Specifically, the UpdateSourceTrigger of bindings on this property is set to LostFocus by default. This means the source of the binding will be updated when the TextBox loses&nbsp;<em>logical</em> focus within its focus scope (see <a href="https://msdn.microsoft.com/en-us/library/aa969768.aspx#Logical_Focus">https://msdn.microsoft.com/en-us/library/aa969768.aspx#Logical_Focus</a>&nbsp;for an overview of logical focus and focus scopes in WPF). This means that there can be times when the source data is temporarily out of sync with the target (the control). In certain scenarios, this can result in unexpected data loss. A typical situation is as follows:</p>
<ol>
<li>Data is loaded from some data source</li>
<li>A TextBox is bound to that data</li>
<li>The Text of the TextBox is changed</li>
<li>A ToolBar Button, MenuItem, or shortcut key is invoked to submit the data back to the data source</li>
<li>The data source remains unchanged!</li>
</ol>
<p>Typically a ToolBar or a Menu has its own logical focus scope, and therefore interacting with them does not remove logical focus from the TextBox. If a shortcut key is pressed, this also typically will not remove logical focus from the TextBox. Since logical focus was not lost, the binding source was not updated, and so the seemingly changed data was not submitted back to the data source.</p>
<p>One simple solution is to exhaustively update all binding sources <em>before</em> submitting the data. This can be&nbsp;a bit tricky, so I'll walk through the code required for this.</p>
<p>First, I'll implement a couple DependencyObject&nbsp;extension methods that make traversing the visual tree simpler:</p>
<p class="MsoNormal"><span style="FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt">public</span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"> <span style="COLOR: blue">static</span> <span style="COLOR: #2b91af">IEnumerable</span>&lt;<span style="COLOR: #2b91af">DependencyObject</span>&gt; EnumerateVisualChildren(<span style="COLOR: blue">this</span> <span style="COLOR: #2b91af">DependencyObject</span> dependencyObject)<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt">{<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span><span style="COLOR: blue">for</span> (<span style="COLOR: blue">int</span> i = 0; i &lt; <span style="COLOR: #2b91af">VisualTreeHelper</span>.GetChildrenCount(dependencyObject); i++)<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span>{<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: blue">yield</span> <span style="COLOR: blue">return</span> <span style="COLOR: #2b91af">VisualTreeHelper</span>.GetChild(dependencyObject, i);<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span>}<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt">}</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><br /></span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"></span>
<p class="MsoNormal"><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"></span><span style="FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt">public</span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"> <span style="COLOR: blue">static</span> <span style="COLOR: #2b91af">IEnumerable</span>&lt;<span style="COLOR: #2b91af">DependencyObject</span>&gt; EnumerateVisualDescendents(<span style="COLOR: blue">this</span> <span style="COLOR: #2b91af">DependencyObject</span> dependencyObject)<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt">{<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span><span style="COLOR: blue">yield</span> <span style="COLOR: blue">return</span> dependencyObject;<br /></span><br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span><span style="COLOR: blue">foreach</span> (<span style="COLOR: #2b91af">DependencyObject</span> child <span style="COLOR: blue">in</span> dependencyObject.EnumerateVisualChildren())<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span>{<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: blue">foreach</span> (<span style="COLOR: #2b91af">DependencyObject</span> descendent <span style="COLOR: blue">in</span> child.EnumerateVisualDescendents())<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: blue">yield</span> <span style="COLOR: blue">return</span> descendent;<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span>}<br /></span><span style="LINE-HEIGHT: 115%; FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA">}</span></p>
<p class="MsoNormal"><span style="LINE-HEIGHT: 115%; FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"><br /></span></p>
<p class="MsoNormal"><span style="LINE-HEIGHT: 115%; FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"></span></p>
<p class="MsoNormal"><span style="LINE-HEIGHT: 115%; FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"></span>Next, I'll implement a DependencyObject extension method that updates the binding sources for all DependencyPropertys on that DependencyObject and all of its visual descendents:</p>
<p class="MsoNormal"><span style="FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt">public</span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"> <span style="COLOR: blue">static</span> <span style="COLOR: blue">void</span> UpdateBindingSources(<span style="COLOR: blue">this</span> <span style="COLOR: #2b91af">DependencyObject</span> dependencyObject)<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt">{<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span><span style="COLOR: blue">foreach</span> (<span style="COLOR: #2b91af">DependencyObject</span> element <span style="COLOR: blue">in</span> dependencyObject.EnumerateVisualDescendents())<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span>{<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: #2b91af">LocalValueEnumerator</span> localValueEnumerator = element.GetLocalValueEnumerator();<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: blue">while</span> (localValueEnumerator.MoveNext())<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #2b91af">BindingExpressionBase</span> bindingExpression = <span style="COLOR: #2b91af">BindingOperations</span>.GetBindingExpressionBase(element, localValueEnumerator.Current.Property);<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: blue">if</span> (bindingExpression != <span style="COLOR: blue">null</span>)<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>bindingExpression.UpdateSource();<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;</span>}<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span>}<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt">}</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><br /></span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"></span></p>
<p>All that's needed at this point is to invoke the UpdateBindingSources extension method on an appropriate DependencyObject (such as the top level Window) before submitting the data. This will ensure that the values in all binding targets have been pushed back to the binding sources. If the application in question has multiple Windows that should all have their binding sources updated, one more extension method may be useful:</p>
<p class="MsoNormal"><span style="FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt">public</span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"> <span style="COLOR: blue">static</span> <span style="COLOR: blue">void</span> UpdateBindingSources(<span style="COLOR: blue">this</span> <span style="COLOR: #2b91af">Application</span> application)<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt">{<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span><span style="COLOR: blue">foreach</span> (<span style="COLOR: #2b91af">Window</span> window <span style="COLOR: blue">in</span> application.Windows)<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span>{<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>window.UpdateBindingSources();<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span>}<br /></span><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt">}</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"><br /></span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"></span></p>
<p>Optionally, this extension method could be called before submitting the data: </p>
<p><span style="font-family: Consolas; color: #2b91af; font-size: x-small;"><span style="font-family: Consolas; color: #2b91af; font-size: x-small;"><span style="font-family: Consolas; color: #2b91af;"><span style="font-size: small;"></span></span></span></span></p>
<p><span style="font-size: small;"><span style="font-family: Consolas; color: #2b91af;"><span style="font-family: Consolas; color: #2b91af;"><span style="color: #2b91af;">Application</span></span></span><span style="font-family: Consolas;">.Current.UpdateBindingSources();</span></span></p>
<p><span style="font-family: Consolas; font-size: x-small;"><span style="font-family: Consolas; font-size: x-small;"></span></span></p>
<p>It probably seems like this could be incredibly slow, but in practice, I've found that this causes no noticeable delay in a medium sized application with a significant number of bindings. If this became a performance bottleneck, it might be possible to optimize specifically around the case of UpdateTrigger.LostFocus by carefully examining the WPF FocusManager to determine the actual set of elements that currently have logical focus and only updating binding sources on those elements.</p>
<p>It's also worth noting that this generic solution can be incorrect in certain binding scenarios. For example, an application might be using Bindings with the UpdateSourceTrigger set to Explicit and use some special criteria to decide when to commit the binding changes. Obviously in such a case, an indiscriminant call to the UpdateBindingSources extension method might thwart those efforts. Again, in practice I've found this generic solution to solve the underlying problem without significant side effects.</p>
<p>If you have an alternative solution to this problem, I'd love to hear about it. Other feedback is of course welcome as well.</p>
</p>]]></content:encoded>
    </item>
  </channel>
</rss>