<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-25127186</id><updated>2011-11-10T15:35:01.123+01:00</updated><category term='TT.DOM'/><category term='TT.DataForm'/><category term='Diagnose'/><category term='Community Projekte'/><category term='Konferenzen'/><category term='Veröffentlichungen'/><category term='TT.UIA'/><title type='text'>head.WriteLine()</title><subtitle type='html'>Wissenswertes über Silverlight, WPF, Windows Forms und SQL Server.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default?start-index=101&amp;max-results=100'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>149</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-25127186.post-6057727331817714287</id><published>2011-11-10T15:32:00.001+01:00</published><updated>2011-11-10T15:32:39.377+01:00</updated><title type='text'>Artikel über TT.UIA &amp; TT.DataForm in der aktuellen dotnetpro</title><content type='html'>&lt;p&gt;In der aktuellen Ausgabe der &lt;a href="http://dotnetpro.de/"&gt;dotnetpro&lt;/a&gt; (12/2011) ist mein Artikel “&lt;strong&gt;Kurz angemerkt: Aspektorientierte UI-Entwicklung mit Data Annotations&lt;/strong&gt;” erschienen. Dies ist der dritte Teil einer dreiteiligen Artikelserie in denen ich die technischen Aspekte von &lt;a href="http://uiannotations.codeplex.com/"&gt;Thinktecture UIAnnotations&lt;/a&gt; und &lt;a href="http://dataform.codeplex.com/"&gt;Thinktecture DataForm&lt;/a&gt; erkläre. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Aus dem Abstract: &lt;/strong&gt;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Moderne Softwareoberflächen sollen ansprechend, einheitlich und einfach zu bedienen sein. Eine große Herausforderung – zumal längst nicht jeder Entwickler auch ein guter UI-Designer ist. Metadaten bieten die Möglichkeit, Oberflächen zur Laufzeit nach einheitlichen Richtlinien zu erzeugen, und erlauben es darüber hinaus, die Anzeige zu lokalisieren und Eingaben zu prüfen.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;a href="http://dotnetpro.de/"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="dnp_122011" border="0" alt="dnp_122011" src="http://lh3.ggpht.com/-nfrj0072z9M/TrvghnaNcGI/AAAAAAAAAVk/zgWnozdhRCI/dnp_122011%25255B3%25255D.jpg?imgmax=800" width="134" height="188" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-6057727331817714287?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/6057727331817714287/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=6057727331817714287' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/6057727331817714287'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/6057727331817714287'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2011/11/artikel-uber-ttuia-ttdataform-in-der.html' title='Artikel über TT.UIA &amp;amp; TT.DataForm in der aktuellen dotnetpro'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/-nfrj0072z9M/TrvghnaNcGI/AAAAAAAAAVk/zgWnozdhRCI/s72-c/dnp_122011%25255B3%25255D.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-5454318230675616955</id><published>2011-10-22T12:44:00.001+02:00</published><updated>2011-10-22T12:44:55.218+02:00</updated><title type='text'>Artikel über TT.UIA in der aktuellen dotnetpro</title><content type='html'>In der aktuellen Ausgabe der &lt;a href="http://www.dotnetpro.de/"&gt;dotnetpro&lt;/a&gt; (11/2011) ist mein Artikel “&lt;strong&gt;Sauber getrennt und gekapselt – Aspektorientierte UI-Entwicklung mit Behaviors&lt;/strong&gt;” erschienen. Dies ist der zweite Teil einer dreiteiligen Artikelserie in denen ich die technischen Aspekte von &lt;a href="http://uiannotations.codeplex.com/"&gt;Thinktecture UIAnnotations&lt;/a&gt; erkläre.  &lt;br /&gt;&lt;strong&gt;Aus dem Abstract:&lt;/strong&gt;  &lt;br /&gt;  &lt;blockquote&gt;   &lt;p&gt;Das Entwurfsmuster MVVM trennt klar zwischen Oberfläche und Logik. Um auch noch die UI-Interaktionslogik in wiederverwendbare Form zu bringen, per Markup zuweisbar zu machen und trotzdem noch MVVM-konform zu bleiben, sind Behaviors und Trigger das richtige Mittel. dotnetpro zeigt, wie sie funktionieren.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;a href="http://dotnetpro.de/"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="dnp_112011" border="0" alt="dnp_112011" src="http://lh6.ggpht.com/--etZCcROgII/TqKepkSN_OI/AAAAAAAAAVM/4_qSTkcfeoY/dnp_112011%25255B4%25255D.jpg?imgmax=800" width="134" height="188" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-5454318230675616955?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/5454318230675616955/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=5454318230675616955' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/5454318230675616955'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/5454318230675616955'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2011/10/artikel-uber-ttuia-in-der-aktuellen.html' title='Artikel über TT.UIA in der aktuellen dotnetpro'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/--etZCcROgII/TqKepkSN_OI/AAAAAAAAAVM/4_qSTkcfeoY/s72-c/dnp_112011%25255B4%25255D.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-2943561148609848118</id><published>2011-10-01T12:01:00.001+02:00</published><updated>2011-10-01T12:01:04.447+02:00</updated><title type='text'>Slides &amp; Samples von der BASTA!</title><content type='html'>&lt;p&gt;Die &lt;a href="http://basta.net/"&gt;BASTA!&lt;/a&gt; hat wieder mächtig Spaß gemacht. Einen Dank an die Teilnehmer meiner Sessions! Hier das Material:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="https://skydrive.live.com/?cid=4029b6652bf3f13f&amp;amp;sc=documents&amp;amp;uc=3&amp;amp;id=4029B6652BF3F13F%21202#"&gt;Aspektorientierte UI-Entwicklung mit WPF und Silverlight&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="https://skydrive.live.com/?cid=4029b6652bf3f13f&amp;amp;sc=documents&amp;amp;uc=3&amp;amp;id=4029B6652BF3F13F%21202#"&gt;MVVM: Advanced Topics&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="https://skydrive.live.com/?cid=4029b6652bf3f13f&amp;amp;sc=documents&amp;amp;uc=3&amp;amp;id=4029B6652BF3F13F%21202#"&gt;Sicherheitsarchitekturen für Clientanwendungen&lt;/a&gt;      &lt;br /&gt;(zusammen mit &lt;a href="http://www.leastprivilege.com/"&gt;Dominick Baier&lt;/a&gt;)      &lt;br /&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-2943561148609848118?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/2943561148609848118/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=2943561148609848118' title='1 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/2943561148609848118'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/2943561148609848118'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2011/10/slides-samples-von-der-basta.html' title='Slides &amp;amp; Samples von der BASTA!'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-6446210437102364997</id><published>2011-09-19T13:07:00.001+02:00</published><updated>2011-09-19T13:07:17.352+02:00</updated><title type='text'>Die BASTA! geht wieder auf Tour</title><content type='html'>&lt;p&gt;Zum zweiten Mal in diesem Jahr geht die BASTA! auf &lt;a href="http://basta-on-tour.de/"&gt;Tour&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Vom 21.-23. November geht es in Düsseldorf wieder um “Architecture &amp;amp; Good Practices”.&lt;/p&gt;  &lt;blockquote&gt;   &lt;h4&gt;Architektur, WPF, WCF, Entity Framework, jQuery, ASP.NET...&lt;/h4&gt;    &lt;p&gt;Die BASTA! on Tour - Architecture &amp;amp; Good Practices ist das Tochterevent der BASTA! - der größten unabhängigen .NET-Konferenz im deutschsprachigen Raum. Drei Tage lang bietet Ihnen dieses große Trainingsevent insgesamt sechs Power Workshops, acht Sessions und ein Speaker Panel zu den Themen Architektur und Best Practices in der .NET-Entwicklung. Die BASTA! on Tour richtet sich an Softwarearchitekten, Projektleiter und Entwickler, die erstklassiges Know-how für geschäftskritische Projekte erhalten möchten… (mehr gibt’s &lt;a href="http://basta-on-tour.de/"&gt;hier&lt;/a&gt;)&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Ich übernehme dabei wieder die Client-Themen:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://entwickler.com/konferenzen/ext_scripts/v2/php/sessions-popup.php?module=bastaontour2011fall&amp;amp;id=20166"&gt;WPF &amp;amp; Silverlight Architecture Patterns&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://entwickler.com/konferenzen/ext_scripts/v2/php/sessions-popup.php?module=bastaontour2011fall&amp;amp;id=20173"&gt;Erweiterbare Anwendungen mit WPF, Silverlight und MEF entwicklen&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Darüber hinaus bestreite ich einen ganztägigen &lt;a href="http://entwickler.com/konferenzen/ext_scripts/v2/php/sessions-popup.php?module=bastaontour2011fall&amp;amp;id=20161"&gt;Workshop&lt;/a&gt; über die WPF. Am dritten Tag gibt es diesmal zwei zusätzliche &lt;a href="http://basta-on-tour.de/2011fall/workshops/"&gt;Workshops&lt;/a&gt;, in denen je einen Web und eine Desktop-Anwendung live entwickelt werden. &lt;/p&gt;  &lt;p&gt;Vielleicht sieht man sich ja :)&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-6446210437102364997?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/6446210437102364997/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=6446210437102364997' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/6446210437102364997'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/6446210437102364997'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2011/09/die-basta-geht-wieder-auf-tour.html' title='Die BASTA! geht wieder auf Tour'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-7113266333207535579</id><published>2011-09-19T12:56:00.001+02:00</published><updated>2011-09-19T12:56:16.227+02:00</updated><title type='text'>Slides &amp; Samples von der NRWConf</title><content type='html'>&lt;p&gt;Die &lt;a href="http://nrwconf.de/de/"&gt;NRWConf&lt;/a&gt; hat auch in diesem Jahr wieder mächtig Spaß gemacht. Einen Dank an die Teilnehmer meiner Session! Hier das Material:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="https://skydrive.live.com/?cid=4029b6652bf3f13f&amp;amp;sc=documents&amp;amp;id=4029B6652BF3F13F%21200#"&gt;Dynamische UI-Generierung mit WPF und Silverlight&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-7113266333207535579?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/7113266333207535579/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=7113266333207535579' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/7113266333207535579'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/7113266333207535579'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2011/09/slides-samples-von-der-nrwconf.html' title='Slides &amp;amp; Samples von der NRWConf'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-7557695171823317150</id><published>2011-08-25T07:47:00.000+02:00</published><updated>2011-08-25T07:47:09.940+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TT.DataForm'/><title type='text'>TT.DataForm: MVVM Support</title><content type='html'>Bei der Entwicklung von &lt;a href="http://dataform.codeplex.com/"&gt;TT.DataForm&lt;/a&gt; habe ich besonderen Wert auf den MVVM-Support gelegt. Dies betrifft sowohl die Datenbindung, als auch die Operationen die der Benutzer über die Oberfläche auslösen kann. Hierfür stehen entsprechende Command-Eigenschaften bereit, mit denen einen ViewModel das Control steuern kann.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;AddCommand&lt;/strong&gt;: Legt einen Command für die Neuanlage eines Datensatzes fest. &lt;/li&gt;&lt;li&gt;&lt;strong&gt;RemoveCommand&lt;/strong&gt;: Legt einen Command für das Entfernen von Datensätzen fest. &lt;/li&gt;&lt;li&gt;&lt;strong&gt;SelectionButtonCommand&lt;/strong&gt;: Legt den Command für die Auswahlschaltfläche von Bildern fest. &lt;/li&gt;&lt;/ul&gt;Für die Navigation stehen keine separaten Commands zu Verfügung, da diese idealerweise über eine entsprechende die Datenquellen-View, wie &lt;strong&gt;ICollectionView&lt;/strong&gt; oder &lt;strong&gt;IEditableCollectionView&lt;/strong&gt; gesteuert werden können.&lt;br /&gt;&lt;br /&gt;In manchen Fällen muss das ViewModel jedoch aktiv mit der DataForm kommunizieren. So sollte zum Beispiel vor dem Speichern der Änderungen die aktive Eingabe abgeschlossen werden, um den gerade eingegebenen Wert in die Datenquelle zu übertragen. Hierfür stellt DataForm die Methode &lt;em&gt;AcceptChanges()&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;Da das ViewModel jedoch nicht direkt mit der Komponente kommunizieren kann, werden die wichtigsten Methoden in einem so genannten &lt;strong&gt;ActionCommand&lt;/strong&gt; abstrahiert. Hierbei stellt das ViewModel eine Eigenschaft vom Typ ActionCommand zu Verfügung, die an die gleichnamige Eigenschaft der DataForm gebunden wird. Daraufhin kann das ViewModel über die &lt;strong&gt;ExecuteAction()&lt;/strong&gt;-Methode die entsprechende Methode auf dem Command aufrufen, welche daraufhin an die DataForm weitergeleitet wird. &lt;strong&gt;ExcuteAction()&lt;/strong&gt; nimmt den Typ der Methode in Form eines Wertes der &lt;strong&gt;DataFormAction&lt;/strong&gt;-Enumeration entgegen. Die folgenden Werte stehen hierbei zu Verfügung:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;AcceptChanges&lt;/strong&gt;: Übernimmt die über die Oberfläche durchgeführten Änderungen. &lt;/li&gt;&lt;li&gt;&lt;strong&gt;DetachDataSource&lt;/strong&gt;: Entfernt die Datenquelle und die zugehörigen UI-Elemente aus dem Control. &lt;/li&gt;&lt;li&gt;&lt;strong&gt;Reset&lt;/strong&gt;: Erstellt die Oberfläche anhand Datenquelle neu. &lt;/li&gt;&lt;li&gt;&lt;strong&gt;SetBusy&lt;/strong&gt;: Sperrt die Oberfläche und blendet den BusyIndicator ein. &lt;/li&gt;&lt;li&gt;&lt;strong&gt;SetAvailable&lt;/strong&gt;: Blendet den BusyIndicator aus und entsperrt die Oberfläche. &lt;/li&gt;&lt;/ul&gt;Das folgende Beispiel demonstriert die Anwendung:&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;View:&lt;/strong&gt;&lt;br /&gt;&lt;span style="font-family: Consolas;"&gt;&amp;lt;dataform:DataForm      &lt;br /&gt;&amp;nbsp; ActionCommand="{Binding ActionCommand}" /&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;ViewModel:&lt;/strong&gt;&lt;br /&gt;&lt;span style="font-family: Consolas;"&gt;…      &lt;br /&gt;public ActionCommand ActionCommand { get; set; }       &lt;br /&gt;…       &lt;br /&gt;private void SaveChanges()       &lt;br /&gt;{       &lt;br /&gt;&amp;nbsp; this.ActionCommand.ExecuteAction(       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DataFormAction.AcceptChanges, null);       &lt;br /&gt;&amp;nbsp; this.ActionCommand.ExecuteAction(       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DataFormAction.SetBusy, null);       &lt;br /&gt;&amp;nbsp; …       &lt;br /&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Der Wert &lt;strong&gt;DataFormAction.SetBusy&lt;/strong&gt; bewirkt hierbei, dass alle Eingabefelder deaktiviert werden und der eingebaute BusyIndicator eingeblendet wird.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://lh6.ggpht.com/-pS5VTYaOSUQ/Tk0V7sgCBqI/AAAAAAAAAUw/Ul181x7-hWc/s1600-h/BusyIndicator9.png"&gt;&lt;img alt="BusyIndicator" border="0" height="490" src="http://lh4.ggpht.com/-ScNX-QqEJCc/Tk0V8fKdvNI/AAAAAAAAAU0/btuklw8KE3A/BusyIndicator_thumb5.png?imgmax=800" style="background-image: none; border-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="BusyIndicator" width="442" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Der Wert &lt;strong&gt;DataFormAction.SetAvailable&lt;/strong&gt; beendet die Animation wieder. &lt;br /&gt;&lt;br /&gt;Zusätzlich bietet &lt;a href="http://dataform.codeplex.com/"&gt;TT.DataForm&lt;/a&gt; die folgenden Eigenschaften, mit denen das Verhalten der Oberfläche konfiguriert werden kann.&lt;br /&gt;&lt;br /&gt;&lt;table border="1" cellpadding="2" cellspacing="0" style="width: 471px;"&gt;&lt;tbody&gt;&lt;tr&gt;       &lt;td valign="top" width="163"&gt;&lt;strong&gt;Eigenschaft&lt;/strong&gt;&lt;/td&gt;        &lt;td valign="top" width="306"&gt;&lt;strong&gt;Beschreibung&lt;/strong&gt;&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td valign="top" width="163"&gt;AllowAddNew&lt;/td&gt;        &lt;td valign="top" width="306"&gt;Bestimmt, die Neuanlage eines Datensatzes über das Steuerelement möglich sein soll.&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td valign="top" width="163"&gt;AllowRemove&lt;/td&gt;        &lt;td valign="top" width="306"&gt;Bestimmt, das Entfernen eines Datensatzes über das Steuerelement möglich sein soll.&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td valign="top" width="163"&gt;IsReadOnly&lt;/td&gt;        &lt;td valign="top" width="306"&gt;Bestimmt, ob das Steuerelement schreibgeschützt dargestellt werden soll.&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td valign="top" width="163"&gt;Error&lt;/td&gt;        &lt;td valign="top" width="306"&gt;Liefert den aktuellen Eigabefehler oder einen Leerstring zurück.&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td valign="top" width="163"&gt;HasError&lt;/td&gt;        &lt;td valign="top" width="306"&gt;Ruft ab, ob der aktuelle Datensatz Eingabefehler enthält.&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td valign="top" width="163"&gt;IsBusy&lt;/td&gt;        &lt;td valign="top" width="306"&gt;Legt fest, ob der Busy Indicator angezeigt werden soll.&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td valign="top" width="163"&gt;BusyIndicatorType&lt;/td&gt;        &lt;td valign="top" width="306"&gt;Legt den Typ des Busy Indicators fest. Zur Auswahl stehen &lt;em&gt;Wheel&lt;/em&gt;, &lt;em&gt;Dots&lt;/em&gt; und Custom. Bei letzterem Wert muss über die Eigenschaft &lt;em&gt;BusyIndicatorTemplate&lt;/em&gt; ein benutzerdefiniertes Template bereitgestellt werden.&lt;/td&gt;     &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;Das Beispielprojekt, das in den Sourcen von &lt;a href="http://dataform.codeplex.com/"&gt;TT.DataForm&lt;/a&gt; enthalten ist, zeigt die Verwendung der verschiedenen Mechanismen in einem MVVM-Szenario.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-7557695171823317150?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/7557695171823317150/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=7557695171823317150' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/7557695171823317150'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/7557695171823317150'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2011/08/ttdataform-mvvm-support.html' title='TT.DataForm: MVVM Support'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/-ScNX-QqEJCc/Tk0V8fKdvNI/AAAAAAAAAU0/btuklw8KE3A/s72-c/BusyIndicator_thumb5.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-7577066451834166220</id><published>2011-08-24T07:59:00.001+02:00</published><updated>2011-08-24T08:00:13.503+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TT.DataForm'/><title type='text'>TT.DataForm: UI Customizing</title><content type='html'>In diesem Post soll es um die Anpassung der einzelnen UI-Bestandteile von &lt;a href="http://dataform.codeplex.com/"&gt;TT.DataForm&lt;/a&gt; gehen.&lt;br /&gt;&lt;a href="http://dataform.codeplex.com/"&gt;TT.DataForm&lt;/a&gt; besteht aus einer Reihe von Unterkomponenten, die über Styles und Templates separat angepasst werden können. Hierzu zählen:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;DataFormHeader&lt;/strong&gt;: Der Kopfbereich des Controls (Titel, Navigation) &lt;/li&gt;&lt;li&gt;&lt;strong&gt;Marker&lt;/strong&gt;: Markierungssymbole (aktives Feld, geändertes Feld, Pflichtfeld, Fehler) &lt;/li&gt;&lt;li&gt;&lt;strong&gt;DataFormItem&lt;/strong&gt;: Ein Feldzeile mit Bezeichner, Eingabeelement, sowie den Markern. &lt;/li&gt;&lt;li&gt;&lt;strong&gt;DataFormFooter&lt;/strong&gt;: Der Fußbereich des Controls (Beschreibungstext, Fehlertext). &lt;/li&gt;&lt;li&gt;&lt;strong&gt;BusyIndicator&lt;/strong&gt;: Der eingebaute BusyIndicator der DataForm. &lt;/li&gt;&lt;/ul&gt;Die folgende Abbildung zeigt den internen Aufbau:&lt;a href="http://www.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=dataform&amp;amp;DownloadId=270924"&gt;&lt;img alt="TTDataFormCustomizing" border="0" height="348" src="http://lh3.ggpht.com/-GBgs0o8jCmI/Tk0V04MqguI/AAAAAAAAAUs/MJV5UX1iq0Q/TTDataFormCustomizing12.png?imgmax=800" style="background-image: none; border-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="TTDataFormCustomizing" width="469" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Hierbei beschreiben die gelben Kästchen die jeweilige Komponente mit ihren Eigenschaften, während die grünen Kästchen die zugehörigen DataForm-Eigenschaften kennzeichnen, mit denen Anpassungen vorgenommen werden können.&lt;br /&gt;&lt;br /&gt;Um beispielsweise die Symbole der Navigationsleiste zu ändern, können über &lt;strong&gt;HeaderStyle&lt;/strong&gt; die Eigenschaften des &lt;strong&gt;DataFormHeader&lt;/strong&gt;-Objekts verändert werden.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: Consolas;"&gt;&amp;lt;dataform:DataForm x:Name="personDataForm"&amp;gt;      &lt;br /&gt;&amp;nbsp; &amp;lt;dataform:DataForm.HeaderStyle&amp;gt;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Style TargetType="dataform:DataFormHeader"&amp;gt;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Setter Property="Background"       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Value="LightYellow" /&amp;gt;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Setter Property="MoveFirstImage"       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Value="/Images/Navigation_First.png" /&amp;gt;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Setter Property="MovePreviousImage"       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Value="/Images/Navigation_Previous.png" /&amp;gt;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Setter Property="MoveNextImage"       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Value="/Images/Navigation_Next.png" /&amp;gt;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Setter Property="MoveLastImage"       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Value="/Images/Navigation_Last.png" /&amp;gt;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Setter Property="AddImage"       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Value="/Images/New.png" /&amp;gt;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Setter Property="RemoveImage"       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Value="/Images/Delete.png" /&amp;gt;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Style&amp;gt;       &lt;br /&gt;&amp;nbsp; &amp;lt;/dataform:DataForm.HeaderStyle&amp;gt;       &lt;br /&gt;&amp;lt;/dataform&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Darüber hinaus stehen eine Reihe allgemeiner Eigenschaften bereit, mit denen grundsätzliche Entscheidungen des Erscheinungsbilds festgelegt werden können. Die folgende Tabelle zeigt die hierfür wichtigsten Einstellungen:&lt;br /&gt;&lt;br /&gt;&lt;table border="1" cellpadding="2" cellspacing="0" style="width: 471px;"&gt;&lt;tbody&gt;&lt;tr&gt;       &lt;td valign="top" width="134"&gt;&lt;strong&gt;Eigenschaft&lt;/strong&gt;&lt;/td&gt;        &lt;td valign="top" width="335"&gt;&lt;strong&gt;Beschreibung&lt;/strong&gt;&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td valign="top" width="134"&gt;RowHeight&lt;/td&gt;        &lt;td valign="top" width="335"&gt;Bestimmt die Höhe einer Feldzeile.&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td valign="top" width="134"&gt;ColumnSpacing&lt;/td&gt;        &lt;td valign="top" width="335"&gt;Bestimmt den Abstand zwischen Anzeigetext und Eingabesteuerelement.&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td valign="top" width="134"&gt;ColumnCount&lt;/td&gt;        &lt;td valign="top" width="335"&gt;Legt die Anzahl der anzuzeigenden Spalten fest.&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td valign="top" width="134"&gt;ShowHeader&lt;/td&gt;        &lt;td valign="top" width="335"&gt;Bestimmt, ob der Kopfbereich angezeigt werden soll.&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td valign="top" width="134"&gt;ShowFooter&lt;/td&gt;        &lt;td valign="top" width="335"&gt;Bestimmt, ob der Fußbereich angezeigt werden soll.&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td valign="top" width="134"&gt;ShowEditTracker&lt;/td&gt;        &lt;td valign="top" width="335"&gt;Bestimmt, ob das Symbol für geänderte Felder angezeigt werden soll.&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td valign="top" width="134"&gt;ShowRowMarker&lt;/td&gt;        &lt;td valign="top" width="335"&gt;Bestimmt, ob das Symbol für das aktuell fokussierte Felder angezeigt werden soll.&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td valign="top" width="134"&gt;ShowRequiredFieldMarker&lt;/td&gt;        &lt;td valign="top" width="335"&gt;Bestimmt, ob das Symbol für Pflichtfelder angezeigt werden soll.&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td valign="top" width="134"&gt;ShowErrorMarker&lt;/td&gt;        &lt;td valign="top" width="335"&gt;Bestimmt, ob das Symbol für Eingabefehler angezeigt werden soll.&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td valign="top" width="134"&gt;CornerRadius&lt;/td&gt;        &lt;td valign="top" width="335"&gt;Legt den Radius des äußeren Rahmens fest.&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td valign="top" width="134"&gt;ShowDropShadow&lt;/td&gt;        &lt;td valign="top" width="335"&gt;Zeichnet einen Schatteneffekt für das Steuerelement.&lt;/td&gt;     &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;Noch mehr Beispiele für die Anpassungsmöglichkeiten finden Sie im Demoprojekt, das den Sourcen von &lt;a href="http://dataform.codeplex.com/"&gt;TT.DataForm&lt;/a&gt; beiliegt.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-7577066451834166220?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/7577066451834166220/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=7577066451834166220' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/7577066451834166220'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/7577066451834166220'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2011/08/ttdataform-ui-customizing.html' title='TT.DataForm: UI Customizing'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/-GBgs0o8jCmI/Tk0V04MqguI/AAAAAAAAAUs/MJV5UX1iq0Q/s72-c/TTDataFormCustomizing12.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-2080034393868490975</id><published>2011-08-23T08:12:00.002+02:00</published><updated>2011-08-24T07:58:12.026+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TT.DataForm'/><title type='text'>TT.DataForm: Mappings</title><content type='html'>Nachdem ich &lt;a href="http://headwriteline.blogspot.com/2011/08/ttdataform-data-binding_22.html"&gt;hier&lt;/a&gt; bereits die Data Binding-Mechanismen von &lt;a href="http://dataform.codeplex.com/"&gt;TT.DataForm&lt;/a&gt; beschrieben habe, soll es in diesem Post um die Anpassung der UI-Generierung gehen. Hierfür stehen zwei Modelle zu Verfügung: &lt;strong&gt;Control Mappings&lt;/strong&gt; und &lt;strong&gt;Item Definitions&lt;/strong&gt;.&lt;br /&gt;&lt;h4&gt;Control Mappings&lt;/h4&gt;Mit den Control Mappings kann konfiguriert werden, in welcher Form die zu Verfügung gestellten Daten in UI-Elemente umgesetzt werden sollen. Standardmäßig verfolgt &lt;a href="http://dataform.codeplex.com/"&gt;TT.DataForm&lt;/a&gt; das folgende Mapping:&lt;br /&gt;&lt;br /&gt;&lt;table border="1" cellpadding="2" cellspacing="0" style="width: 400px;"&gt;&lt;tbody&gt;&lt;tr&gt;         &lt;td valign="top" width="200"&gt;&lt;strong&gt;Datentyp&lt;/strong&gt;&lt;/td&gt;          &lt;td valign="top" width="200"&gt;&lt;strong&gt;Input Control&lt;/strong&gt;&lt;/td&gt;       &lt;/tr&gt;&lt;tr&gt;         &lt;td valign="top" width="200"&gt;int, double, decimal&lt;/td&gt;          &lt;td valign="top" width="200"&gt;NumericUpDown&lt;/td&gt;       &lt;/tr&gt;&lt;tr&gt;         &lt;td valign="top" width="200"&gt;string &lt;/td&gt;          &lt;td valign="top" width="200"&gt;TextBox&lt;/td&gt;       &lt;/tr&gt;&lt;tr&gt;         &lt;td valign="top" width="200"&gt;DateTime &lt;/td&gt;          &lt;td valign="top" width="200"&gt;DatePicker&lt;/td&gt;       &lt;/tr&gt;&lt;tr&gt;         &lt;td valign="top" width="200"&gt;bool &lt;/td&gt;          &lt;td valign="top" width="200"&gt;CheckBox&lt;/td&gt;       &lt;/tr&gt;&lt;tr&gt;         &lt;td valign="top" width="200"&gt;ImageSource &lt;/td&gt;          &lt;td valign="top" width="200"&gt;Image&lt;/td&gt;       &lt;/tr&gt;&lt;tr&gt;         &lt;td valign="top" width="200"&gt;Sonstige&lt;/td&gt;          &lt;td valign="top" width="200"&gt;TextBlock&lt;/td&gt;       &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;Um dieses Mapping anzupassen, können &lt;strong&gt;ControlMapping&lt;/strong&gt;-Objekte definiert und über die &lt;strong&gt;ControlMapping&lt;/strong&gt;-Eigenschaft zugewiesen werden. Hierbei stehen die folgenden Möglichkeiten zu Verfügung:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Mapping auf Feldebene &lt;/li&gt;&lt;li&gt;Mapping auf Datentypebene &lt;/li&gt;&lt;li&gt;Definition eines &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.datatemplate.aspx"&gt;DataTemplate&lt;/a&gt; &lt;/li&gt;&lt;li&gt;Angabe von Metadaten &lt;/li&gt;&lt;/ul&gt;Hier ein paar Beispiele:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: Consolas;"&gt;&amp;lt;dataform:DataForm.ControlMappings&amp;gt;      &lt;br /&gt;&amp;nbsp; &amp;lt;dataform:ControlMapping ControlType="{x:Type TextBox}"       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; BindingPropertyName="Text"       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DataPropertyName="Id" /&amp;gt;       &lt;br /&gt;&amp;nbsp; &amp;lt;dataform:ControlMapping DataType="{x:Type sys:String}"       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ControlType="{x:Type TextBlock}"       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; BindingPropertyName="Text" /&amp;gt;       &lt;br /&gt;&amp;nbsp; &amp;lt;dataform:ControlMapping DataType="{x:Type sys:DateTime}"       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IsReadOnly="True"       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Description="The birthday."&amp;gt;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;dataform:ControlMapping.ColumnTemplate&amp;gt;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;DataTemplate&amp;gt;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;TextBox Text="{Binding Path=Birthday,       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; StringFormat={}{0:dd. MMMM yyyy}}"       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IsReadOnly="False" /&amp;gt;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/DataTemplate&amp;gt;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/dataform:ControlMapping.ColumnTemplate&amp;gt;       &lt;br /&gt;&amp;nbsp; &amp;lt;/dataform:ControlMapping&amp;gt;       &lt;br /&gt;&amp;lt;/dataform:DataForm.ControlMappings&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In diesem Beispiel wurde festgelegt, dass die Eigenschaft &lt;em&gt;Id&lt;/em&gt; als &lt;em&gt;TextBox&lt;/em&gt; (statt als &lt;em&gt;NumericUpDown&lt;/em&gt;) gerendert und hierbei die &lt;em&gt;Text&lt;/em&gt;-Eigenschaft gebunden werden soll. Darüber hinaus wurde festgelegt, dass alle Eigenschaften vom Typ &lt;em&gt;string&lt;/em&gt; in Form von &lt;em&gt;TextBlock&lt;/em&gt; (statt &lt;em&gt;TextBox&lt;/em&gt;) dargestellt werden. Für den Datentyp &lt;em&gt;DateTime&lt;/em&gt; wurde zusätzlich festgelegt, dass alle Felder des Typs schreibgeschützt dargestellt werden sollen. Diese Art der Metadatenangabe kann sinnvoll sein, wenn die Datenquelle nicht mit &lt;a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.aspx"&gt;Data Annotations&lt;/a&gt; attributiert wurde, bzw. die Angaben überschrieben werden soll. Zuletzt wurde für das Feld &lt;em&gt;Birthday&lt;/em&gt; ein eigenes &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.datatemplate.aspx"&gt;DataTemplate&lt;/a&gt; definiert. Dies kann dann sinnvoll sein, wenn das zu erzeugende UI-Control speziell konfiguriert oder das Binding zum Beispiel mit einem &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.data.ivalueconverter.aspx"&gt;ValueConverter&lt;/a&gt; versehen werden muss.&lt;br /&gt;&lt;h4&gt;Item Definitions&lt;/h4&gt;Die Item Definitions erfüllen im Grunde den gleichen Zweck wie die Control Mappings, erlauben hierbei jedoch weitaus mehr Anpassungsmöglichkeiten. So kann zum Beispiel nicht nur das Eingabeelement, sondern auch das Anzeigeelement festgelegt werden. Darüber hinaus können Item Definitions sowohl für gebundene, als auch für ungebundene Felder definiert werden. Das bedeutet, dass die Oberfläche zum Beispiel ein Notizfeld enthalten kann, obwohl die Datenquelle keine entsprechende Eigenschaft bereitstellt.&lt;br /&gt;Die Erstellung von Item Definitions erfolgt über die Eigenschaft &lt;strong&gt;DataFormItems&lt;/strong&gt;. Hierüber können ein oder mehrere &lt;strong&gt;DataFormItem&lt;/strong&gt;-Objekte zugewiesen werden. Diese bestimmen über die Eigenschaften &lt;strong&gt;Header&lt;/strong&gt; und &lt;strong&gt;Content&lt;/strong&gt; den Anzeigetext bzw. das zu verwendende Eingabeelement.&lt;br /&gt;Hier ein Beispiel für die Definition von Item Definitions:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: Consolas;"&gt;&amp;lt;dataform:DataForm.DataFormItems&amp;gt;      &lt;br /&gt;&amp;nbsp; &amp;lt;dataform:DataFormItem Header="ID:"&amp;gt;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;dataform:DataFormItem.Content&amp;gt;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;controls:NumericUpDown Width="100"       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="font-family: Consolas;"&gt;HorizontalAlignment="Left"      &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Value="{Binding Path=Id, ValidatesOnDataErrors=True}"/&amp;gt;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/dataform:DataFormItem.Content&amp;gt;       &lt;br /&gt;&amp;nbsp; &amp;lt;/dataform:DataFormItem&amp;gt;       &lt;br /&gt;&amp;nbsp; &amp;lt;dataform:DataFormItem&amp;gt;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;dataform:DataFormItem.Header&amp;gt;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;TextBlock Text="Name:" /&amp;gt;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/dataform:DataFormItem.Header&amp;gt;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;dataform:DataFormItem.Content&amp;gt;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;TextBox Text="{Binding Path=Name}" /&amp;gt;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/dataform:DataFormItem.Content&amp;gt;       &lt;br /&gt;&amp;nbsp; &amp;lt;/dataform:DataFormItem&amp;gt;       &lt;br /&gt;&amp;lt;/dataform:DataForm.DataFormItems&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Wie zu sehen ist, kann die &lt;strong&gt;Header&lt;/strong&gt;-Eigenschaft entweder mit einem einfachen Text, oder mit einem beliebigem Control gefüllt werden.&lt;br /&gt;&lt;br /&gt;Im nächsten Post geht es um die grafischen Anpassungsmöglichkeiten von &lt;a href="http://dataform.codeplex.com/"&gt;TT.DataForm&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-2080034393868490975?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/2080034393868490975/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=2080034393868490975' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/2080034393868490975'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/2080034393868490975'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2011/08/ttdataform-mappings.html' title='TT.DataForm: Mappings'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-5605829769621404236</id><published>2011-08-22T10:59:00.002+02:00</published><updated>2011-08-22T11:00:09.089+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TT.DataForm'/><title type='text'>TT.DataForm: Data Binding</title><content type='html'>Nach der kurzen Einführung &lt;a href="http://headwriteline.blogspot.com/2011/08/just-released-thinktecture-dataform.html"&gt;hier&lt;/a&gt;, gehe ich in den folgenden Posts näher auf die Features von &lt;a href="http://dataform.codeplex.com/"&gt;TT.DataForm&lt;/a&gt; ein. Den Anfang mache ich mit dem Thema Data Binding.  &lt;br /&gt;&lt;h4&gt;Datenquellen&lt;/h4&gt;Eine Datenquelle bindet man an &lt;a href="http://dataform.codeplex.com/"&gt;TT.DataForm&lt;/a&gt; über die Eigenschaft &lt;strong&gt;DataSource&lt;/strong&gt;. Hierbei kann eine beliebige Datenquelle angegeben werden – unabhängig davon ob es sich um eine einzelnes Objekt oder eine Liste handelt. Die folgenden Datentypen werden hierbei unterstützt:  &lt;br /&gt;&lt;ul&gt;&lt;li&gt;System.Object &lt;/li&gt;&lt;li&gt;System.Type &lt;/li&gt;&lt;li&gt;IEnumerable &lt;/li&gt;&lt;li&gt;ICollectionView &lt;/li&gt;&lt;li&gt;CollectionViewSource &lt;/li&gt;&lt;li&gt;ListCollectionView &lt;/li&gt;&lt;/ul&gt;Darüber hinaus kann &lt;a href="http://dataform.codeplex.com/"&gt;TT.DataForm&lt;/a&gt; auch mit dem Data Source Windows von Visual Studio verknüpft werden, dass ein direktes Einfügen aus der Toolbox möglich ist.  &lt;br /&gt;&lt;a href="http://lh5.ggpht.com/-XLm6i0_M-LU/TlIahuEYhOI/AAAAAAAAAU4/jOp1P39gQCo/s1600-h/DataSourceWindow_thumb4%25255B2%25255D.png"&gt;&lt;img alt="DataSourceWindow_thumb4" border="0" height="257" src="http://lh3.ggpht.com/-xIf0Rm9uUQE/TlIaiDaULhI/AAAAAAAAAU8/D701ErTwYok/DataSourceWindow_thumb4_thumb.png?imgmax=800" style="background-image: none; border: 0px currentColor; display: inline; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="DataSourceWindow_thumb4" width="218" /&gt;&lt;/a&gt;  &lt;br /&gt;&lt;h4&gt;Metadaten&lt;/h4&gt;Die Generierung der Oberfläche erfolgt auf Grundlage von Metadaten, welche die Datenquelle in Form von &lt;a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.aspx"&gt;Data Annotations&lt;/a&gt; bereit stellt. So werden zum Beispiel die Labels mit den Anzeigenamen belegt, die über das &lt;a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.displayattribute.aspx"&gt;Display&lt;/a&gt;-Attribut angegeben wurden. Beispiel:    &lt;br /&gt;&lt;span style="font-family: consolas;"&gt;using System.ComponentModel.DataAnnotations;      &lt;br /&gt;public class Person       &lt;br /&gt;{       &lt;br /&gt;&amp;nbsp; [Required]       &lt;br /&gt;&amp;nbsp; [Editable(false)]       &lt;br /&gt;&amp;nbsp; [Display(Name = "ID", Description = "The id of the person.")]      &lt;br /&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="font-family: consolas;"&gt;[DisplayFormat(DataFormatString = "#{0}")]      &lt;br /&gt;&amp;nbsp; public int Id { get; set; }       &lt;br /&gt;&lt;br /&gt;&amp;nbsp; [Required]       &lt;br /&gt;&amp;nbsp; [StringLength(50)]       &lt;br /&gt;&amp;nbsp; [Display(Name = "Fullname",       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Description="The full name of the person.")]       &lt;br /&gt;&amp;nbsp; public string Name { get; set; }&amp;nbsp; &lt;br /&gt;&amp;nbsp; …       &lt;br /&gt;} &lt;/span&gt;    &lt;br /&gt;Hierbei werden sowohl die Anzeigeattribute, als auch die Formatierungen und Validierungsregeln von &lt;a href="http://dataform.codeplex.com/"&gt;TT.DataForm&lt;/a&gt; bei der Generierung berücksichtigt.    &lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Lookup-Daten&lt;/h4&gt;Oft werden neben der primären Datenquelle zusätzliche Daten, zum Beispiel für ComboBoxen benötigt. Hierfür bietet &lt;a href="http://dataform.codeplex.com/"&gt;TT.DataForm&lt;/a&gt; die Methode &lt;strong&gt;SetAssociationSource()&lt;/strong&gt;, sowie die Eigenschaft &lt;strong&gt;SubDataSources&lt;/strong&gt;. Mit Ihnen können mit der Hauptdatenquelle verknüpfte Datenquellen angegeben werden. Hierbei wird jeweils der Name der Eigenschaft in der Hauptdatenquelle, sowie die Liste der verknüpften Datenquelle angegeben.  &lt;br /&gt;Der folgende Code zeigt ein einfaches Beispiel:  &lt;br /&gt;&lt;span style="font-family: consolas;"&gt;var list = new ObservableCollection&amp;lt;Department&amp;gt;()    &lt;br /&gt;{     &lt;br /&gt;&amp;nbsp; new Department { Id = 1, Name = "Development" }     &lt;br /&gt;}     &lt;br /&gt;var persons = new ObservableCollection&amp;lt;Person&amp;gt;()     &lt;br /&gt;{     &lt;br /&gt;&amp;nbsp; new Person     &lt;br /&gt;&amp;nbsp; {     &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Id = 1,     &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Name = "Jörg Neumann",     &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Department = departments[0]     &lt;br /&gt;&amp;nbsp; }     &lt;br /&gt;};     &lt;br /&gt;&lt;span style="background-color: yellow;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: consolas;"&gt;&lt;strong&gt;dataForm.DataSource = persons;      &lt;br /&gt;dataForm.SetAssociationSource("Department", departments);&lt;/strong&gt;&lt;/span&gt;  &lt;br /&gt;Daraufhin erzeugt &lt;a href="http://dataform.codeplex.com/"&gt;TT.DataForm&lt;/a&gt; für die Department-Eigenschaft eine Combobox und bindet diese an die angegebene Quelle.  &lt;br /&gt;&lt;a href="http://lh3.ggpht.com/-aHZGrWAmYxw/TlIaius6hqI/AAAAAAAAAVA/kN4Gb_NkmEw/s1600-h/SubDataSources_thumb2%25255B2%25255D.png"&gt;&lt;img alt="SubDataSources_thumb2" border="0" height="218" src="http://lh6.ggpht.com/-vrUx42-NOXE/TlIajLdzMcI/AAAAAAAAAVE/IC_4WNmzOUs/SubDataSources_thumb2_thumb.png?imgmax=800" style="background-image: none; border: 0px currentColor; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="SubDataSources_thumb2" width="448" /&gt;&lt;/a&gt;  &lt;br /&gt;Die Eigenschaft &lt;strong&gt;SubDataSources&lt;/strong&gt; ist empfehlenswert, wenn die Quelle per Markup zugewiesen werden soll und die Anwendung dem MVVM-Pattern folgt. Hierbei muss als Quelle lediglich der Name der entsprechenden ViewModel-Eigenschaft angegeben werden, welche die verknüpfte Datenquelle zu Verfügung stellt.  &lt;br /&gt;&lt;strong&gt;ViewModel:&lt;/strong&gt;   &lt;br /&gt;&lt;span style="font-family: consolas;"&gt;class PersonViewModel    &lt;br /&gt;{     &lt;br /&gt;public ObservableCollection&amp;lt;Person&amp;gt; Persons { get; }     &lt;br /&gt;public ObservableCollection&amp;lt;Departments&amp;gt; Departments { get; }     &lt;br /&gt;}&lt;/span&gt;  &lt;br /&gt;&lt;strong&gt;View:&lt;/strong&gt;   &lt;br /&gt;&lt;span style="font-family: consolas;"&gt;&amp;lt;tt:DataForm DataSource = "{Binding Persons}"&amp;gt;    &lt;br /&gt;&amp;nbsp; &amp;lt;tt:DataForm.SubDataSources&amp;gt;     &lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: consolas;"&gt;&lt;span style="background-color: yellow;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: consolas;"&gt;&lt;strong&gt;&amp;nbsp; &amp;lt;tt:SubDataSource      &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; EntityPropertyName = "Department"       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DataSourcePropertyName = "Departments"/&amp;gt;       &lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style="font-family: consolas;"&gt;&amp;nbsp; &amp;lt;tt:DataForm.SubDataSources&amp;gt;    &lt;br /&gt;&amp;lt;/tt:DataForm&amp;gt;&lt;/span&gt;  &lt;br /&gt;Im nächsten Post beschreibe ich, wie das Mapping zwischen Datenquelle und UI-Element beeinflusst werden kann.     &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-5605829769621404236?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/5605829769621404236/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=5605829769621404236' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/5605829769621404236'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/5605829769621404236'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2011/08/ttdataform-data-binding_22.html' title='TT.DataForm: Data Binding'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/-xIf0Rm9uUQE/TlIaiDaULhI/AAAAAAAAAU8/D701ErTwYok/s72-c/DataSourceWindow_thumb4_thumb.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-2574720847799812550</id><published>2011-08-19T09:43:00.000+02:00</published><updated>2011-08-19T09:43:06.403+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TT.DataForm'/><title type='text'>Just Released: Thinktecture DataForm</title><content type='html'>&lt;a href="http://dataform.codeplex.com/"&gt;Thinktecture DataForm&lt;/a&gt; ist ein Open Source Control für WPF (eine Silverlight-Version ist in Arbeit), das eine automatische Generierung von formularbasierten Oberflächen ermöglicht. Hierfür analysiert es die übergebene Datenquelle und die hiermit verknüpften &lt;a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.aspx"&gt;Data Annotations&lt;/a&gt;. Darüber hinaus kann die Generierung durch ein umfangreiches Customizing-Modell gesteuert werden. Für eine bessere Usability werden kontextsensitive Symbole und Informationen zu den Daten angezeigt (Pflichtfeldmarkierungen, Beschreibungen, Eingabefehler, …). Darüber hinaus kann so gut wie jeder Aspekt der Oberfläche durch Styles und Templates angepasst bzw. ersetzt werden. Die Komponente unterstützt eine Vielzahl verschiedener Datenquellentypen, sowie programmatische und deklarative Validierung. Zudem kann die komplette Funktionalität über Commands gesteuert werden, was einen Einsatz in MVVM-Anwendungen erleichtert.&lt;br /&gt;&lt;a href="http://lh5.ggpht.com/-S1LPmQzbvf8/Tk0VlubNMqI/AAAAAAAAAUk/AgtZEIbFxKs/s1600-h/TTDataFormOverview5.png"&gt;&lt;img alt="TTDataFormOverview" border="0" height="322" src="http://lh6.ggpht.com/-0ufEeT-0DAo/Tk0VmR8nw9I/AAAAAAAAAUo/F7TRePqF2Yo/TTDataFormOverview_thumb3.png?imgmax=800" style="background-image: none; border-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="TTDataFormOverview" width="466" /&gt;&lt;/a&gt;&lt;br /&gt;Die Einzelheiten der Komponente werde ich in nächster Zeit in separaten Posts beschreiben. Darüber hinaus gibt es auf der &lt;a href="http://dataform.codeplex.com/"&gt;CodePlex&lt;/a&gt;-Site eine &lt;a href="http://dataform.codeplex.com/documentation"&gt;Dokumentation&lt;/a&gt;. Zudem ist ein Artikel in der &lt;a href="http://www.dotnetpro.de/"&gt;dotnetpro&lt;/a&gt; in Planung.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-2574720847799812550?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/2574720847799812550/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=2574720847799812550' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/2574720847799812550'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/2574720847799812550'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2011/08/just-released-thinktecture-dataform.html' title='Just Released: Thinktecture DataForm'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/-0ufEeT-0DAo/Tk0VmR8nw9I/AAAAAAAAAUo/F7TRePqF2Yo/s72-c/TTDataFormOverview_thumb3.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-6919309426514300926</id><published>2011-08-15T16:52:00.002+02:00</published><updated>2011-08-22T08:25:50.372+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TT.UIA'/><title type='text'>Artikel über TT.UIA in der dotnetpro</title><content type='html'>In der aktuellen Ausgabe der &lt;a href="http://www.dotnetpro.de/"&gt;dotnetpro&lt;/a&gt; (9/2011) ist mein Artikel “&lt;strong&gt;Aspektorientierte UI-Entwicklung mit Adornern&lt;/strong&gt;” erschienen. Dies ist der erste Teil einer dreiteiligen Artikelserie in denen ich die technischen Aspekte von &lt;a href="http://uiannotations.codeplex.com/"&gt;Thinktecture UIAnnotations&lt;/a&gt; erkläre.&lt;br /&gt;&lt;strong&gt;Aus dem Abstract:&lt;/strong&gt;&lt;br /&gt;&lt;blockquote&gt;Benutzeroberflächen sind mehr als nur einfache Eingabemasken. Das drückt sich unter anderem darin aus, dass Nutzerfreundlichkeit und Interaktivität immer wichtiger werden. Bei der Implementierung stehen hingegen Kapselung und Wiederverwendbarkeit im Vordergrund. Adorner werden beiden Anforderungen gerecht.&lt;/blockquote&gt;&lt;a href="http://www.dotnetpro.de/"&gt;&lt;img alt="dnp_092011" border="0" height="188" src="http://lh5.ggpht.com/-JBwSM4XpKR4/TkkyyiJt3qI/AAAAAAAAAUQ/-a8nMdGcUZg/dnp_092011%25255B3%25255D.jpg?imgmax=800" style="background-image: none; border: 0px currentColor; display: block; float: none; margin-left: auto; margin-right: auto; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="dnp_092011" width="134" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-6919309426514300926?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/6919309426514300926/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=6919309426514300926' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/6919309426514300926'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/6919309426514300926'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2011/08/artikel-uber-ttuia-in-der-dotnetpro.html' title='Artikel über TT.UIA in der dotnetpro'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/-JBwSM4XpKR4/TkkyyiJt3qI/AAAAAAAAAUQ/-a8nMdGcUZg/s72-c/dnp_092011%25255B3%25255D.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-4806082764425307171</id><published>2011-07-13T14:06:00.002+02:00</published><updated>2011-08-22T08:25:40.316+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TT.UIA'/><title type='text'>TT.UIA for Silverlight</title><content type='html'>&lt;a href="http://uiannotations.codeplex.com/"&gt;TT.UIA&lt;/a&gt; ist nun auch für Silverlight verfügbar. Es enthält die komplette Funktionalität der WPF-Version. Zusätzlich bringt es separate Behaviors für alle Adorner mit.&lt;br /&gt;&lt;br /&gt;Mehr Infos gibt’s &lt;a href="http://uiannotations.codeplex.com/"&gt;hier&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-4806082764425307171?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/4806082764425307171/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=4806082764425307171' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/4806082764425307171'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/4806082764425307171'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2011/07/ttuia-for-silverlight.html' title='TT.UIA for Silverlight'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-6978685088095943371</id><published>2011-07-04T10:41:00.001+02:00</published><updated>2011-07-04T10:41:10.620+02:00</updated><title type='text'>Re-MVPed</title><content type='html'>&lt;p&gt;My MVP award for the &amp;quot;Client App Dev&amp;quot; category has been renewed for another year. Thanks!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-6978685088095943371?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/6978685088095943371/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=6978685088095943371' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/6978685088095943371'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/6978685088095943371'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2011/07/re-mvped.html' title='Re-MVPed'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-7820988546398851397</id><published>2011-05-25T08:28:00.002+02:00</published><updated>2011-08-22T08:25:22.409+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TT.UIA'/><title type='text'>TT.UIA: Command Behavior</title><content type='html'>Wie &lt;a href="http://headwriteline.blogspot.com/2011/05/ttuia-behaviors.html"&gt;hier&lt;/a&gt; bereits beschrieben, eignen sich Behaviors sehr gut um Problemstellungen rund um MVVM zu lösen. Ein häufiges Problem in diesem Zusammenhang ist der Umgang mit Commands. Sie können lediglich Buttons (und bei WPF auch Menu Items) zugewiesen werden – alle anderen UI-Elemente verfügen nicht über eine Command-Eigenschaft. Zudem wird der Command immer nur über das &lt;em&gt;Click&lt;/em&gt;-Event ausgelöst. Auch bezieht sich der Status eines Command stets auf die &lt;em&gt;IsEnabled&lt;/em&gt;-Eigenschaft des jeweiligen Controls. All diese Limitationen versucht &lt;a href="http://uiannotations.codeplex.com/"&gt;TT.UIA&lt;/a&gt; mit dem Command Behavior zu lösen.&lt;br /&gt;&lt;h4&gt;Das Command Behavior&lt;/h4&gt;Die Klasse &lt;strong&gt;CommandBehavior&lt;/strong&gt; leitet von &lt;a href="http://msdn.microsoft.com/de-de/library/system.windows.interactivity.triggeraction(v=expression.40).aspx"&gt;TriggerAction&amp;lt;T&amp;gt;&lt;/a&gt; ab und kann somit auf beliebige Elemente und deren Events angewendet werden. Beispiel:&lt;br /&gt;&lt;span style="font-family: Consolas;"&gt;&amp;lt;Button&amp;gt;      &lt;br /&gt;&amp;nbsp; &amp;lt;i:Interaction.Triggers&amp;gt;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;i:EventTrigger EventName="Click"&amp;gt;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;behaviors:CommandBehavior       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Command="{Binding OkCommand}"       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; PropertyName="Visiblity"       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CanExecutePropertyValue="Visible"       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CanNotExecutePropertyValue="Collapsed" /&amp;gt;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/i:EventTrigger&amp;gt;       &lt;br /&gt;&amp;nbsp; &amp;lt;/i:Interaction.Triggers&amp;gt;       &lt;br /&gt;&amp;lt;/Button&amp;gt;&lt;/span&gt;&lt;br /&gt;Hier wurde einem Button der &lt;strong&gt;CommandBehavior&lt;/strong&gt; zugewiesen. Bei welchem Event das Command ausgeführt werden soll wurde hierbei über die &lt;em&gt;EventName&lt;/em&gt;-Eigenschaft der Klasse &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.interactivity.eventtrigger(v=expression.40).aspx"&gt;EventTrigger&lt;/a&gt; angegeben.&lt;br /&gt;Die Bindung zum Command kann daraufhin wie gewohnt über die Eigenschaften &lt;em&gt;Command&lt;/em&gt; bzw. &lt;em&gt;CommandParameter&lt;/em&gt; zugewiesen werden. Zusätzlich kann über die Eigenschaften &lt;em&gt;PropertyName&lt;/em&gt;, &lt;em&gt;CanExecutePropertyValue&lt;/em&gt; und &lt;em&gt;ExecutePropertyValue&lt;/em&gt; angegeben werden, welche Eigenschaft des zugehörigen Elements auf welchen Wert gesetzt werden soll, wenn der Command aktiv bzw. inaktiv ist. Sollte für das Setzen des Eigenschaftenwertes eine Konvertierung erforderlich sein, kann über die &lt;em&gt;Converter&lt;/em&gt;-Eigenschaft ein entsprechender Value Converter angegeben werden.&lt;br /&gt;Darüber hinaus bietet &lt;strong&gt;CommandBehavior&lt;/strong&gt; die Eigenschaft &lt;em&gt;CommandAction&lt;/em&gt;. Dies ist ein shortcut für den Fall, dass sich der Status des Commands lediglich auf die Eigenschaft &lt;em&gt;IsEnabled&lt;/em&gt; oder &lt;em&gt;Visibility&lt;/em&gt; auswirken sollen. Hierbei muss &lt;em&gt;CommandAction&lt;/em&gt; lediglich auf den Wert &lt;em&gt;Hide&lt;/em&gt; oder &lt;em&gt;Disable&lt;/em&gt; gesetzt werden. Hierbei kann die explizite Angabe über &lt;em&gt;PropertyName&lt;/em&gt;, &lt;em&gt;CanExecutePropertyValue&lt;/em&gt; und &lt;em&gt;ExecutePropertyValue&lt;/em&gt; entfallen. Beispiel:&lt;br /&gt;&lt;span style="font-family: Consolas;"&gt;&amp;lt;Button&amp;gt;      &lt;br /&gt;&amp;nbsp; &amp;lt;i:Interaction.Triggers&amp;gt;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;i:EventTrigger EventName="Click"&amp;gt;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;behaviors:CommandBehavior       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Command="{Binding OkCommand}"       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;strong&gt;CommandAction="Hide"&lt;/strong&gt; /&amp;gt;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/i:EventTrigger&amp;gt;       &lt;br /&gt;&amp;nbsp; &amp;lt;/i:Interaction.Triggers&amp;gt;       &lt;br /&gt;&amp;lt;/Button&amp;gt;&lt;/span&gt;&lt;br /&gt;So, das war es erstmal mit meiner Blog-Serie zu &lt;a href="http://uiannotations.codeplex.com/"&gt;TT.UIA&lt;/a&gt;. Als nächstes steht die Silverlight-Portierung an. Stay tuned!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-7820988546398851397?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/7820988546398851397/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=7820988546398851397' title='1 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/7820988546398851397'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/7820988546398851397'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2011/05/ttuia-command-behavior.html' title='TT.UIA: Command Behavior'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-6468588231255179548</id><published>2011-05-24T07:57:00.002+02:00</published><updated>2011-08-22T08:25:09.354+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TT.UIA'/><title type='text'>TT.UIA: Adorner Factory Behaviors</title><content type='html'>Wie &lt;a href="http://headwriteline.blogspot.com/2011/05/ttuia-einfuhrung.html"&gt;hier&lt;/a&gt; und &lt;a href="http://headwriteline.blogspot.com/2011/05/ttuia-behavior-factories_23.html"&gt;hier&lt;/a&gt; bereits beschrieben, haben &lt;a href="http://blogs.msdn.com/b/expression/archive/2009/03/23/an-introduction-to-behaviors-triggers-and-actions.aspx"&gt;Expression Blend Behaviors&lt;/a&gt; ein paar Limitationen. Hierzu zählt zum Beispiel die Tatsache, dass sie nicht so flexibel wie Adorner sind. So können sie zum Beispiel nur das zugewiesene Element selbst manipulieren und keine zusätzlichen Elemente einfügen. Um diese Limitationen zu umgehen, bietet &lt;a href="http://uiannotations.codeplex.com/"&gt;TT.UIA&lt;/a&gt; die Klasse &lt;strong&gt;AdornerFactoryBehavior&lt;/strong&gt;.&lt;br /&gt;Mit ihr kann ein beliebiger Adorner in Form eines Behaviors zugewiesen werden. Beispiel:&lt;br /&gt;&lt;span style="font-family: Consolas;"&gt;&amp;lt;TextBox&amp;gt;      &lt;br /&gt;&amp;nbsp; &amp;lt;i:Interaction.Behaviors&amp;gt;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;behaviors:AdornerFactoryBehavior       &lt;br /&gt;AdornerTypeName="Thinktecture.UIAnnotations.ElementTrackerAdorner" /&amp;gt;       &lt;br /&gt;&amp;nbsp; &amp;lt;/i:Interaction.Behaviors&amp;gt;       &lt;br /&gt;&amp;lt;/TextBox&amp;gt;&lt;/span&gt;&lt;br /&gt;Dies hat den Vorteil, dass der Adorner sehr einfach mit Expression Blend zugewiesen werden kann.&lt;br /&gt;&lt;a href="http://lh4.ggpht.com/_11VTbOPwP_U/TdtI1hMaJKI/AAAAAAAAASc/b8qJ-x-f8uA/s1600-h/AdornerFactoryBehaviorInBlend3.png"&gt;&lt;img alt="AdornerFactoryBehaviorInBlend" border="0" height="274" src="http://lh4.ggpht.com/_11VTbOPwP_U/TdtI2D00MjI/AAAAAAAAASg/0zeGtocwCmU/AdornerFactoryBehaviorInBlend_thumb1.png?imgmax=800" style="background-image: none; border-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="AdornerFactoryBehaviorInBlend" width="463" /&gt;&lt;/a&gt;&lt;br /&gt;Darüber hinaus ist es auch möglich, einen Adorner mehrfach dem gleichen Element zuzuweisen, was mit der Attached Property-Syntax nicht möglich ist.&lt;br /&gt;Die meisten Adorner von &lt;a href="http://uiannotations.codeplex.com/"&gt;TT.UIA&lt;/a&gt; verfügen jedoch über zusätzliche Eigenschaften, die nicht generisch über &lt;strong&gt;AdornerFactoryBehavior&lt;/strong&gt; zugewiesen werden können. Daher bietet es sich an, eine entsprechende Ableitung zu erstellen. Ein Beispiel hierfür ist die Klasse &lt;strong&gt;CueBannerBehavior&lt;/strong&gt;. Sie kapselt den &lt;strong&gt;CueBannerAdorner&lt;/strong&gt; in dem sie von &lt;strong&gt;AdornerFactoryBehavior&lt;/strong&gt; ableitet und die Eigenschaft &lt;em&gt;CueBannerText&lt;/em&gt; bereitstellt. &lt;br /&gt;&lt;span style="font-family: Consolas;"&gt;public class CueBannerAdornerFactoryBehavior      &lt;br /&gt;: AdornerFactoryBehavior       &lt;br /&gt;{       &lt;br /&gt;&amp;nbsp; protected override Adorner CreateAdorner()       &lt;br /&gt;&amp;nbsp; {       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var adorner = new CueBannerAdorner(this.AssociatedObject);       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; adorner.CueBanner = this.CueBannerText;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return adorner;       &lt;br /&gt;&amp;nbsp; }       &lt;br /&gt;&amp;nbsp; public static readonly DependencyProperty       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; CueBannerTextProperty = DependencyProperty.Register(       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "CueBannerText", typeof(string),       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; typeof(CueBannerAdornerFactoryBehavior),       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; new PropertyMetadata("",&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; OnCueBannerTextPropertyChanged));       &lt;br /&gt;&amp;nbsp; public string CueBannerText       &lt;br /&gt;&amp;nbsp; {       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; get { return (string)GetValue(CueBannerTextProperty); }       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; set { SetValue(CueBannerTextProperty, value); }       &lt;br /&gt;&amp;nbsp; }       &lt;br /&gt;&amp;nbsp; private static void OnCueBannerTextPropertyChanged(       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DependencyObject sender,       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DependencyPropertyChangedEventArgs e)       &lt;br /&gt;&amp;nbsp; {       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ((CueBannerAdornerFactoryBehavior)sender)       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .OnCueBannerTextChanged(sender, e);       &lt;br /&gt;&amp;nbsp; }       &lt;br /&gt;&amp;nbsp; private void OnCueBannerTextChanged(       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DependencyObject sender,       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DependencyPropertyChangedEventArgs e)       &lt;br /&gt;&amp;nbsp; {       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (this.Adorner != null &amp;amp;&amp;amp; e.NewValue != null)       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ((CueBannerAdorner)this.Adorner)       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .CueBanner = e.NewValue.ToString();       &lt;br /&gt;&amp;nbsp; }       &lt;br /&gt;}&lt;/span&gt;&lt;br /&gt;Hier wurde zunächst die Methode &lt;strong&gt;CreateAdorner()&lt;/strong&gt; der Basisklasse überschieben und hierin der &lt;strong&gt;CueBannerAdorner&lt;/strong&gt; erstellt. Die Property &lt;em&gt;CueBannerText&lt;/em&gt; muss nun lediglich an den Adorner durchgereicht werden.&lt;br /&gt;Im nächsten Post geht es mal nicht um grafische Effekte, sondern den sinnvollen Einsatz von Behaviors in MVVM-Szenarien.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-6468588231255179548?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/6468588231255179548/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=6468588231255179548' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/6468588231255179548'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/6468588231255179548'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2011/05/ttuia-adorner-factory-behaviors.html' title='TT.UIA: Adorner Factory Behaviors'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_11VTbOPwP_U/TdtI2D00MjI/AAAAAAAAASg/0zeGtocwCmU/s72-c/AdornerFactoryBehaviorInBlend_thumb1.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-5552455607642768499</id><published>2011-05-23T08:17:00.002+02:00</published><updated>2011-08-22T08:24:56.880+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TT.UIA'/><title type='text'>TT.UIA: Behavior Factories</title><content type='html'>Wie &lt;a href="http://headwriteline.blogspot.com/2011/05/ttuia-einfuhrung.html"&gt;hier&lt;/a&gt; bereits beschrieben, haben &lt;a href="http://blogs.msdn.com/b/expression/archive/2009/03/23/an-introduction-to-behaviors-triggers-and-actions.aspx"&gt;Expression Blend Behaviors&lt;/a&gt; ein paar Limitationen. Hierzu zählt zum Beispiel die Tatsache, dass sie nicht per Style zugewiesen werden können. Um diese Limitation zu umgehen, bietet &lt;a href="http://uiannotations.codeplex.com/"&gt;TT.UIA&lt;/a&gt; die Behavior Factories.&lt;br /&gt;&lt;h4&gt;Die Klasse BehaviorFactory&lt;/h4&gt;Behaviors werden zwar auch über Attached Properties zugewiesen, können aber nicht über einen Style zugewiesen werden. Dies ist per Design so und führt bei jedem Versuch zu einer Exception. Behaviors lassen sich jedoch per Code zuweisen. Diese Möglichkeit nutzt die Klasse &lt;strong&gt;BehaviorFactory&lt;/strong&gt;. Sie stellt die Attached Property &lt;em&gt;BehaviorTypeNam&lt;/em&gt;e zu Verfügung, über die die Typbezeichnung des Behaviors angegeben werden kann. Der so angegebene Behavior-Typ wird daraufhin instanziiert und per Code an das entsprechende Element gebunden.&lt;br /&gt;In folgendem Beispiel wird das Focus Behavior mit Hilfe von &lt;strong&gt;BehaviorFactory&lt;/strong&gt; innerhalb eines Styles zugewiesen:&lt;br /&gt;&lt;span style="font-family: Consolas;"&gt;&amp;lt;Window&amp;gt;      &lt;br /&gt;&amp;lt;Window.Resources&amp;gt;       &lt;br /&gt;&amp;lt;Style TargetType="TextBox"&amp;gt;       &lt;br /&gt;&amp;lt;Setter Property="behaviors:BehaviorFactory.BehaviorTypeName" Value="Thinktecture.UIAnnotations.Behaviors.FocusBehavior" /&amp;gt;       &lt;br /&gt;&amp;lt;/Style&amp;gt;       &lt;br /&gt;&amp;lt;/Window.Resources&amp;gt;       &lt;br /&gt;...       &lt;br /&gt;&amp;lt;/Window&amp;gt;&lt;/span&gt;&lt;br /&gt;Da der Style implizit definiert wurde, werden daraufhin alle Textboxen des Fensters mit dem Behavior ausgestattet, ohne das diese explizit zugewiesen werden müssen.&lt;br /&gt;In diesem Fall kann es jedoch vorkommen, das eine bestimmte Textbox des Fensters nicht mit dem Behavior ausgestattet werden soll. Hierfür bietet &lt;strong&gt;BehaviorFactory &lt;/strong&gt;die Attached Property &lt;em&gt;DetachBehaviorTypeName&lt;/em&gt;. Sie unterbindet für das zugehörige Element ist Zuweisung des über einen Style definierten Behaviors.&lt;br /&gt;&lt;span style="font-family: Consolas;"&gt;&amp;lt;TextBox      &lt;br /&gt;behaviors:BehaviorFactory.&lt;strong&gt;DetachBehaviorTypeName&lt;/strong&gt;=       &lt;br /&gt;"Thinktecture.UIAnnotations.Behaviors.FocusBehavior" /&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;h4&gt;&lt;strong&gt;TriggerActionFactory&lt;/strong&gt; und &lt;strong&gt;TargetedTriggerActionFactory&lt;/strong&gt;&lt;/h4&gt;Wenn das betreffende Behavior nicht von &lt;a href="http://msdn.microsoft.com/en-us/library/ff726531(v=expression.40).aspx"&gt;Behavior&amp;lt;T&amp;gt;&lt;/a&gt;, sondern von &lt;a href="http://msdn.microsoft.com/de-de/library/system.windows.interactivity.triggeraction(v=expression.40).aspx"&gt;TriggerAction&amp;lt;T&amp;gt;&lt;/a&gt; oder &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.interactivity.targetedtriggeraction(v=expression.40).aspx"&gt;TargetedTriggerAction&amp;lt;T&amp;gt;&lt;/a&gt; ableitet, muss zusätzlich noch der Name des auslösenden Events, bzw. das Zielelement angegeben werden. Hierfür bietet &lt;a href="http://uiannotations.codeplex.com/"&gt;TT.UIA&lt;/a&gt; die spezialisierten Klassen &lt;strong&gt;TriggerActionFactory&lt;/strong&gt; und &lt;strong&gt;TargetedTriggerActionFactory&lt;/strong&gt;&lt;em&gt;.&lt;/em&gt;&lt;br /&gt;Im nächsten Post geht es ebenfalls um Behaviors. Hier werde ich die Klasse &lt;strong&gt;AdornerFactoryBehavior&lt;/strong&gt; vorstellen, die verwendet werden kann, um beliebige Adorner per Behavior zuzuweisen.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-5552455607642768499?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/5552455607642768499/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=5552455607642768499' title='7 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/5552455607642768499'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/5552455607642768499'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2011/05/ttuia-behavior-factories_23.html' title='TT.UIA: Behavior Factories'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-5867581962756782696</id><published>2011-05-21T10:16:00.001+02:00</published><updated>2011-05-23T14:46:17.136+02:00</updated><title type='text'>Slides von der BASTA! ON TOUR</title><content type='html'>&lt;p&gt;Die erste BASTA! ON TOUR in diesem Jahr hat richtig Spaß gemacht! Hier die Slides meiner Sessions:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://cid-4029b6652bf3f13f.office.live.com/self.aspx/%c3%96ffentlich/BASTA%20ON%20TOUR%202011-1/Neumann%5E_WPFArchitekturmuster.pdf"&gt;WPF Architekturmuster&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://cid-4029b6652bf3f13f.office.live.com/self.aspx/%c3%96ffentlich/BASTA%20ON%20TOUR%202011-1/Neumann%5E_WPF%5E_TippsTricks.pdf#resId/4029B6652BF3F13F!196"&gt;WPF Tipps &amp;amp; Tricks&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-5867581962756782696?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/5867581962756782696/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=5867581962756782696' title='3 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/5867581962756782696'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/5867581962756782696'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2011/05/slides-von-der-basta-on-tour.html' title='Slides von der BASTA! ON TOUR'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-1853511648123976546</id><published>2011-05-20T08:25:00.002+02:00</published><updated>2011-08-22T08:24:45.475+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TT.UIA'/><title type='text'>TT.UIA: Behaviors</title><content type='html'>Wie &lt;a href="http://headwriteline.blogspot.com/2011/05/ttuia-einfuhrung.html"&gt;hier&lt;/a&gt; bereits beschrieben, haben &lt;a href="http://blogs.msdn.com/b/expression/archive/2009/03/23/an-introduction-to-behaviors-triggers-and-actions.aspx"&gt;Expression Blend Behaviors&lt;/a&gt; gegenüber Attached Properties einige Vorteile. Hierzu zählt vor allem die Designer-Unterstützung in Blend. Ein weiterer Vorteil ist jedoch auch die Tatsache, dass Behaviors mit mehreren Elementen verbunden werden können.&lt;br /&gt;Ein einfaches Beispiel:Ein Dialog enthält eine Textbox/Button-Kombination zur Auswahl einer Datei.&lt;br /&gt;&lt;a href="http://lh4.ggpht.com/_11VTbOPwP_U/TdYJOlRjwdI/AAAAAAAAASE/qAlWM25EzvM/s1600-h/OpenFileBehavior4.png"&gt;&lt;img alt="OpenFileBehavior" border="0" height="269" src="http://lh6.ggpht.com/_11VTbOPwP_U/TdYJPCxjTyI/AAAAAAAAASI/2dVGTUFgvpc/OpenFileBehavior_thumb2.png?imgmax=800" style="background-image: none; border-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="OpenFileBehavior" width="461" /&gt;&lt;/a&gt;&lt;br /&gt;Klassischerweise würde man hier im Code-Behind den Dateidialog öffnen und die Auswahl in die daneben stehende Textbox übertragen. Da dies eine Funktionalität ist, die häufiger benötigt wird, bietet es sich an sie zu kapseln. Der Code-Behind-Ansatz ist jedoch auch in MVVM-Szenarien ein Problem. Das Öffnen des Dialogs möchte man jedoch auch nicht im ViewModel hinterlegen, da es sich um UI-Code handelt.&lt;br /&gt;&lt;h4&gt;Das Open File Behavior&lt;/h4&gt;Mit einem Behavior lässt sich solch eine Funktionalität sehr komfortabel abbilden. &lt;a href="http://uiannotations.codeplex.com/"&gt;TT.UIA&lt;/a&gt; bietet hierfür die Klasse &lt;strong&gt;OpenFileBehavior&lt;/strong&gt;. Sie leitet von &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.interactivity.targetedtriggeraction(v=expression.40).aspx"&gt;TargettetTriggerAction&amp;lt;T&amp;gt;&lt;/a&gt; ab und kann somit nicht nur ein Element (der Button im oberen Beispiel), sondern auch an ein Zielelement (die Textbox) gebunden werden.&lt;br /&gt;&lt;span style="font-family: Consolas;"&gt;...      &lt;br /&gt;&amp;lt;Button       &lt;br /&gt;&amp;nbsp; xmlns:i=       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "clr-namespace:System.Windows.Interactivity;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; assembly=System.Windows.Interactivity"       &lt;br /&gt;&amp;nbsp; xmlns:behaviors=       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "clr-namespace:Thinktecture.UIAnnotations.Behaviors;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; assembly=Thinktecture.UIAnnotations"&amp;gt;       &lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;lt;i:Interaction.Triggers&amp;gt;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;i:EventTrigger EventName="Click"&amp;gt;       &lt;br /&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;behaviors:OpenFileBehavior        &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; TargetName="imageTextBox"         &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DialogTitle="Select an image..."         &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Filter="PNG Files|*.png" /&amp;gt;         &lt;br /&gt;&lt;/strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/i:EventTrigger&amp;gt;       &lt;br /&gt;&amp;nbsp; &amp;lt;/i:Interaction.Triggers&amp;gt;       &lt;br /&gt;&lt;br /&gt;&amp;lt;/Button&amp;gt;       &lt;br /&gt;&lt;br /&gt;&amp;lt;TextBox x:Name="imageTextBox" /&amp;gt;       &lt;br /&gt;... &lt;/span&gt;&lt;br /&gt;Die Deklaration erfolgt hierbei über die Klasse &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.interactivity.interaction(Expression.40).aspx"&gt;System.Windows.Interactivity.Interaction&lt;/a&gt;, die Teil des &lt;a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=75E13D71-7C53-4382-9592-6C07C6A00207"&gt;Expression Blend SDKs&lt;/a&gt; ist.&lt;br /&gt;&lt;h4&gt;Das Busy Behavior&lt;/h4&gt;Ein weiteres Problem in MVVM-Anwendungen ist der Umgang mit Cursorn und anderen Fortschrittsanzeigen. Denn das ViewModel sollte weder explizit einen Cursors setzen, noch ein entsprechendes UI-Element direkt steuern. In Silverlight löst man dies meist mit dem beliebten (wenn auch hässlichen) BusyIndicator, die per Data Binding an das ViewModel gebunden wird. Hierfür muss die Komponente jedoch zur Entwurfszeit in das Layout des jeweiligen Fensters so eingefügt werden, dass sie im Vordergrund steht. Dies verursacht bei nachträglichen Layout-Änderungen häufig Probleme. Zudem sollte die Bedienung des Fensters verhindert werden, sobald der BusyIndicator aktiv wird. &lt;br /&gt;All diese Herausforderungen versucht die Klasse *BusyBehavior* zu lösen. Sie zeigt eine überdimensionale Eieruhr und legt dabei einen Overlay über das zugehörige Fenster um die Bedienung der Oberfläche durch den Benutzer zu verhindern. Das Busy Behavior kann mit einem beliebigen Element verknüpft werden. Es ermittelt zur Laufzeit das übergeordnete Fenster und fügt sich auf oberster Ebene in den visuellen Baum ein.&lt;br /&gt;&lt;span style="font-family: Consolas;"&gt;&amp;lt;i:Interaction.Behaviors&amp;gt;      &lt;br /&gt;&amp;nbsp; &amp;lt;behaviors:BusyBehavior       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IsBusy="{Binding IsBusy}" /&amp;gt;       &lt;br /&gt;&amp;lt;/i:Interaction.Behaviors&amp;gt;&lt;/span&gt;&lt;br /&gt;Die Steuerung erfolgt über die Eigenschaft *IsBusy*, die zum Beispiel an eine entsprechende Eigenschaft des zugehörigen ViewModels gebunden werden kann. Das Ganze sieht dann zur Laufzeit in etwas so aus:&lt;br /&gt;&lt;a href="http://lh4.ggpht.com/_11VTbOPwP_U/TdYJP-ZagzI/AAAAAAAAASM/OyvB8aop4KM/s1600-h/BusyBehavior2.png"&gt;&lt;img alt="BusyBehavior" border="0" height="244" src="http://lh5.ggpht.com/_11VTbOPwP_U/TdYJQa8RseI/AAAAAAAAASQ/6EM7_opvuMQ/BusyBehavior_thumb.png?imgmax=800" style="background-image: none; border-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="BusyBehavior" width="244" /&gt;&lt;/a&gt;   &lt;br /&gt;&lt;h4&gt;Das Dialog Button Behavior&lt;/h4&gt;Die Klasse &lt;strong&gt;DialogButtonBehavior&lt;/strong&gt; steuert das Verhalten von Dialogschaltflächen. Klassischerweise hat ein Dialog einen &lt;em&gt;Accept&lt;/em&gt;- und einen &lt;em&gt;Cancel&lt;/em&gt;-Button, womit der Benutzer das Fenster mit &lt;em&gt;Enter&lt;/em&gt; bestätigen, bzw. mit &lt;em&gt;ESC &lt;/em&gt;abbrechen kann. Hierbei wird das Fenster geschlossen und die &lt;em&gt;DialogResult&lt;/em&gt;-Eigenschaft entsprechend gesetzt. All dies fasst &lt;strong&gt;DialogButtonBehavior&lt;/strong&gt; zusammen, wie das folgende Beispiel zeigt:&lt;br /&gt;&lt;span style="font-family: Consolas;"&gt;&amp;lt;Button&amp;gt;      &lt;br /&gt;&amp;nbsp; &amp;lt;i:Interaction.Behaviors&amp;gt;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;behaviors:DialogButtonBehavior ButtonType="Ok" /&amp;gt;       &lt;br /&gt;&amp;nbsp; &amp;lt;/i:Interaction.Behaviors&amp;gt;       &lt;br /&gt;&amp;lt;/Button&amp;gt;&lt;/span&gt;&lt;br /&gt;Über die Eigenschaft &lt;em&gt;ButtonType&lt;/em&gt; kann das entsprechende Verhalten definiert werden.&lt;br /&gt;&lt;h4&gt;Das Focus Behavior&lt;/h4&gt;Die Klasse &lt;strong&gt;FocusBehavior&lt;/strong&gt; markiert das fokussierte Eingabeelement mit einer beliebigen Hintergrundfarbe.&lt;br /&gt;&lt;span style="font-family: Consolas;"&gt;&amp;lt;TextBox&amp;gt;      &lt;br /&gt;&amp;nbsp; &amp;lt;i:Interaction.Behaviors&amp;gt;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;behaviors:FocusBehavior HighlightBrush="Yellow" /&amp;gt;       &lt;br /&gt;&amp;nbsp; &amp;lt;/i:Interaction.Behaviors&amp;gt;       &lt;br /&gt;&amp;lt;/TextBox&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;a href="http://lh3.ggpht.com/_11VTbOPwP_U/TdYJQqCqivI/AAAAAAAAASU/IHqMcPp6TKQ/s1600-h/FocusBehavior3.png"&gt;&lt;img alt="FocusBehavior" border="0" height="63" src="http://lh5.ggpht.com/_11VTbOPwP_U/TdYJRIUOFZI/AAAAAAAAASY/555DaC2xyaA/FocusBehavior_thumb1.png?imgmax=800" style="background-image: none; border-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="FocusBehavior" width="198" /&gt;&lt;/a&gt;&lt;br /&gt;So, das war’s erstmal mit den Behaviors von &lt;a href="http://uiannotations.codeplex.com/"&gt;TT.UIA&lt;/a&gt;. Im nächsten Post gehe ich auf die &lt;strong&gt;Behavior Factories&lt;/strong&gt; ein, mit denen einige Limitationen der Behaviors behoben werden können.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-1853511648123976546?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/1853511648123976546/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=1853511648123976546' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/1853511648123976546'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/1853511648123976546'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2011/05/ttuia-behaviors.html' title='TT.UIA: Behaviors'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_11VTbOPwP_U/TdYJPCxjTyI/AAAAAAAAASI/2dVGTUFgvpc/s72-c/OpenFileBehavior_thumb2.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-2677229283598864179</id><published>2011-05-19T17:58:00.002+02:00</published><updated>2011-08-22T08:24:15.390+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TT.UIA'/><title type='text'>TT.UIA: Generic Adorner</title><content type='html'>Wie &lt;a href="http://headwriteline.blogspot.com/2011/05/ttuia-adorner.html"&gt;hier&lt;/a&gt; bereits beschrieben, bringt &lt;a href="http://uiannotations.codeplex.com/"&gt;TT.UIA&lt;/a&gt; eine Reihe fertiger Adorner mit. Unter ihnen ist auch der &lt;strong&gt;Generic Adorner&lt;/strong&gt;, mit dem beliebige Elemente als Adorner definiert und mit anderen Elementen verknüpft werden können.&lt;br /&gt;Die Klasse &lt;strong&gt;GenericAdorner&lt;/strong&gt; dient als Platzhalter für beliebigen Content, der frei positioniert werden kann. Die Zuweisung erfolgt hingegen über die Klasse &lt;strong&gt;GenericAdorners&lt;/strong&gt;, welche entsprechende Attached Properties für die Konfiguration bereitstellt.&lt;br /&gt;Das folgende Beispiel demonstriert die Verwendung:&lt;br /&gt;&lt;span style="font-family: Consolas;"&gt;&amp;lt;Window ...&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Consolas;"&gt;&amp;nbsp; &amp;lt;Window.Resources&amp;gt;      &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;ToolBar x:Key="adornerToolbar"&amp;gt;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Button ToolTip="Cut" Command="Cut"&amp;gt;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Image Source="/Images/Cut.png" Stretch="None" /&amp;gt;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Button&amp;gt;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Button ToolTip="Copy" Command="Copy"&amp;gt;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Image Source="/Images/Copy.png" Stretch="None" /&amp;gt;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Button&amp;gt;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Button ToolTip="Paste" Command="Paste"&amp;gt;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Image Source="/Images/Paste.png" Stretch="None" /&amp;gt;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Button&amp;gt;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/ToolBar&amp;gt;       &lt;br /&gt;&amp;nbsp; &amp;lt;/Window.Resources&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Consolas;"&gt;&amp;nbsp; &amp;lt;TextBox      &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; am:GenericAdorners.AdornerElement="{StaticResource adornerToolbar}"       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; am:GenericAdorners.VerticalAlignment="Top"       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; am:GenericAdorners.HorizontalAlignment="Right"       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; am:GenericAdorners.Placement="VerticalOuterHorizontalInner"       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; am:GenericAdorners.Margin="0,0,0,0"       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; am:GenericAdorners.Visible="True"       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; am:GenericAdorners.VisibleOnFocus="True" /&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Consolas;"&gt;&amp;lt;/Window&amp;gt;      &lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Hier wurde zunächst eine Toolbar im Resource Dictionary des Fensters definiert, welche als Adorner einer Textbox zugewiesen werden soll. Die Zuweisung erfolgt über die Attached Property &lt;strong&gt;GenericAdorners.AdornerElement&lt;/strong&gt;. Für die Positionierung stehen die Properties &lt;strong&gt;HorizontalAlignment&lt;/strong&gt;, &lt;strong&gt;VerticalAlignment&lt;/strong&gt; und &lt;strong&gt;Placement&lt;/strong&gt; zu Verfügung. &lt;strong&gt;Placement&lt;/strong&gt; gibt hierbei an, ob sich die Position auf den inneren oder äußeren Rahmen des jeweiligen Controls beziehen soll. Die folgende Abbildung zeigt die möglichen Kombinationen:&lt;br /&gt;&lt;a href="http://lh4.ggpht.com/_11VTbOPwP_U/TdU-Fh4EWuI/AAAAAAAAAR0/FsSBceRIDEk/s1600-h/GenericAdornerPlacement4.png"&gt;&lt;img alt="GenericAdornerPlacement" border="0" height="409" src="http://lh5.ggpht.com/_11VTbOPwP_U/TdU-GVe6ogI/AAAAAAAAAR4/N09qHQJAO2g/GenericAdornerPlacement_thumb2.png?imgmax=800" style="background-image: none; border-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="GenericAdornerPlacement" width="457" /&gt;&lt;/a&gt;&lt;br /&gt;Über die Eigenschaft &lt;strong&gt;VisibleOnFocus&lt;/strong&gt; kann zusätzlich festgelegt werden, ob der Adorner dynamisch eingeblendet werden soll, wenn das zugehörige Element den Fokus erhält.&lt;br /&gt;In den Beispielen zu &lt;a href="http://uiannotations.codeplex.com/"&gt;TT.UIA&lt;/a&gt; ist eine kleine Demo enthalten, die den Einsatz von &lt;strong&gt;GenericAdorner&lt;/strong&gt; zeigt.&lt;br /&gt;&lt;a href="http://lh6.ggpht.com/_11VTbOPwP_U/TdU-HEscCgI/AAAAAAAAAR8/0g9WuWaXagI/s1600-h/GenericAdornerDemo5.png"&gt;&lt;img alt="GenericAdornerDemo" border="0" height="260" src="http://lh6.ggpht.com/_11VTbOPwP_U/TdU-HzHdabI/AAAAAAAAASA/xcQjN8URBB4/GenericAdornerDemo_thumb3.png?imgmax=800" style="background-image: none; border-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="GenericAdornerDemo" width="453" /&gt;&lt;/a&gt;&lt;br /&gt;Das war’s erstmal mit den Adornern. Im nächsten Post geht es um die Behaviors in &lt;a href="http://uiannotations.codeplex.com/"&gt;TT.UIA&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-2677229283598864179?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/2677229283598864179/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=2677229283598864179' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/2677229283598864179'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/2677229283598864179'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2011/05/ttuia-generic-adorner.html' title='TT.UIA: Generic Adorner'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_11VTbOPwP_U/TdU-GVe6ogI/AAAAAAAAAR4/N09qHQJAO2g/s72-c/GenericAdornerPlacement_thumb2.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-7056175043006294420</id><published>2011-05-18T13:14:00.002+02:00</published><updated>2011-08-22T08:23:50.866+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TT.UIA'/><title type='text'>TT.UIA: Data Annotation Support</title><content type='html'>Wie ich &lt;a href="http://headwriteline.blogspot.com/2011/05/ttuia-adorner.html"&gt;hier&lt;/a&gt; bereits beschrieben habe, können die Adorner von &lt;a href="http://uiannotations.codeplex.com/"&gt;TT.UIA&lt;/a&gt; sehr leicht per Style zugewiesen werden. Doch neben dieser existiert noch eine weitere Möglichkeit die Zuweisung zu automatisieren.&lt;br /&gt;&lt;a href="http://uiannotations.codeplex.com/"&gt;TT.UIA&lt;/a&gt; bietet mit &lt;strong&gt;Annotations.AttachDataAnnotations&lt;/strong&gt; eine Attached Property, die auf Root-Ebene zugewiesen wird. Wird sie auf &lt;em&gt;true&lt;/em&gt; gesetzt, werden alle Elemente des Fensters oder des User Controls durchlaufen und dessen Datenbindungen analysiert. &lt;a href="http://uiannotations.codeplex.com/"&gt;TT.UIA&lt;/a&gt; prüft hierbei, ob die Datenquelle der jeweiligen Bindung über &lt;a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.aspx"&gt;Data Annotations&lt;/a&gt; verfügt. Ist dem so, werden für bestimmte Annotations entsprechenden Adorner gesetzt. Hier ein einfaches Beispiel für eine annotierte Datenquelle:&lt;br /&gt;&lt;span style="font-family: Consolas;"&gt;using System.ComponentModel.DataAnnotations;      &lt;br /&gt;public class Person       &lt;br /&gt;{       &lt;br /&gt;&lt;strong&gt;&amp;nbsp; [Required]        &lt;br /&gt;&amp;nbsp; [Display(Prompt = "Enter the full name!")]         &lt;br /&gt;&lt;/strong&gt;&amp;nbsp; public string Name { get; set; }       &lt;br /&gt;} &lt;/span&gt;&lt;br /&gt;Hier wurde die Eigenschaft &lt;em&gt;Name&lt;/em&gt; als Pflichtfeld markiert und ein entsprechender Prompt-Text hinterlegt.&lt;br /&gt;Das Markup des Fensters könnte nun zum Beispiel wie folgt aussehen:&lt;br /&gt;&lt;span style="font-family: Consolas;"&gt;&amp;lt;Window &lt;strong&gt;uia:ApplyDataAnnotations="True"&lt;/strong&gt;&amp;gt;       &lt;br /&gt;&amp;nbsp; &amp;lt;TextBox Text="{Binding Person.Name}" /&amp;gt;       &lt;br /&gt;&amp;lt;/Window&amp;gt;&lt;/span&gt;&lt;br /&gt;Das Ergebnis sähe hierbei wie folgt aus:&lt;br /&gt;&lt;a href="http://lh3.ggpht.com/_11VTbOPwP_U/TdOqJdruvrI/AAAAAAAAARk/NwuHmjTCbBQ/s1600-h/ApplyDataAnnotations3.png"&gt;&lt;img alt="ApplyDataAnnotations" border="0" height="63" src="http://lh5.ggpht.com/_11VTbOPwP_U/TdOqJzciuxI/AAAAAAAAARo/e50XCOwMAHg/ApplyDataAnnotations_thumb1.png?imgmax=800" style="background-image: none; border-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="ApplyDataAnnotations" width="240" /&gt;&lt;/a&gt;&lt;br /&gt;Für das &lt;em&gt;Required&lt;/em&gt;-Attribut wurde der &lt;em&gt;Required&lt;/em&gt;-Adorner und für den Prompt-Text der &lt;em&gt;CueBanner&lt;/em&gt;-Adorner zugewiesen.&lt;br /&gt;Darüber hinaus werden die folgenden &lt;a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.aspx"&gt;Data Annotations&lt;/a&gt; von &lt;a href="http://uiannotations.codeplex.com/"&gt;TT.UIA&lt;/a&gt; unterstützt:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;EditableAttribute.AllowEdit&lt;/strong&gt;       &lt;br /&gt;Setzt die &lt;i&gt;IsEnabled-&lt;/i&gt;Eigenschaft des zugehörigen Elements. &lt;/li&gt;&lt;li&gt;&lt;strong&gt;RequiredAttribute&lt;/strong&gt;       &lt;br /&gt;Verknüpft das zugehörige Element mit dem &lt;em&gt;Required Adorner&lt;/em&gt;. &lt;/li&gt;&lt;li&gt;&lt;strong&gt;StringLengthAttribute.MaximumLength&lt;/strong&gt;       &lt;br /&gt;Setzt die &lt;i&gt;MaxLength&lt;/i&gt;-Eigenschaft des zugehörigen Eingabesteuerelements (&lt;i&gt;TextBox&lt;/i&gt;, &lt;i&gt;ComboBox&lt;/i&gt; oder &lt;em&gt;DatePicker&lt;/em&gt;). &lt;/li&gt;&lt;li&gt;&lt;strong&gt;DisplayFormatAttribute.DataFormatString&lt;/strong&gt;       &lt;br /&gt;Das Format wird dem &lt;em&gt;Binding&lt;/em&gt;-Objekt des zugehörigen Elements zugewiesen. &lt;/li&gt;&lt;li&gt;&lt;strong&gt;DisplayFormatAttribute.NullDisplayText&lt;/strong&gt;       &lt;br /&gt;Verknüpft das zugehörige Element mit dem &lt;em&gt;CueBanner Adorner&lt;/em&gt;. &lt;/li&gt;&lt;/ul&gt;Darüber hinaus bietet die &lt;strong&gt;Annotations&lt;/strong&gt;-Klasse mit der Attached Property &lt;strong&gt;DescriptionDisplayControl&lt;/strong&gt; die Möglichkeit, Beschreibungstexte die über &lt;strong&gt;DisplayAttribute.Description&lt;/strong&gt; zugewiesen wurden, in einem beliebigen Control anzuzeigen. Beispiel:&lt;br /&gt;&lt;strong&gt;Datenquelle:&lt;/strong&gt;&lt;br /&gt;&lt;span style="font-family: Consolas;"&gt;using System.ComponentModel.DataAnnotations;      &lt;br /&gt;public class Person       &lt;br /&gt;{       &lt;br /&gt;&lt;strong&gt;&amp;nbsp; [Display(Description="The name of the person.")]        &lt;br /&gt;&lt;/strong&gt;&amp;nbsp; [Required]       &lt;br /&gt;&amp;nbsp; [Display(Prompt = "Enter the full name!")]       &lt;br /&gt;&amp;nbsp; public string Name { get; set; }       &lt;br /&gt;} &lt;/span&gt;&lt;br /&gt;&lt;strong&gt;Markup:&lt;/strong&gt;&lt;br /&gt;&lt;span style="font-family: Consolas;"&gt;&amp;lt;Window uia:ApplyDataAnnotations="True"      &lt;br /&gt;&amp;nbsp; &lt;strong&gt;uia:Annotations.DescriptionDisplayControl="{Binding ElementName=descriptionLabel}"&lt;/strong&gt;       &lt;br /&gt;&amp;nbsp; &lt;strong&gt;uia:Annotations.DescriptionDefaultText="Ready."&lt;/strong&gt;&amp;gt;       &lt;br /&gt;&amp;nbsp; …       &lt;br /&gt;&amp;lt;/Window&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;strong&gt;Ergebnis:&lt;/strong&gt;&lt;br /&gt;&lt;a href="http://lh4.ggpht.com/_11VTbOPwP_U/TdOqKQJbfbI/AAAAAAAAARs/wV2QrPi-SSI/s1600-h/DescriptionDisplayControl3.png"&gt;&lt;img alt="DescriptionDisplayControl" border="0" height="240" src="http://lh4.ggpht.com/_11VTbOPwP_U/TdOqLKHUeGI/AAAAAAAAARw/EiW7srpu1XY/DescriptionDisplayControl_thumb1.png?imgmax=800" style="background-image: none; border-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="DescriptionDisplayControl" width="240" /&gt;&lt;/a&gt;&lt;br /&gt;Die Anzeige erfolgt hierbei beim Erhalt des Fokus. Welchen Text das Statuselement anzeigen soll, wenn kein gebundenes Element den Fokus hat, kann über die Eigenschaft &lt;strong&gt;Annotations.DescriptionDefaultText&lt;/strong&gt; festgelegt werden.&lt;br /&gt;Im nächsten Post geht es um den Generic Adorner, mit dem beliebige UI-Elemente als Adorner an andere Element “angehängt“ werden können.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-7056175043006294420?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/7056175043006294420/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=7056175043006294420' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/7056175043006294420'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/7056175043006294420'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2011/05/ttuia-data-annotation-support.html' title='TT.UIA: Data Annotation Support'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_11VTbOPwP_U/TdOqJzciuxI/AAAAAAAAARo/e50XCOwMAHg/s72-c/ApplyDataAnnotations_thumb1.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-7755575448014095731</id><published>2011-05-17T09:01:00.003+02:00</published><updated>2011-05-17T09:30:24.983+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TT.UIA'/><title type='text'>TT.UIA: Adorner</title><content type='html'>Nachdem ich im &lt;a href="http://headwriteline.blogspot.com/2011/05/ttuia-einfuhrung.html"&gt;letzten&lt;/a&gt; Post die Funktionsweise von &lt;a href="http://uiannotations.codeplex.com/"&gt;TT.UIA&lt;/a&gt; vorgestellt habe, soll es nun um die einzelnen Adorner und ihre Anwendung gehen. Doch bevor es losgeht, erkläre ich - zum besseren Verständig - das Prinzip der WPF Adorner noch einmal in ein paar Worten.&lt;br /&gt;&lt;h4&gt;WPF Adorner&lt;/h4&gt;Bei Adornern handelt es sich um grafische Erweiterungen, die zur Laufzeit mit beliebigen Elementen des visuellen Baums verbunden werden können. Hierbei zeichnet der Adorner über die Oberfläche des zugehörigen Controls, bzw. erweitert dieses um zusätzliche Elemente. Adorner sind Teil von WPF und wurden ursprünglich für die Abbildung von Drag &amp;amp; Drop-Funktionalität entwickelt. Sie eignen sich jedoch auch gut für punktuelle Erweiterungen. So werden sie beispielsweise auch bei der Validierungsfunktionalität von WPF verwendet.&lt;br /&gt;&lt;h4&gt;TT.UIA-Adorner&lt;/h4&gt;Für die Zuweisung von Adornern bietet &lt;a href="http://uiannotations.codeplex.com/"&gt;TT.UIA&lt;/a&gt; die zentrale Klasse &lt;strong&gt;Annotations&lt;/strong&gt;. Sie bietet eine Reihe von Attached Properties, die zur Erstellung von Konfiguration dienen. Beispiel:&lt;br /&gt;&lt;span style="font-family: Consolas;"&gt;&amp;lt;TextBox&amp;nbsp; &lt;br /&gt;&amp;nbsp; uia:Annotations.ShowElementTracker="True"       &lt;br /&gt;&amp;nbsp; uia:Annotations.TrackerImageAlignment="Left" /&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;a href="http://lh4.ggpht.com/_11VTbOPwP_U/TdIdO1LiCNI/AAAAAAAAAQU/VmwP_O7y3gA/s1600-h/ElementTracker3.png"&gt;&lt;img alt="ElementTracker" border="0" height="75" src="http://lh4.ggpht.com/_11VTbOPwP_U/TdIdPciExSI/AAAAAAAAAQY/Y5VP5-EZMug/ElementTracker_thumb1.png?imgmax=800" style="background-image: none; border-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="ElementTracker" width="227" /&gt;&lt;/a&gt;&lt;br /&gt;Hier wurde der &lt;strong&gt;ElementTracker&lt;/strong&gt;-Adorner zugewiesen und über die Eigenschaft &lt;em&gt;TrackerImageAlignment&lt;/em&gt; positioniert.&lt;br /&gt;&lt;h4&gt;Adorner per Style zuweisen&lt;/h4&gt;Die Zuweisung per Attached Property hat den Vorteil, dass kein zusätzlicher Code erforderlich ist und sich die Adorner auch per Style zuweisen lassen. Beispiel:&lt;br /&gt;&lt;span style="font-family: Consolas;"&gt;&amp;lt;Style TargetType="{x:Type TextBox}"&amp;gt;      &lt;br /&gt;&amp;nbsp; &amp;lt;Setter Property="uia:Annotations.ShowElementTracker"       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Value="True" /&amp;gt;       &lt;br /&gt;&amp;nbsp; &amp;lt;Setter Property="uia:Annotations.TrackerImageAlignment"       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Value="Left" /&amp;gt;       &lt;br /&gt;&amp;lt;/Style&amp;gt;&lt;/span&gt;&lt;br /&gt;Hier wurde ein impliziter Style definiert, der automatisch allen Textboxen den &lt;em&gt;ElementTracker&lt;/em&gt;-Adorner zuweist. &lt;br /&gt;&lt;h4&gt;Die Adorner-Sammlung von TT.UIA&lt;/h4&gt;&lt;a href="http://uiannotations.codeplex.com/"&gt;TT.UIA&lt;/a&gt; bietet eine Reihe vorgefertigter Adorner. Hier eine kurze Auflistung der entsprechenden Attached Properties mit Beschreibung:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;HighlightOnFocus&lt;/strong&gt; markiert das fokussierte Element mit einem weichen Rahmen.       &lt;br /&gt;&lt;a href="http://lh3.ggpht.com/_11VTbOPwP_U/TdIdPoKehCI/AAAAAAAAAQc/BdyGwWTUGO0/s1600-h/HighlightOnFocus3.png"&gt;&lt;img alt="HighlightOnFocus" border="0" height="67" src="http://lh5.ggpht.com/_11VTbOPwP_U/TdIdP6QjXfI/AAAAAAAAAQg/PZGxoJE-0js/HighlightOnFocus_thumb1.png?imgmax=800" style="background-image: none; border-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="HighlightOnFocus" width="207" /&gt;&lt;/a&gt; &lt;/li&gt;&lt;li&gt;&lt;strong&gt;IsRequired&lt;/strong&gt; markiert ein Pflichtfeld, welches über &lt;strong&gt;RequiredImageAlignment&lt;/strong&gt; positioniert werden kann.       &lt;br /&gt;&lt;a href="http://lh6.ggpht.com/_11VTbOPwP_U/TdIdQIMLYKI/AAAAAAAAAQk/II_wdYeRUbs/s1600-h/Required3.png"&gt;&lt;img alt="Required" border="0" height="66" src="http://lh4.ggpht.com/_11VTbOPwP_U/TdIdQVh43UI/AAAAAAAAAQo/CoDVaQKWLk8/Required_thumb1.png?imgmax=800" style="background-image: none; border-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="Required" width="205" /&gt;&lt;/a&gt; &lt;/li&gt;&lt;li&gt;&lt;strong&gt;ShowEditTracker&lt;/strong&gt; markiert Felder, dessen Wert vom Benutzer geändert wurden. Die Position kann über &lt;strong&gt;TrackerImageAlignment&lt;/strong&gt; festgelegt werden.       &lt;br /&gt;&lt;a href="http://lh5.ggpht.com/_11VTbOPwP_U/TdIdQ3JnG2I/AAAAAAAAAQs/pB1138Gm_9A/s1600-h/EditTracker3.png"&gt;&lt;img alt="EditTracker" border="0" height="58" src="http://lh3.ggpht.com/_11VTbOPwP_U/TdIdRDGwpCI/AAAAAAAAAQw/3KCvbyiYm4k/EditTracker_thumb1.png?imgmax=800" style="background-image: none; border-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="EditTracker" width="240" /&gt;&lt;/a&gt; &lt;/li&gt;&lt;li&gt;&lt;strong&gt;ShowElementTracker&lt;/strong&gt; zeigt ein Symbol vor oder hinter dem aktuell fokussierten Element an. Die Position kann über &lt;strong&gt;TrackerImageAlignment&lt;/strong&gt; festgelegt werden.       &lt;br /&gt;&lt;a href="http://lh3.ggpht.com/_11VTbOPwP_U/TdIdRWnbuII/AAAAAAAAAQ0/nm4zLaD55kA/s1600-h/ElementTracker7.png"&gt;&lt;img alt="ElementTracker" border="0" height="75" src="http://lh6.ggpht.com/_11VTbOPwP_U/TdIdRjkdheI/AAAAAAAAAQ4/6uK29U0QSoM/ElementTracker_thumb3.png?imgmax=800" style="background-image: none; border-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="ElementTracker" width="227" /&gt;&lt;/a&gt; &lt;/li&gt;&lt;li&gt;&lt;strong&gt;AttachErrorTemplate&lt;/strong&gt; verknüpft das Control mit einem &lt;em&gt;Error Template&lt;/em&gt;, das im Fehlerfall angezeigt wird.       &lt;br /&gt;&lt;a href="http://lh6.ggpht.com/_11VTbOPwP_U/TdIdR_2U2_I/AAAAAAAAAQ8/JAWBYwQqQa4/s1600-h/ErrorTemplate3.png"&gt;&lt;img alt="ErrorTemplate" border="0" height="64" src="http://lh5.ggpht.com/_11VTbOPwP_U/TdIdSBLCscI/AAAAAAAAARA/K8SnFs5NSts/ErrorTemplate_thumb1.png?imgmax=800" style="background-image: none; border-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="ErrorTemplate" width="240" /&gt;&lt;/a&gt; &lt;/li&gt;&lt;li&gt;&lt;strong&gt;AttachEditContextMenu&lt;/strong&gt; verknüpft ein Eingabesteuerelement mit einem erweiterten Editor-Context-Menü.       &lt;br /&gt;&lt;a href="http://lh4.ggpht.com/_11VTbOPwP_U/TdIdSaoQCSI/AAAAAAAAARE/O-Oi0pPt9lw/s1600-h/EditContextMenu3.png"&gt;&lt;img alt="EditContextMenu" border="0" height="206" src="http://lh3.ggpht.com/_11VTbOPwP_U/TdIdSqZyc9I/AAAAAAAAARI/LMo-JW_NrUc/EditContextMenu_thumb1.png?imgmax=800" style="background-image: none; border-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="EditContextMenu" width="240" /&gt;&lt;/a&gt; &lt;/li&gt;&lt;li&gt;&lt;strong&gt;AttachEditorToolbar&lt;/strong&gt; verknüpft ein Eingabesteuerelement mit einer Editor-Toolbar.       &lt;br /&gt;&lt;a href="http://lh4.ggpht.com/_11VTbOPwP_U/TdIdTGxVOeI/AAAAAAAAARM/Xd7xIWY9b8M/s1600-h/EditorToolbar3.png"&gt;&lt;img alt="EditorToolbar" border="0" height="97" src="http://lh3.ggpht.com/_11VTbOPwP_U/TdIdTcVD6gI/AAAAAAAAARQ/rKPbgYl64lA/EditorToolbar_thumb1.png?imgmax=800" style="background-image: none; border-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="EditorToolbar" width="238" /&gt;&lt;/a&gt; &lt;/li&gt;&lt;li&gt;&lt;strong&gt;CueBanner&lt;/strong&gt; weist dem zugewiesenen Control ein Wasserzeichentext zu.       &lt;br /&gt;&lt;a href="http://lh3.ggpht.com/_11VTbOPwP_U/TdIdTm5-DDI/AAAAAAAAARU/7euYXpCD-kI/s1600-h/CueBanner3.png"&gt;&lt;img alt="CueBanner" border="0" height="73" src="http://lh5.ggpht.com/_11VTbOPwP_U/TdIdT5abIyI/AAAAAAAAARY/YS7joImRmWI/CueBanner_thumb1.png?imgmax=800" style="background-image: none; border-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="CueBanner" width="206" /&gt;&lt;/a&gt; &lt;/li&gt;&lt;li&gt;&lt;strong&gt;AttachSmartTag&lt;/strong&gt; weist dem zugewiesenen Control einen Smart Tag zu. Dessen Menü muss hierbei über die Eigenschaft &lt;strong&gt;SmartTagMenu&lt;/strong&gt; zugewiesen werden.       &lt;br /&gt;&lt;a href="http://lh3.ggpht.com/_11VTbOPwP_U/TdIdUNqUcaI/AAAAAAAAARc/QTQ0q62XIEw/s1600-h/SmartTag3.png"&gt;&lt;img alt="SmartTag" border="0" height="118" src="http://lh4.ggpht.com/_11VTbOPwP_U/TdIdUnzXDgI/AAAAAAAAARg/gUt42Z72ZM4/SmartTag_thumb1.png?imgmax=800" style="background-image: none; border-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="SmartTag" width="226" /&gt;&lt;/a&gt; &lt;/li&gt;&lt;/ul&gt;Eine detaillierte Beschreibung aller Adorner findet ihr in der &lt;a href="http://uiannotations.codeplex.com/documentation"&gt;Dokumentation&lt;/a&gt; von &lt;a href="http://uiannotations.codeplex.com/"&gt;TT.UIA&lt;/a&gt;, die Implementierungsdetails werde ich in Kürze in der &lt;a href="http://www.dotnetpro.de/"&gt;dotnetpro&lt;/a&gt; veröffentlichen.&lt;br /&gt;Im nächsten Post geht es um die Möglichkeit Adorner automatisch per &lt;a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.aspx"&gt;Data Annotations&lt;/a&gt; zuzuweisen.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-7755575448014095731?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/7755575448014095731/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=7755575448014095731' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/7755575448014095731'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/7755575448014095731'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2011/05/ttuia-adorner.html' title='TT.UIA: Adorner'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_11VTbOPwP_U/TdIdPciExSI/AAAAAAAAAQY/Y5VP5-EZMug/s72-c/ElementTracker_thumb1.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-5870810703722412664</id><published>2011-05-16T14:36:00.002+02:00</published><updated>2011-05-17T09:30:05.496+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TT.UIA'/><title type='text'>TT.UIA: Einführung</title><content type='html'>Die Idee hinter &lt;a href="http://uiannotations.codeplex.com/"&gt;thinktecture UIAnnotations&lt;/a&gt; (TT.UIA) ist es, UI-Interaktionslogik zu kapseln und diese deklarativ an vorhandene Steuerelemente “anzuhängen”. Der Vorteil liegt hierbei in der flexiblen Anwendbarkeit. Wenn man zum Beispiel eine Textbox mit einem Wasserzeichentext (&lt;em&gt;CueBanner&lt;/em&gt;) ausstatten will, gibt es mehrere Möglichkeiten.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Templating&lt;/strong&gt;: Man erstellt ein Custom Template für die Textbox. Dies ist kein leichtes Unterfangen und ohne Code nur sehr schwer zu realisieren. Zudem muss das Template explizit oder implizit zugewiesen werden.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Vererbung&lt;/strong&gt;: Hierbei wird eine Ableitung von Textbox erstellt und mit einem Custom Template verknüpft. Bei diesem Ansatz ist alles zwar schön gekapselt, jedoch funktioniert dies nur für Textboxen – Comboboxen, DatePicker und co. sind hiervon natürlich nicht betroffen. Daher müsste man den Vorgang für diese Controls wiederholen. Und wenn dann noch weitere Features implementiert werden sollen, ist man schnell dabei für die komplette Toolbox Ableitungen zu erstellen.&lt;/li&gt;&lt;/ul&gt;Noch schwieriger wird es, wenn die Erweiterungen nicht nur das Control selbst betreffen. Wenn zum Beispiel neben allen Input Controls, die an Pflichtfelder gebunden sind, ein entsprechendes Symbol erscheinen soll, müssten für alle Control-Typen Custom- oder User Controls erstellt werden.&lt;br /&gt;Aus diesen (und vielen weiteren) Gründe liegt es nahe, die entsprechende Funktionalität mehr oder weniger Control-neutral abzubilden und diese dann im jeweiligen Fall an das gewünschte Control “anzuhängen”. Beispiel:&lt;br /&gt;&lt;span style="font-family: Consolas;"&gt;&amp;lt;TextBox &lt;strong&gt;uia:CueBanner="Enter your name!"&lt;/strong&gt; /&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;a href="http://lh6.ggpht.com/_11VTbOPwP_U/TdEaUBmwu_I/AAAAAAAAAQE/DMaTLtrfp9A/s1600-h/CueBanner%5B3%5D.png"&gt;&lt;img alt="CueBanner" border="0" height="73" src="http://lh6.ggpht.com/_11VTbOPwP_U/TdEaUsKypTI/AAAAAAAAAQI/DAh4ALPlAnY/CueBanner_thumb%5B1%5D.png?imgmax=800" style="background-image: none; border: 0px currentColor; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="CueBanner" width="206" /&gt;&lt;/a&gt;&lt;br /&gt;In diesem Beispiel wird von &lt;a href="http://uiannotations.codeplex.com/"&gt;TT.UIA&lt;/a&gt; ein WPF Adorner erzeugt, der direkt auf die Oberfläche des entsprechenden Controls zeichnet. Dies hat den Vorteil, dass keine Ableitung des Controls erforderlich ist. Zudem kann der Adorner auch außerhalb des Controls zeichnen, was eine leichte Kennzeichnung von Felder (Pflichtfeld, …) ermöglicht.&lt;br /&gt;Für das “Anhängen” von UI-Funktionalität bietet &lt;a href="http://uiannotations.codeplex.com/"&gt;TT.UIA&lt;/a&gt; zwei verschiedene Ansätze: Attached Properties und Expression Blend Behaviors. Beide Varianten haben Ihre Vor- und Nachteile.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Attached Properties&lt;/strong&gt; bestechen durch ihre Einfachheit. Wie im oberen Beispiel dargestellt, können Sie sehr leicht an ein beliebiges Control angehängt werden. Doch der eigentliche Vorteil – gegenüber Behaviors – ist, dass sie auch per Style zugewiesen werden können. &lt;/li&gt;&lt;li&gt;&lt;strong&gt;Expression Blend Behaviors&lt;/strong&gt; sind vor allem für Designer bzw. alle die vornehmlich in Expression Blend entwickeln interessant. Denn Blend bietet eine sehr gute Designer-Unterstützung für Behaviors. XAML-lastige Entwickler mögen sie wegen ihrer ausladenden Syntax hingegen eher weniger. Der wirkliche Vorteil gegenüber Attached Properties ist jedoch, dass man sie mit Events verknüpfen kann.&lt;/li&gt;&lt;/ul&gt;Hier ein Beispiel für die Deklaration eines TT.UIA-Behavior.&lt;br /&gt;&lt;span style="font-family: Consolas;"&gt;&amp;lt;TextBox&amp;gt;     &lt;br /&gt;&amp;nbsp; &amp;lt;i:Interaction.Behaviors&amp;gt;      &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;behaviors:FocusBehavior HighlightBrush="Yellow" /&amp;gt;      &lt;br /&gt;&amp;nbsp; &amp;lt;/i:Interaction.Behaviors&amp;gt;      &lt;br /&gt;&amp;lt;/TextBox&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;a href="http://lh6.ggpht.com/_11VTbOPwP_U/TdEaU3aNBNI/AAAAAAAAAQM/rUU94iIrIUw/s1600-h/FocusBehavior%5B3%5D.png"&gt;&lt;img alt="FocusBehavior" border="0" height="63" src="http://lh3.ggpht.com/_11VTbOPwP_U/TdEaVN1RRHI/AAAAAAAAAQQ/iBHnFk1D0S0/FocusBehavior_thumb%5B1%5D.png?imgmax=800" style="background-image: none; border: 0px currentColor; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="FocusBehavior" width="198" /&gt;&lt;/a&gt;&lt;br /&gt;Hier wird das &lt;strong&gt;FocusBehavior&lt;/strong&gt; verwendet, welches das fokussierte Control in einer beliebigen Farbe einfärbt.&lt;br /&gt;Im nächsten Post stelle ich die einzelnen Adorner und Behaviors von &lt;a href="http://uiannotations.codeplex.com/"&gt;TT.UIA&lt;/a&gt; im Detail vor.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-5870810703722412664?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/5870810703722412664/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=5870810703722412664' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/5870810703722412664'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/5870810703722412664'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2011/05/ttuia-einfuhrung.html' title='TT.UIA: Einführung'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_11VTbOPwP_U/TdEaUsKypTI/AAAAAAAAAQI/DAh4ALPlAnY/s72-c/CueBanner_thumb%5B1%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-8479663518607837744</id><published>2011-05-09T20:32:00.003+02:00</published><updated>2011-05-17T09:30:16.778+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TT.UIA'/><title type='text'>Just Released: thinktecture UIAnnotations</title><content type='html'>Nach mehr als einem Jahr bin ich nun endlich mit meinem &lt;strong&gt;UIAnnotations&lt;/strong&gt;-Projekt fertig!&lt;br /&gt;&lt;a href="http://uiannotations.codeplex.com/"&gt;thinktecture UIAnnotations&lt;/a&gt;&lt;br /&gt;&lt;blockquote&gt;With thinktecture UIAnnotations you can extend your UI with additional functionality via Adorners and Behaviors. All parts are assignable via markup, which is helpful in MVVM scenarios and promotes the developer/designer interaction.     &lt;br /&gt;With &lt;b&gt;thinktecture UIAnnotations&lt;/b&gt; you can declarative attach visual &lt;i&gt;Adorners&lt;/i&gt; and &lt;i&gt;Expression Blend Behaviors&lt;/i&gt; to your user interfaces, including smart tags, editor toolbars and visual state markers for required fields, edit states and more. It also can automatically attach adorners to elements while reflecting the Data Annotations of the associated data sources. For a better MVVM support it offers a generic command behavior that is assignable to every event of a given element. &lt;b&gt;thinktecture UIAnnotations&lt;/b&gt; is available for &lt;b&gt;WPF&lt;/b&gt; and &lt;b&gt;Silverlight&lt;/b&gt; (comming soon).&lt;/blockquote&gt;&lt;b&gt;thinktecture UIAnnotations&lt;/b&gt; in brief: &lt;br /&gt;&lt;ul&gt;&lt;li&gt;10+ useful adorners and 5+ Expression Blend Behaviors. &lt;/li&gt;&lt;li&gt;automatic assignment of adorners via Data Annotations. &lt;/li&gt;&lt;li&gt;a custom adorner model for silverlight (comming soon). &lt;/li&gt;&lt;li&gt;&lt;b&gt;GenericAdorner&lt;/b&gt; allows to attach every element as an adorner. &lt;/li&gt;&lt;li&gt;&lt;b&gt;AdornerBehaviorFactory&lt;/b&gt; that can be used to wrap every adorner as an Expression Blend Behavior. &lt;/li&gt;&lt;li&gt;&lt;b&gt;BehaviorFactory&lt;/b&gt; allows the assignment of Expression Blend Behaviors via styles. &lt;/li&gt;&lt;li&gt;with &lt;b&gt;Command Behavior&lt;/b&gt; you can map every control event to a command.&lt;/li&gt;&lt;/ul&gt;Und da ein Bild mehr sagt als tausend Worte:&lt;br /&gt;&lt;a href="http://lh3.ggpht.com/_11VTbOPwP_U/TcgzSvWMB8I/AAAAAAAAAP8/d2TPEYhVW3M/s1600-h/Showcase%5B252%5D.png"&gt;&lt;img alt="Showcase" border="0" height="295" src="http://lh3.ggpht.com/_11VTbOPwP_U/TcgzVcYNSaI/AAAAAAAAAQA/SGDBmewGUt0/Showcase_thumb%5B250%5D.png?imgmax=800" style="background-image: none; border: 0px currentColor; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="Showcase" width="469" /&gt;&lt;/a&gt;&lt;br /&gt;Die Details folgen in späteren Posts. Stay tuned!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-8479663518607837744?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/8479663518607837744/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=8479663518607837744' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/8479663518607837744'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/8479663518607837744'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2011/05/just-released-thinktecture.html' title='Just Released: thinktecture UIAnnotations'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_11VTbOPwP_U/TcgzVcYNSaI/AAAAAAAAAQA/SGDBmewGUt0/s72-c/Showcase_thumb%5B250%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-1459267075122636038</id><published>2011-04-18T12:58:00.001+02:00</published><updated>2011-04-18T12:58:49.641+02:00</updated><title type='text'>Artikel in der aktuellen dotnetpro</title><content type='html'>&lt;p&gt;In der aktuellen Ausgabe der &lt;a href="http://www.dotnetpro.de"&gt;dotnetpro&lt;/a&gt; (5/2011) ist mein Artikel “&lt;b&gt;Die Qual der Wahl: UI-Technologien im Vergleich&lt;/b&gt;” erschienen.&lt;/p&gt;  &lt;p&gt;Aus dem Abstract:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Für UI-Entwickler wird die Lage zunehmend verwirrender: Da gibt es das gute alte Windows Forms, die Windows Presentation Foundation und Silverlight, und seit Neuestem entbrennt eine Diskussion über das kommende HTML5. Die spannende Frage ist nun: „Auf welche Technologie setze ich als Entwickler in Zukunft?“&lt;/p&gt;    &lt;p&gt;&lt;a href="http://www.dotnetpro.de"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="dnp_052011" border="0" alt="dnp_052011" src="http://lh5.ggpht.com/_11VTbOPwP_U/TawZaFUQEnI/AAAAAAAAAP4/ltyaL1MOizI/dnp_052011%5B3%5D.jpg?imgmax=800" width="134" height="189" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-1459267075122636038?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/1459267075122636038/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=1459267075122636038' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/1459267075122636038'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/1459267075122636038'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2011/04/artikel-in-der-aktuellen-dotnetpro.html' title='Artikel in der aktuellen dotnetpro'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_11VTbOPwP_U/TawZaFUQEnI/AAAAAAAAAP4/ltyaL1MOizI/s72-c/dnp_052011%5B3%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-2549263615169544792</id><published>2011-03-28T15:35:00.002+02:00</published><updated>2011-08-22T09:00:22.435+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TT.DOM'/><title type='text'>TT.DOM Update &amp; Silverlight-Version</title><content type='html'>Nach einer längeren Pause habe ich mich mal wieder um mein TT.DOM-Projekt gekümmert:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://dataobjectmodel.codeplex.com/releases/view/63360"&gt;TT.DOM v0.14 (.NET 4.0)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://dataobjectmodel.codeplex.com/releases/view/63357"&gt;TT.DOM for Silverlight 4&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;Mehr Infos gibt’s &lt;a href="http://dataobjectmodel.codeplex.com/"&gt;hier&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-2549263615169544792?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/2549263615169544792/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=2549263615169544792' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/2549263615169544792'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/2549263615169544792'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2011/03/ttdom-update-silverlight-version.html' title='TT.DOM Update &amp;amp; Silverlight-Version'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-8440257248732385735</id><published>2011-02-28T11:13:00.001+01:00</published><updated>2011-02-28T11:13:40.853+01:00</updated><title type='text'>Die BASTA! geht wieder auf Tour</title><content type='html'>&lt;p&gt;Auch in diesem Jahr geht die BASTA! wieder auf &lt;a href="http://basta-on-tour.de/architecture-best-practices2011/"&gt;Tour&lt;/a&gt;. Die erste Station in diesem Jahr ist Düsseldorf.&lt;/p&gt;  &lt;p&gt;Vom 19.-20. Mai geht es um “Architecture &amp;amp; Good Practices”.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Insgesamt zwei Tage lang bietet Ihnen die BASTA! on Tour – Architecture &amp;amp; Best Practices vier Power Workshops, acht Sessions und ein Speaker Panel mit erstklassigem Know-how zum Thema Architektur und Best Practices in der .NET-Welt. Die bekanntesten Architekturproﬁs zeigen Ihnen wie Sie eine Anwendung professionell aufbauen, welche Strategien besonders erfolgreich sind, welche Stärken und Schwächen verschiedene Technologien haben oder wie Sie bei der Implementierung konkret vorgehen sollten.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Ich konzentriere mich in meinen Sessions (wen wundert’s) auf die Clientseite:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://entwickler.com/konferenzen/ext_scripts/v2/php/sessions-popup.php?module=bastaontour2011&amp;amp;id=17963"&gt;WPF Architecture Patterns&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://entwickler.com/konferenzen/ext_scripts/v2/php/sessions-popup.php?module=bastaontour2011&amp;amp;id=17965"&gt;WPF Tipps &amp;amp; Tricks&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Darüber hinaus bestreite ich einen ganztägigen &lt;a href="http://entwickler.com/konferenzen/ext_scripts/v2/php/sessions-popup.php?module=bastaontour2011&amp;amp;id=17955"&gt;Workshop&lt;/a&gt; über die WPF.&lt;/p&gt;  &lt;p&gt;Vielleicht sieht man sich ja :)&lt;/p&gt;  &lt;p&gt;Weitere Details gibt’s &lt;a href="http://basta-on-tour.de/architecture-best-practices2011/"&gt;hier&lt;/a&gt;. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-8440257248732385735?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/8440257248732385735/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=8440257248732385735' title='1 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/8440257248732385735'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/8440257248732385735'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2011/02/die-basta-geht-wieder-auf-tour.html' title='Die BASTA! geht wieder auf Tour'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-3094321102585707697</id><published>2011-02-28T10:59:00.001+01:00</published><updated>2011-02-28T10:59:27.852+01:00</updated><title type='text'>Slides &amp; Samples von der BASTA! Spring</title><content type='html'>&lt;p&gt;Die Spring-BASTA! hat wieder mächtig Spaß gemacht. Einen Dank an die Teilnehmer meiner Sessions! Hier das Material:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://cid-4029b6652bf3f13f.office.live.com/self.aspx/%c3%96ffentlich/BASTA%202011%20Spring/Neumann%5E_UIGeneration.zip"&gt;Dynamische UI-Generierung mit WPF und Silverlight&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://cid-4029b6652bf3f13f.office.live.com/self.aspx/%c3%96ffentlich/BASTA%202011%20Spring/Neumann%5E_ModulareApps%5E_T1.zip"&gt;Modulare Anwendungsarchitektur mit MVVM und MEF, Teil 1&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://cid-4029b6652bf3f13f.office.live.com/self.aspx/%c3%96ffentlich/BASTA%202011%20Spring/Neumann%5E_ModulareApps%5E_T2.zip"&gt;Modulare Anwendungsarchitektur mit MVVM und MEF, Teil 2&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://cid-4029b6652bf3f13f.office.live.com/self.aspx/%c3%96ffentlich/BASTA%202011%20Spring/Neumann%5E_ModulareAppsWS.zip"&gt;Modulare Anwendungsarchitektur mit WPF und Silverlight&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-3094321102585707697?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/3094321102585707697/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=3094321102585707697' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/3094321102585707697'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/3094321102585707697'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2011/02/slides-samples-von-der-basta-spring.html' title='Slides &amp;amp; Samples von der BASTA! Spring'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-2762013739555189972</id><published>2010-12-21T13:24:00.001+01:00</published><updated>2010-12-21T13:24:01.714+01:00</updated><title type='text'>Zwei neue SQL Server-Bücher</title><content type='html'>&lt;p&gt;Pünktlich zu Weihnachten erscheinen gleich zwei neue SQL Server-Bücher, an denen ich mitgewirkt habe.&lt;/p&gt;  &lt;p&gt;Bei &lt;a href="http://www.microsoft-press.de/"&gt;Microsoft Press&lt;/a&gt;: “&lt;b&gt;&lt;a href="http://www.amazon.de/Microsoft-Server-2008-Entwicklerbuch-Profi-Know-how/dp/3866455143/ref=sr_1_3?s=books&amp;amp;ie=UTF8&amp;amp;qid=1292932105&amp;amp;sr=1-3"&gt;Microsoft SQL Server 2008 R2 - Das Entwicklerbuch&lt;/a&gt;&lt;/b&gt;” (zusammen mit zusammen mit Georg Urban, Klaus Löffelmann und Alexander Köller)&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.amazon.de/Microsoft-Server-2008-Entwicklerbuch-Profi-Know-how/dp/3866455143/ref=sr_1_3?s=books&amp;amp;ie=UTF8&amp;amp;qid=1292932105&amp;amp;sr=1-3"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="CoverMSPress" border="0" alt="CoverMSPress" src="http://lh3.ggpht.com/_11VTbOPwP_U/TRCcXlVIjrI/AAAAAAAAAPk/teSZ48ZV1zw/CoverMSPress%5B4%5D.jpg?imgmax=800" width="240" height="240" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;und bei &lt;a href="http://galileopress.de/"&gt;Galileo Press&lt;/a&gt; die 4. Auflage von “&lt;b&gt;&lt;a href="http://www.amazon.de/SQL-Server-2008-Programmierhandbuch-Installation/dp/3836216930/ref=sr_1_4?s=books&amp;amp;ie=UTF8&amp;amp;qid=1292932105&amp;amp;sr=1-4"&gt;SQL Server 2008 R2 - Das Programmierhandbuch&lt;/a&gt;&lt;/b&gt;” (zusammen mit Dirk Mertins und Andreas Kühnel):&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.amazon.de/SQL-Server-2008-Programmierhandbuch-Installation/dp/3836216930/ref=sr_1_4?s=books&amp;amp;ie=UTF8&amp;amp;qid=1292932105&amp;amp;sr=1-4"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="CoverGalileo" border="0" alt="CoverGalileo" src="http://lh3.ggpht.com/_11VTbOPwP_U/TRCcYOQaWGI/AAAAAAAAAPo/zcNhLLEdYuM/CoverGalileo%5B4%5D.jpg?imgmax=800" width="240" height="240" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-2762013739555189972?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/2762013739555189972/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=2762013739555189972' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/2762013739555189972'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/2762013739555189972'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2010/12/zwei-neue-sql-server-bucher.html' title='Zwei neue SQL Server-Bücher'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_11VTbOPwP_U/TRCcXlVIjrI/AAAAAAAAAPk/teSZ48ZV1zw/s72-c/CoverMSPress%5B4%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-1846782587786919948</id><published>2010-09-27T10:25:00.001+02:00</published><updated>2010-09-27T10:25:39.519+02:00</updated><title type='text'>Slides &amp; Samples von der BASTA!</title><content type='html'>&lt;p&gt;Auch die Herbst-BASTA! hat wieder mächtig Spaß gemacht. Einen Dank an die Teilnehmer meiner Sessions! Hier das Material:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://cid-4029b6652bf3f13f.office.live.com/self.aspx/%c3%96ffentlich/Neumann%5E_MEF.zip"&gt;Entwicklung modularer Anwendungen mit MEF&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://cid-4029b6652bf3f13f.office.live.com/self.aspx/%c3%96ffentlich/Neumann%5E_ComponentDevelopment.zip"&gt;Controls für WPF und Silverlight entwickeln&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://cid-4029b6652bf3f13f.office.live.com/self.aspx/%c3%96ffentlich/MVVMDemo.zip"&gt;.NET End-to-End: verteilt, sicher, pragmatisch&lt;/a&gt;      &lt;br /&gt;(zusammen mit &lt;a href="http://weblogs.thinktecture.com/cweyer/"&gt;Christian Weyer&lt;/a&gt; und &lt;a href="http://www.leastprivilege.com/"&gt;Dominick Baier&lt;/a&gt;)&lt;/li&gt; &lt;/ul&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-1846782587786919948?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/1846782587786919948/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=1846782587786919948' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/1846782587786919948'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/1846782587786919948'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2010/09/slides-samples-von-der-basta.html' title='Slides &amp;amp; Samples von der BASTA!'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-2740697742369571718</id><published>2010-09-10T15:27:00.001+02:00</published><updated>2010-09-10T15:27:59.760+02:00</updated><title type='text'>Slides &amp; Demos von der NRW Conf 2010</title><content type='html'>&lt;p&gt;Auch in diesem Jahr war die &lt;a href="http://www.nrwconf.de/2010"&gt;NRWConf&lt;/a&gt; wieder klasse. Hier das Material meiner Session, die ich mit Jürgen Behrens bestritten habe.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://cid-4029b6652bf3f13f.office.live.com/self.aspx/%c3%96ffentlich/WCF%20Client%20Patterns%20NRW2010.zip"&gt;WCF Client Patterns&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-2740697742369571718?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/2740697742369571718/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=2740697742369571718' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/2740697742369571718'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/2740697742369571718'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2010/09/slides-demos-von-der-nrw-conf-2010.html' title='Slides &amp;amp; Demos von der NRW Conf 2010'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-4066219390605832164</id><published>2010-07-22T07:52:00.001+02:00</published><updated>2010-07-22T07:52:27.096+02:00</updated><title type='text'>Die BASTA! geht wieder auf Tour</title><content type='html'>&lt;p&gt;Zu meiner Freude macht die &lt;a href="www.basta-on-tour.de"&gt;BASTA! ON TOUR&lt;/a&gt; diesmal in Hamburg halt. Vom 15. bis 16. November geht es unter dem Motto &amp;quot;Webanwendungen mit .NET&amp;quot; zwei Tage lang um die Entwicklung von Browser-basierten Anwendungen mit ASP.NET und Silverlight.    &lt;br /&gt;Hierbei werde ich die folgenden zwei Workshops bestreiten:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Silverlight Architecture Patterns&lt;/li&gt;    &lt;li&gt;Silverlight Tipps &amp;amp; Tricks&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Mehr Infos gibt’s auf &lt;a href="www.basta-on-tour.de"&gt;www.basta-on-tour.de&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Vielleicht sieht man sich ja!&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.basta-on-tour.de"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Basta_on_Tour_Banner325x125v2neu rot" border="0" alt="Basta_on_Tour_Banner325x125v2neu rot" src="http://lh5.ggpht.com/_11VTbOPwP_U/TEfcmaec7oI/AAAAAAAAAPY/-67_3qxD2QE/Basta_on_Tour_Banner325x125v2neu%20rot%5B3%5D.jpg?imgmax=800" width="244" height="96" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-4066219390605832164?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/4066219390605832164/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=4066219390605832164' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/4066219390605832164'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/4066219390605832164'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2010/07/die-basta-geht-wieder-auf-tour.html' title='Die BASTA! geht wieder auf Tour'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_11VTbOPwP_U/TEfcmaec7oI/AAAAAAAAAPY/-67_3qxD2QE/s72-c/Basta_on_Tour_Banner325x125v2neu%20rot%5B3%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-9057079029711906618</id><published>2010-07-02T07:52:00.001+02:00</published><updated>2010-07-02T07:52:16.333+02:00</updated><title type='text'>Re-MVPed</title><content type='html'>&lt;p&gt;My MVP award for the &amp;quot;Client App Dev&amp;quot; category has been renewed for another year. Thanks!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-9057079029711906618?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/9057079029711906618/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=9057079029711906618' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/9057079029711906618'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/9057079029711906618'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2010/07/re-mvped.html' title='Re-MVPed'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-7231094330441802502</id><published>2010-06-22T12:55:00.002+02:00</published><updated>2011-08-22T09:02:57.194+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TT.DOM'/><title type='text'>TT.DOM in der aktuellen dotnetpro, Teil 4</title><content type='html'>In der aktuellen Ausgabe der &lt;a href="http://dotnetpro.de/"&gt;dotnetpro&lt;/a&gt; (7/2010) ist der vierte und letzte Teil meiner Artikelserie über die Entwicklung von Datenklassen erschienen. Hierin geht es um den Einsatz von &lt;a href="http://dataobjectmodel.codeplex.com/"&gt;TT.DOM&lt;/a&gt; in verteilten Anwendungen.&lt;br /&gt;Aus dem Abstract:&lt;br /&gt;&lt;blockquote&gt;In verteilten Anwendungen überschreiten Objekte die Prozessgrenze. Dies stellt den Entwickler vor einige Herausforderungen. Dabei spielen nicht nur Themen wie Serialisierung, sondern auch Änderungsverfolgung, Synchronisation und Konkurrenzbehandlung eine Rolle. Darüber hinaus sind Zugriffsrechte sowie kommunikationsspezifische Eigenheiten nicht zu unterschätzen.&lt;/blockquote&gt;&lt;a href="http://www.blogger.com/www.dotnetpro.de"&gt;&lt;img alt="dnp_072010" border="0" height="188" src="http://lh3.ggpht.com/_11VTbOPwP_U/TCCWoxV3m6I/AAAAAAAAAPU/sN2PKrur4mg/dnp_072010%5B4%5D.jpg?imgmax=800" style="border-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" title="dnp_072010" width="134" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-7231094330441802502?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/7231094330441802502/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=7231094330441802502' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/7231094330441802502'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/7231094330441802502'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2010/06/ttdom-in-der-aktuellen-dotnetpro-teil-4.html' title='TT.DOM in der aktuellen dotnetpro, Teil 4'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_11VTbOPwP_U/TCCWoxV3m6I/AAAAAAAAAPU/sN2PKrur4mg/s72-c/dnp_072010%5B4%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-5787220782362644475</id><published>2010-06-01T10:58:00.002+02:00</published><updated>2011-08-22T09:02:47.621+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TT.DOM'/><title type='text'>TT.DOM in der aktuellen DevDorado</title><content type='html'>In der aktuellen Ausgabe der &lt;a href="http://www.devdorado.de/"&gt;DevDorado&lt;/a&gt; (2/2010) ist mein Artikel “Thinktecture.DataObjectModel: Vermittler zwischen den Welten” erschienen. Aus dem Abstract:&lt;br /&gt;&lt;blockquote&gt;Bei der Entwicklung verteilter Anwendungen kommen verschiedenste Technologien zum Einsatz: WCF für die Kommunikation, ein O/R-Mapper für den Datenzugriff, eine Clienttechnologie zur Präsentation und vieles mehr. Das Zusammenspiel funktioniert jedoch nicht immer reibungslos. Besonders bei den Datenobjekten treffen teilweise gegensätzliche Anforderungen aufeinander. Mit dem Thinktecture.DataObjectModel steht ein Open-Source-Framework zur Verfügung, das zwischen den Welten vermittelt und vor allem auf Clientseite eine Menge fehlender Funktionalität nachrüstet.&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-5787220782362644475?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/5787220782362644475/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=5787220782362644475' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/5787220782362644475'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/5787220782362644475'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2010/06/ttdom-in-der-aktuellen-devdorado.html' title='TT.DOM in der aktuellen DevDorado'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-6080038648972152305</id><published>2010-05-20T11:19:00.002+02:00</published><updated>2011-08-22T09:02:37.511+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TT.DOM'/><title type='text'>TT.DOM in der aktuellen dotnetpro, Teil 3</title><content type='html'>In der aktuellen Ausgabe der &lt;a href="http://dotnetpro.de/"&gt;dotnetpro&lt;/a&gt; (6/2010) ist der dritte Teil meiner vierteiligen Artikelserie über die Entwicklung von Datenklassen erschienen. Hierin beschreibe ich das View-Modell von &lt;a href="http://dataobjectmodel.codeplex.com/"&gt;TT.DOM&lt;/a&gt;.&lt;br /&gt;Aus dem Abstract:&lt;br /&gt;&lt;blockquote&gt;Benutzer schätzen es, Darstellungen von Daten individuell anpassen zu können – sortieren oder filtern, Spalten ausblenden oder berechnete Spalten anzeigen. All dies erlaubt normalerweise die DataView-Klasse. Bei eigenen Objekten müssen Sie sich selbst um solche Anforderungen selbst kümmern. Das Thinktecture.DataObjectModel hilft auch hierbei.&lt;/blockquote&gt;&lt;a href="http://dotnetpro.de/"&gt;&lt;img alt="dnp_062010[1]" border="0" height="188" src="http://lh5.ggpht.com/_11VTbOPwP_U/S_T-iKRsWAI/AAAAAAAAAPQ/jq4LV7flN64/dnp_062010%5B1%5D%5B1%5D.jpg?imgmax=800" style="border: 0px currentColor; display: block; float: none; margin-left: auto; margin-right: auto;" title="dnp_062010[1]" width="134" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-6080038648972152305?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/6080038648972152305/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=6080038648972152305' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/6080038648972152305'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/6080038648972152305'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2010/05/ttdom-in-der-aktuellen-dotnetpro-teil-3.html' title='TT.DOM in der aktuellen dotnetpro, Teil 3'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_11VTbOPwP_U/S_T-iKRsWAI/AAAAAAAAAPQ/jq4LV7flN64/s72-c/dnp_062010%5B1%5D%5B1%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-8240116032128808986</id><published>2010-05-20T10:02:00.001+02:00</published><updated>2010-05-20T10:02:49.359+02:00</updated><title type='text'>Slides von der BASTA! ON TOUR</title><content type='html'>&lt;p&gt;Hier die Slides meiner Sessions von der &lt;a href="http://it-republik.de/konferenzen/basta_ontour2010/"&gt;BASTA ON TOUR&lt;/a&gt;:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://cid-4029b6652bf3f13f.skydrive.live.com/self.aspx/%c3%96ffentlich/Neumann%5E_WPFArchitekturmuster.pdf"&gt;WPF Architekturmuster&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://cid-4029b6652bf3f13f.skydrive.live.com/self.aspx/%c3%96ffentlich/Neumann%5E_WPF%5E_TippsTricks.pdf"&gt;WPF Tipps &amp;amp; Tricks&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Vielen Dank an die Teilnehmer! Das hat Spaß gemacht!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-8240116032128808986?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/8240116032128808986/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=8240116032128808986' title='1 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/8240116032128808986'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/8240116032128808986'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2010/05/slides-von-der-basta-on-tour.html' title='Slides von der BASTA! ON TOUR'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-4317736898332732689</id><published>2010-05-12T09:48:00.001+02:00</published><updated>2010-07-02T07:54:41.596+02:00</updated><title type='text'>Externe Change Callbacks für Dependency Properties</title><content type='html'>&lt;p&gt;Neulich kam in einem Training die Frage auf, wie man einen Change Callback an eine Dependency Property hängen kann. Im konkreten Fall ging es darum auf Eingabeänderungen in einer ComboBox zu reagieren. Da diese jedoch kein passendes Event hierfür vorsieht, muss manuell nachgeholfen werden.    &lt;br /&gt;Zwar bieten Dependecy Properties grundsätzlich die Möglichkeit über die Metadaten einen Change Callback einzuhängen, jedoch nur von der Klasse, welche die Property registriert.     &lt;br /&gt;Über die Klasse &lt;strong&gt;DependencyPropertyDescriptor&lt;/strong&gt; kann man jedoch auch einen externen Handler einklinken und sich auf diese Weise - auch ohne Event - über Änderungen informieren lassen.     &lt;br /&gt;Das ganze funktioniert wie folgt: &lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;DependencyPropertyDescriptor desc =      &lt;br /&gt;&amp;#160; DependencyPropertyDescriptor.FromProperty(       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ComboBox.TextProperty, typeof(ComboBox));       &lt;br /&gt;if (desc != null)       &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; desc.AddValueChanged(cbx, (s, e) =&amp;gt; ... );       &lt;br /&gt;} &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Aber wie immer gilt: Abmelden nicht vergessen (&lt;font face="Courier New"&gt;RemoveValueChanged&lt;/font&gt;), damit der Gargabe Collector später aufräumen kann ;)&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-4317736898332732689?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/4317736898332732689/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=4317736898332732689' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/4317736898332732689'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/4317736898332732689'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2010/05/externe-change-callbacks-fur-dependency.html' title='Externe Change Callbacks für Dependency Properties'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-2471284488590076759</id><published>2010-04-16T10:44:00.001+02:00</published><updated>2010-04-16T10:44:51.232+02:00</updated><title type='text'>Die BASTA! geht auf Tour</title><content type='html'>&lt;p&gt;Vom 18.-19. Mai findet in München die erste &lt;a href="http://it-republik.de/konferenzen/basta_ontour2010/"&gt;BASTA! ON TOUR&lt;/a&gt; unter dem Motto “Architecture &amp;amp; Good Practices” statt.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Das neue Tochterevent der BASTA! legt seinen thematischen Schwerpunkt auf .NET-Architekturen. In zwei Tracks, neun Sessions, vier Workshops und einer Keynote&amp;#160; profitieren Sie vom geballten Wissen und der Praxiserfahrung von mehreren der bekanntesten Architektur-Profis der .NET-Welt.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Ich konzentriere mich in meinen Sessions (wen wundert’s) auf die Clientseite:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://entwickler.com/konferenzen/ext_scripts/v2/php/sessions-popup.php?module=basta_ontour2010&amp;amp;id=13872"&gt;WPF-Architekturmuster&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://entwickler.com/konferenzen/ext_scripts/v2/php/sessions-popup.php?module=basta_ontour2010&amp;amp;id=13882"&gt;Tipps &amp;amp; Tricks zu WPF&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Darüber hinaus bestreite ich unter dem Titel “&lt;a href="http://entwickler.com/konferenzen/ext_scripts/v2/php/sessions-popup.php?module=basta_ontour2010&amp;amp;id=13885"&gt;Desktop-Anwendungen mit WPF 4.0&lt;/a&gt;” einen ganztägigen Workshop am 9. Mai.&lt;/p&gt;  &lt;p&gt;Vielleicht sieht man sich ja :)&lt;/p&gt;  &lt;p&gt;&lt;a href="http://it-republik.de/konferenzen/basta_ontour2010/"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="basta-on-tour2" border="0" alt="basta-on-tour2" src="http://lh5.ggpht.com/_11VTbOPwP_U/S8gjgp-mA3I/AAAAAAAAAPM/z-Oa9w2U_GI/bastaontour24.jpg?imgmax=800" width="244" height="93" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-2471284488590076759?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/2471284488590076759/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=2471284488590076759' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/2471284488590076759'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/2471284488590076759'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2010/04/die-basta-geht-auf-tour.html' title='Die BASTA! geht auf Tour'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_11VTbOPwP_U/S8gjgp-mA3I/AAAAAAAAAPM/z-Oa9w2U_GI/s72-c/bastaontour24.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-2258972582550491207</id><published>2010-04-09T08:11:00.002+02:00</published><updated>2011-08-22T09:02:16.872+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TT.DOM'/><title type='text'>TT.DOM in der aktuellen dotnetpro, Teil 2</title><content type='html'>In der aktuellen Ausgabe der dotnetpro (5/2010) ist der zweite Teil meiner vierteiligen Artikelserie über TT.DOM erschienen. Hierin geht es um das Change Tracking und die Transaktionsunterstützung von TT.DOM.&lt;br /&gt;&lt;strong&gt;Aus dem Abstract:&lt;/strong&gt;&lt;br /&gt;&lt;blockquote&gt;Das Verfolgen von Änderungen in eigenen gebundenen Datenobjekten kann zu einer ziemlich komplizierten     &lt;br /&gt;Angelegenheit werden. Das Gleiche gilt für Transaktionen dieser Objekte. Diese sind die Grundlage dafür, Änderungen      &lt;br /&gt;von Objekten wieder rückgängig zu machen. Das Framework Thinktecture.DataObjectModel und sein generisches      &lt;br /&gt;Datenobjektmodell erleichtern dies.&lt;/blockquote&gt;&lt;a href="http://lh3.ggpht.com/_11VTbOPwP_U/S77FFDcAawI/AAAAAAAAAPE/T6JZvfJ_rQk/s1600-h/dnp_052010%5B3%5D.jpg"&gt;&lt;img alt="dnp_052010" border="0" height="188" src="http://lh5.ggpht.com/_11VTbOPwP_U/S77FFyvj-_I/AAAAAAAAAPI/v9u_RSunhQo/dnp_052010_thumb%5B1%5D.jpg?imgmax=800" style="border: 0px currentColor; display: block; float: none; margin-left: auto; margin-right: auto;" title="dnp_052010" width="134" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-2258972582550491207?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/2258972582550491207/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=2258972582550491207' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/2258972582550491207'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/2258972582550491207'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2010/04/ttdom-in-der-aktuellen-dotnetpro-teil-2.html' title='TT.DOM in der aktuellen dotnetpro, Teil 2'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_11VTbOPwP_U/S77FFyvj-_I/AAAAAAAAAPI/v9u_RSunhQo/s72-c/dnp_052010_thumb%5B1%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-1547372802363113657</id><published>2010-03-17T08:30:00.003+01:00</published><updated>2011-08-22T09:02:08.057+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TT.DOM'/><title type='text'>TT.DOM: Views, Teil 2</title><content type='html'>Wie im &lt;a href="http://headwriteline.blogspot.com/2010/03/ttdom-views-teil-1.html"&gt;ersten Teil&lt;/a&gt; bereits beschrieben, bietet &lt;a href="http://dataobjectmodel.codeplex.com/"&gt;TT.DOM&lt;/a&gt; ein View-Modell, das es ermöglicht beliebig viele Sichten auf eine Liste zu erzeugen. Während es zuletzt um die Möglichkeiten ging, Sortier- und Filterkriterien auf die View anzuwenden, möchte ich in diesem Post beschreiben, wie Sie die Darstellung einer View anpassen und um berechnete Spalten erweitern können.&lt;br /&gt;&lt;h4&gt;&lt;strong&gt;Views anpassen&lt;/strong&gt;&lt;/h4&gt;Wie &lt;a href="http://headwriteline.blogspot.com/2010/03/ttdom-views-teil-1.html"&gt;hier&lt;/a&gt; bereit beschrieben, basiert die Anpassbarkeit der Views auf dem Interface &lt;strong&gt;ITypedList&lt;/strong&gt;. Es definiert die &lt;strong&gt;GetItemProperties()&lt;/strong&gt;-Methode, über die das gebundene Listensteuerelement Informationen über die Spalten der Datenquelle abfragt. Sie gibt eine Collection von &lt;strong&gt;PropertyDescriptor&lt;/strong&gt;-Objekten zurück, welche die jeweiligen Eigenschaften beschreiben. Über einen &lt;strong&gt;PropertyDescriptor&lt;/strong&gt; kann beispielsweise festgelegt werden, welchen Anzeigenamen eine Eigenschaft bei der Bindung annehmen soll, ob diese schreibgeschützt ist oder diese ausgeblendet werden soll. Diese Darstellungsmerkmale ermittelt die &lt;strong&gt;PropertyDescriptor&lt;/strong&gt;-Klasse per Reflection aus der Datenklasse. In der Datenklasse können die Merkmale in Form von Attributen signalisiert werden:&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;[Browsable(false)]      &lt;br /&gt;public string Name { get; set; }&lt;/span&gt;&lt;br /&gt;Hierbei können die folgenden Attribute aus dem Namespace &lt;strong&gt;System.ComponentModel&lt;/strong&gt; verwendet werden:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Browsable&lt;/strong&gt; bestimmt, ob die Eigenschaft angezeigt werden soll. &lt;/li&gt;&lt;li&gt;&lt;strong&gt;DisplayName&lt;/strong&gt; gibt den Anzeigenamen an &lt;/li&gt;&lt;li&gt;&lt;strong&gt;ReadOnly&lt;/strong&gt; steuert den Schreibschutz der Spalte &lt;/li&gt;&lt;li&gt;&lt;strong&gt;Description&lt;/strong&gt; liefert eine Beschreibung der Spalte &lt;/li&gt;&lt;/ul&gt;Die folgende Abbildung zeigt die Kommunikation zwischen beteiligten Parteien:&lt;br /&gt;&lt;a href="http://lh4.ggpht.com/_11VTbOPwP_U/S6CFDhtJ4QI/AAAAAAAAAOs/7vSdiFb7jpg/s1600-h/ITypedList4.png"&gt;&lt;img alt="ITypedList" border="0" height="351" src="http://lh4.ggpht.com/_11VTbOPwP_U/S6CFEHsv0iI/AAAAAAAAAOw/JpkF7p48Zj0/ITypedList_thumb2.png?imgmax=800" style="border-width: 0px; display: inline;" title="ITypedList" width="463" /&gt;&lt;/a&gt; &lt;br /&gt;Wie &lt;a href="http://headwriteline.blogspot.com/2010/03/ttdom-runtime-proxies.html"&gt;hier&lt;/a&gt; bereits erwähnt, haben Sie nicht immer Einfluss auf die Datenklasse, sodass Sie unter Umständen die genannten Attribute nicht setzen können. Hierfür bietet &lt;strong&gt;DataObjectView&amp;lt;T&amp;gt;&lt;/strong&gt; die Eigenschaft &lt;strong&gt;ColumnAttributes&lt;/strong&gt;. Sie enthält für jede Eigenschaft der Liste ein &lt;strong&gt;DisplayAttributeInfo&lt;/strong&gt;-Objekt, über das die Darstellung gesteuert werden kann.&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;DataObjectView&amp;lt;Person&amp;gt; view = list.DefaultView;      &lt;br /&gt;view.ColumnAttributes["Id"].Browsable = false;       &lt;br /&gt;view.ColumnAttributes["FirstName"].DisplayName = "Vorname";       &lt;br /&gt;view.ColumnAttributes["LastName"].DisplayName = "Nachname";       &lt;br /&gt;view.ColumnAttributes["LastName"].ReadOnly = true;&lt;/span&gt;&lt;br /&gt;Auf diese Weise können Sie die entsprechenden Anzeigeattribute programmatisch zuweisen, ohne die jeweilige Datenklasse anpassen zu müssen. Zudem kann es vorkommen, dass die Darstellung vom jeweiligen Kontext in der Anwendung abhängt.&lt;br /&gt;Neben den genannten Anzeigeattributen bietet &lt;strong&gt;DisplayAttributeInfo&lt;/strong&gt; über die &lt;strong&gt;Ordinal&lt;/strong&gt;-Eigenschaft die Möglichkeit, die Position der Spalte für die Bindung festzulegen. Alternativ können Sie auch die &lt;strong&gt;SetOrdinal()&lt;/strong&gt;-Methode der View verwenden.&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;list.DefaultView.SetOrdinal(      &lt;br /&gt;&amp;nbsp; "Id", "FirstName", "LastName");&lt;/span&gt;&lt;br /&gt;Um diese Art der Anpassung auch dem Endanwender zu ermöglichen, bietet TT.DOM einen Standarddialog (&lt;em&gt;CustomizeColumnsForm&lt;/em&gt;) mit dem die Darstellung zur Laufzeit angepasst werden kann.&lt;br /&gt;&lt;a href="http://lh3.ggpht.com/_11VTbOPwP_U/S6CFEyuLD4I/AAAAAAAAAO4/RVaxs83nW9k/s1600-h/CustomizeColumns6.png"&gt;&lt;img alt="CustomizeColumns" border="0" height="424" src="http://lh5.ggpht.com/_11VTbOPwP_U/S6CFFeRj9II/AAAAAAAAAO8/NAes-5zHlyA/CustomizeColumns_thumb2.png?imgmax=800" style="border-width: 0px; display: inline;" title="CustomizeColumns" width="458" /&gt;&lt;/a&gt; &lt;br /&gt;&lt;h4&gt;&lt;strong&gt;Berechnete Spalten&lt;/strong&gt;&lt;/h4&gt;Über den &lt;strong&gt;ITypedList&lt;/strong&gt;-Mechanismus stellt TT.DOM auch die Möglichkeit zu Verfügung, dynamisch berechnete Spalten zu definieren. Die Spalten werden hierbei über einen eigene &lt;strong&gt;PropertyDescriptor&lt;/strong&gt;-Ableitung bereitgestellt, welche die Werte über einen Delegate ermitteln.&lt;br /&gt;Die Anlage von berechneten Spalten erfolgt über die &lt;strong&gt;ComputedColumns&lt;/strong&gt;-Eigenschaft von &lt;strong&gt;DataObjectView&amp;lt;T&amp;gt;&lt;/strong&gt;. Hierbei geben Sie lediglich den Namen und den Typ der “virtuellen” Eigenschaft, sowie einen Delegate zur Berechnung an.&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;ComputedColumn col =      &lt;br /&gt;&amp;nbsp; new ComputedColumn("FullName", typeof(string),       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; item =&amp;gt;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ((Person)item).FirstName + " " +       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ((Person)item).LastName);       &lt;br /&gt;_persons.DefaultView.ComputedColumns.Add(col);&lt;/span&gt;&lt;br /&gt;Daraufhin erscheint die Spalte automatisch im gebundenen Listensteuerelement. Das sich der Wert der Spalte automatisch aktualisiert, wenn sich die abhängigen Eigenschaften ändern, brauche ich wohl nicht zu erwähnen ;)&lt;br /&gt;Auch bei dieser Technik besteht der Vorteil vor allem darin, berechnete Spalten bereitzustellen, ohne die zugrunde liegende Datenklasse anpassen zu müssen.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-1547372802363113657?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/1547372802363113657/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=1547372802363113657' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/1547372802363113657'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/1547372802363113657'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2010/03/ttdom-views-teil-2.html' title='TT.DOM: Views, Teil 2'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_11VTbOPwP_U/S6CFEHsv0iI/AAAAAAAAAOw/JpkF7p48Zj0/s72-c/ITypedList_thumb2.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-9094128880565211511</id><published>2010-03-16T09:40:00.003+01:00</published><updated>2011-08-22T09:01:58.778+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TT.DOM'/><title type='text'>TT.DOM: Views, Teil 1</title><content type='html'>Neben der normalen &lt;a href="http://headwriteline.blogspot.com/2010/03/ttdom-datenbindung.html"&gt;Datenbindungsfunktionalität&lt;/a&gt; bietet &lt;a href="http://dataobjectmodel.codeplex.com/"&gt;TT.DOM&lt;/a&gt; ein View-Modell, das es ermöglicht mehrere unterschiedliche Sichten auf die selben Daten zu erstellen. So können Sie beispielsweise verschiedene Filter- und Sortierkriterien, oder Anzeigefelder je Sicht definieren.&lt;br /&gt;Hierbei kommen eine Reihe von Standardinterfaces zum Einsatz, die vom jeweiligen Tabellensteuerelement zur Interaktion mit der Datenquelle verwendet werden.&lt;br /&gt;&lt;a href="http://lh6.ggpht.com/_11VTbOPwP_U/S59D_hAAVLI/AAAAAAAAAN8/T0JplkjnOSY/s1600-h/ViewKonzept4.png"&gt;&lt;img alt="View-Konzept" border="0" height="288" src="http://lh6.ggpht.com/_11VTbOPwP_U/S59D_90PyjI/AAAAAAAAAOA/LPwModyMXu0/ViewKonzept_thumb2.png?imgmax=800" style="border-width: 0px; display: inline;" title="View-Konzept" width="464" /&gt;&lt;/a&gt; &lt;br /&gt;Eine View wird durch die Klasse &lt;strong&gt;DataObjectView&amp;lt;T&amp;gt;&lt;/strong&gt; repräsentiert. Sie implementiert die folgenden Interfaces:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;IBindingListView&lt;/strong&gt; stellt Member für das Filtern und Sortieren bereit. Anders als bei LINQ, werden diese jedoch in Form von Zeichenketten bereitgestellt, was die dynamische Erstellung zur Laufzeit ermöglicht. &lt;/li&gt;&lt;li&gt;&lt;strong&gt;ITypedList&lt;/strong&gt; wird von der Datenbindungsinfrastruktur verwendet, um die anzuzeigenden Eigenschaften der Datenquelle abzufragen. Hierzu stellt die Datenquelle &lt;em&gt;PropertyDescriptor&lt;/em&gt;-Objekte zu Verfügung, die um Anzeigeattribute, wie &lt;em&gt;DisplayName&lt;/em&gt;, &lt;em&gt;ReadOnly&lt;/em&gt; oder &lt;em&gt;Browsable&lt;/em&gt; angereichert werden können. Zudem können Sie über diesen Mechanismus berechnete Spalten bereit stellen, die dynamisch erzeugt werden und nicht in Form von Eigenschaften von der Datenklasse bereitgestellt werden müssen. &lt;/li&gt;&lt;li&gt;&lt;strong&gt;IListSource&lt;/strong&gt; wird von der Listenklasse implementiert und verweist auf die Default View. Auf diese Weise wird beim Binden der Liste auf die Default View verwiesen. Dadurch wirken sich Änderungen der Default View direkt auf die Anzeige aus, auch wenn nicht explizit an diese gebunden wurde. &lt;/li&gt;&lt;/ul&gt;&lt;h4&gt;Views erstellen&lt;/h4&gt;Für den Zugriff auf eine View stellt &lt;strong&gt;DataObjectList&amp;lt;T&amp;gt;&lt;/strong&gt; zwei Möglichkeiten zu Verfügung:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;strong&gt;DefaultView&lt;/strong&gt; liefert die Standardsicht der Liste. Wie oben bereits erwähnt wird diese durch das &lt;strong&gt;IListSource&lt;/strong&gt;-Interface standardmäßig bei der Binding verwendet. &lt;/li&gt;&lt;li&gt;&lt;strong&gt;CreateView()&lt;/strong&gt; erzeugt eine neue View. Auf diese Weise können Sie beliebig viele Views für die Datenquelle erstellen, wobei Änderungen der Daten – sowohl in der View, auch in der Originalliste – automatisch synchronisiert werden. &lt;/li&gt;&lt;/ol&gt;&lt;a href="http://lh3.ggpht.com/_11VTbOPwP_U/S59EARoq4dI/AAAAAAAAAOE/bqyTEcykFMo/s1600-h/ListViewRelation3.png"&gt;&lt;img alt="ListViewRelation" border="0" height="323" src="http://lh5.ggpht.com/_11VTbOPwP_U/S59EBEINcqI/AAAAAAAAAOI/UUXM3E4oHeg/ListViewRelation_thumb1.png?imgmax=800" style="border-width: 0px; display: inline;" title="ListViewRelation" width="461" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;h4&gt;Liste sortieren&lt;/h4&gt;Für das Sortieren von Daten stellen alle Tabellensteuerelemente entsprechende Funktionen bereit. Es macht jedoch durchaus Sinn diese Funktionalität auch über das Objektmodell anzubieten. So müssen Sie nicht direkt mit dem Tabellensteuerelement kommunizieren, was die Kapselung der Logik und die Austauschbarkeit der Controls erhöht. Zudem stellt .NET mit dem Interface &lt;strong&gt;IBindingListView&lt;/strong&gt; einen Mechanismus bereit, der eine Synchronisation zwischen der Liste und dem Anzeigesteuerelement ermöglicht. Auf diese Weise passt sich die Anzeige automatisch der programmatisch zugewiesenen Sortierung an und umgekehrt.&lt;br /&gt;Die Zuweisung des Sortierkriteriums vollzieht sich bei TT.DOM nach dem gleichen Prinzip wie bei der guten, alten &lt;strong&gt;DataView&lt;/strong&gt;-Klasse: Es wird eine Zeichenfolge mit den Sortierfeldern und optional “ASC” oder “DESC” für aufsteigende bzw. absteigende Reihenfolge festgelegt.&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;list.DefaultView.Sort = "FirstName ASC, LastName DESC";&lt;/span&gt;&lt;br /&gt;Wie bereits erwähnt, bietet die String-basierte Zuweisung den Vorteil, diese zur Laufzeit zuweisen und ändern zu können. Auf diese Weise kann auch der Anwender von der Funktionalität profitieren. Hierfür stellt TT.DOM den Dialog &lt;strong&gt;SortForm&lt;/strong&gt; bereit. &lt;br /&gt;&lt;a href="http://lh4.ggpht.com/_11VTbOPwP_U/S59EBvee-tI/AAAAAAAAAOM/q53lg1Tl5Mk/s1600-h/SortDialog3.png"&gt;&lt;img alt="SortDialog" border="0" height="424" src="http://lh4.ggpht.com/_11VTbOPwP_U/S59ECK7Ao6I/AAAAAAAAAOQ/2UKCnHU3Tl8/SortDialog_thumb1.png?imgmax=800" style="border-width: 0px; display: inline;" title="SortDialog" width="458" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;h4&gt;Filter definieren&lt;/h4&gt;Das Filtern der Liste erfolgt über die &lt;strong&gt;Filter&lt;/strong&gt;-Eigenschaft der &lt;strong&gt;DataObjectView&amp;lt;T&amp;gt;&lt;/strong&gt;-Klasse. &lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;view.Filter = "LastName LIKE N*";&lt;/span&gt;&lt;br /&gt;Hierbei wird der Ausdruck dynamisch via CodeDom nach C# konvertiert, kompiliert und auf die Liste angewendet. Die folgende Abbildung zeigt diesen Prozess:&lt;br /&gt;&lt;a href="http://lh3.ggpht.com/_11VTbOPwP_U/S59EC5cYrwI/AAAAAAAAAOU/efQeenNnFxY/s1600-h/Filtern6.png"&gt;&lt;img alt="Filtern" border="0" height="332" src="http://lh4.ggpht.com/_11VTbOPwP_U/S59EDh6CsQI/AAAAAAAAAOY/45t0_6S8Qzw/Filtern_thumb4.png?imgmax=800" style="border-width: 0px; display: inline;" title="Filtern" width="410" /&gt;&lt;/a&gt; &lt;br /&gt;Bei der Syntax orientiert sich die Funktionalität an den Filterausdrücken, die &lt;strong&gt;DataView&lt;/strong&gt; bietet. Die folgenden Ausdrücke sind hierbei möglich: &lt;br /&gt;&lt;table border="1" cellpadding="0" cellspacing="0"&gt;&lt;tbody&gt;&lt;tr&gt;       &lt;td valign="top" width="85"&gt;&lt;strong&gt;Funktion&lt;/strong&gt;&lt;/td&gt;        &lt;td valign="top" width="343"&gt;&lt;strong&gt;Beschreibung&lt;/strong&gt;&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td valign="top" width="85"&gt;Lower()&lt;/td&gt;        &lt;td valign="top" width="343"&gt;Wandelt den Text in Kleinbuchstaben.&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td valign="top" width="85"&gt;Upper()&lt;/td&gt;        &lt;td valign="top" width="343"&gt;Wandelt den Text in Großbuchstaben.&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td valign="top" width="85"&gt;Str()&lt;/td&gt;        &lt;td valign="top" width="343"&gt;Wandelt einen Ausdruck in eine Zeichenfolge.&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td valign="top" width="85"&gt;Trim()&lt;/td&gt;        &lt;td valign="top" width="343"&gt;Entfernt Leerzeichen an Anfang und Ende einer Zeichenfolge.&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td valign="top" width="85"&gt;IsNull()&lt;/td&gt;        &lt;td valign="top" width="343"&gt;Gibt &lt;i&gt;true&lt;/i&gt; zurück, wenn ein Ausdruck den Wert &lt;i&gt;null&lt;/i&gt; enthält.&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td valign="top" width="85"&gt;Round()&lt;/td&gt;        &lt;td valign="top" width="343"&gt;Rundet eine Zahl auf eine bestimmte Anzahl an Nachkommastellen.&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td valign="top" width="85"&gt;Date()&lt;/td&gt;        &lt;td valign="top" width="343"&gt;Wandelt eine Zeichenfolge in ein Datum.&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td valign="top" width="85"&gt;Substring()&lt;/td&gt;        &lt;td valign="top" width="343"&gt;Extrahiert eine Teilzeichenfolge an der angegebenen Stelle.&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td valign="top" width="85"&gt;Len()&lt;/td&gt;        &lt;td valign="top" width="343"&gt;Gibt die Länge einer Zeichenkette zurück.&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td valign="top" width="85"&gt;Year()&lt;/td&gt;        &lt;td valign="top" width="343"&gt;Gibt das Jahr eines Datums zurück.&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td valign="top" width="85"&gt;Month()&lt;/td&gt;        &lt;td valign="top" width="343"&gt;Gibt den Monat eines Datums zurück.&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td valign="top" width="85"&gt;Day()&lt;/td&gt;        &lt;td valign="top" width="343"&gt;Gibt den Tag eines Datums zurück.&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td valign="top" width="85"&gt;Hour()&lt;/td&gt;        &lt;td valign="top" width="343"&gt;Gibt die Stunde eines Datums zurück.&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td valign="top" width="85"&gt;Minute()&lt;/td&gt;        &lt;td valign="top" width="343"&gt;Gibt die Minuten eines Datums zurück.&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td valign="top" width="85"&gt;Second()&lt;/td&gt;        &lt;td valign="top" width="343"&gt;Gibt die Sekunden eines Datums zurück.&lt;/td&gt;     &lt;/tr&gt;&lt;tr&gt;       &lt;td valign="top" width="85"&gt;Millisecond()&lt;/td&gt;        &lt;td valign="top" width="343"&gt;Gibt die Millisekunden eines Datums zurück.&lt;/td&gt;     &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;Damit auch der Benutzer von der Funktionalität profitieren kann, stellt TT.DOM zwei Standarddialoge zu Verfügung – einen für die einfache, Spalten-basierte Filterung und einen Expression Editor für Power User.&lt;br /&gt;&lt;a href="http://lh3.ggpht.com/_11VTbOPwP_U/S59EENc7DZI/AAAAAAAAAOc/R6hGMaVgM6U/s1600-h/FilterColumnsDialog3.png"&gt;&lt;img alt="FilterColumnsDialog" border="0" height="287" src="http://lh5.ggpht.com/_11VTbOPwP_U/S59EEw4-0YI/AAAAAAAAAOg/weMgqlhHUoE/FilterColumnsDialog_thumb1.png?imgmax=800" style="border-width: 0px; display: inline;" title="FilterColumnsDialog" width="461" /&gt;&lt;/a&gt; &lt;br /&gt;&lt;a href="http://lh5.ggpht.com/_11VTbOPwP_U/S59EFdTohzI/AAAAAAAAAOk/jV9zVe9tYZM/s1600-h/FilterDialog5.png"&gt;&lt;img alt="FilterDialog" border="0" height="431" src="http://lh5.ggpht.com/_11VTbOPwP_U/S59EFxoqJFI/AAAAAAAAAOo/5lIVWCv0wSc/FilterDialog_thumb3.png?imgmax=800" style="border-width: 0px; display: inline;" title="FilterDialog" width="464" /&gt;&lt;/a&gt; &lt;br /&gt;Ich könnte mir vorstellen den Filterprozess zukünftig durch Scripting (via &lt;strong&gt;dynamic&lt;/strong&gt; in .NET 4.0) zu ersetzen. Dies würde den komplexen Konvertierungsvorgang überflüssig machen und würde zudem einen reichhaltigeren Sprachumfang bieten.&lt;br /&gt;Wenn sich jemand dazu berufen fühlt, einfach bei mir melden! :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-9094128880565211511?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/9094128880565211511/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=9094128880565211511' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/9094128880565211511'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/9094128880565211511'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2010/03/ttdom-views-teil-1.html' title='TT.DOM: Views, Teil 1'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_11VTbOPwP_U/S59D_90PyjI/AAAAAAAAAOA/LPwModyMXu0/s72-c/ViewKonzept_thumb2.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-6593954158113741627</id><published>2010-03-15T08:48:00.002+01:00</published><updated>2011-08-22T09:01:49.148+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TT.DOM'/><title type='text'>TT.DOM: Transaktionen</title><content type='html'>Wie &lt;a href="http://headwriteline.blogspot.com/2010/03/ttdom-change-tracking.html"&gt;hier&lt;/a&gt; bereit beschrieben, stellt &lt;a href="http://dataobjectmodel.codeplex.com/"&gt;TT.DOM&lt;/a&gt; Unterstützung für Undo/Redo-Transaktionen bereit. Darüber hinaus können &lt;strong&gt;DataObject&lt;/strong&gt;-Ableitungen auch an lokalen oder verteilten Transaktionen teilnehmen – ohne dass Sie dafür etwas tun müssen!&lt;br /&gt;Hierfür setzt TT.DOM auf der Funktionalität von &lt;strong&gt;System.Transactions&lt;/strong&gt; auf. So implementiert z.B. die Basisklasse &lt;strong&gt;DataObject&lt;/strong&gt; das Interface &lt;strong&gt;IEnlistmentNotification&lt;/strong&gt; (Prepare, Commit, Rollback, …). Zudem wird sowohl das implizite, als auch das explizite Programmiermodell von System.Transactions unterstützt.     &lt;br /&gt;Beispiel für das explizite Enlistment:&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;Person p = new Person      &lt;br /&gt;&amp;nbsp; { FirstName = "Jörg", LastName = "Neumann" };       &lt;br /&gt;CommittableTransaction tran =       &lt;br /&gt;&amp;nbsp; new CommittableTransaction();       &lt;br /&gt;tran.EnlistVolatile(p);       &lt;br /&gt;p.FirstName = "Joerg";       &lt;br /&gt;tran.Commit();&lt;/span&gt;&lt;br /&gt;Beispiel für das implizite Enlistment:&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;Person p = new Person      &lt;br /&gt;&amp;nbsp; { FirstName = "Jörg", LastName = "Neumann" };       &lt;br /&gt;using (TransactionScope tx = new TransactionScope())       &lt;br /&gt;{       &lt;br /&gt;&amp;nbsp; p.FirstName = "Joerg";       &lt;br /&gt;&amp;nbsp; tx.Complete();       &lt;br /&gt;}&lt;/span&gt;&lt;br /&gt;Das Ganze kann natürlich auch für auf Listenebene vollzogen und mit anderen transaktionsfähigen Objekten kombiniert werden.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-6593954158113741627?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/6593954158113741627/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=6593954158113741627' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/6593954158113741627'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/6593954158113741627'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2010/03/ttdom-transaktionen.html' title='TT.DOM: Transaktionen'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-4027331646132920745</id><published>2010-03-12T13:39:00.003+01:00</published><updated>2011-08-22T09:01:27.127+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TT.DOM'/><title type='text'>TT.DOM in der aktuellen dotnetpro</title><content type='html'>In der aktuellen Ausgabe der &lt;a href="http://dotnetpro.de/"&gt;dotnetpro&lt;/a&gt; (4/2010) ist der &lt;a href="http://dotnetpro.de/articles/onlinearticle3254.aspx"&gt;erste Teil&lt;/a&gt; meiner vierteiligen Artikelserie über TT.DOM erschienen. Hierin geht es zunächst um die Grundlagen von Datenbindung und Eingabevalidierung in Windows Forms, WPF und Silverlight.&lt;br /&gt;&lt;b&gt;Aus dem Abstract:&lt;/b&gt;&lt;br /&gt;&lt;blockquote&gt;In verteilten Anwendungen spielen Datenklassen eine zentrale Rolle. Doch um diese zu erstellen, an die Oberfläche zu binden und zwischen den Schichten zu transferieren, müssen einige Hürden genommen werden. Hierbei spielen Datenbindung, Änderungsverfolgung und Transaktionsverwaltung eine zentrale Rolle. Haben Ihnen in der Vergangenheit DataSet und Co. den größten Teil der Arbeit abgenommen, müssen Sie sich bei der Entwicklung eigener Datenklassen um Vieles selbst kümmern. dotnetpro beleuchtet in dieser Artikelserie die wichtigsten Grundlagen und stellt ein Objektmodell vor, das ihnen einen Großteil der Arbeit abnimmt.&lt;/blockquote&gt;&lt;a href="http://dotnetpro.de/"&gt;&lt;img alt="dnp_042010" border="0" height="188" src="http://lh3.ggpht.com/_11VTbOPwP_U/S5o2ChZ-rNI/AAAAAAAAAN4/wgrVCzzL2BM/dnp_042010%5B4%5D.jpg?imgmax=800" style="border: 0px currentColor; display: block; float: none; margin-left: auto; margin-right: auto;" title="dnp_042010" width="134" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-4027331646132920745?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/4027331646132920745/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=4027331646132920745' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/4027331646132920745'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/4027331646132920745'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2010/03/ttdom-in-der-aktuellen-dotnetpro.html' title='TT.DOM in der aktuellen dotnetpro'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_11VTbOPwP_U/S5o2ChZ-rNI/AAAAAAAAAN4/wgrVCzzL2BM/s72-c/dnp_042010%5B4%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-7602831204632399272</id><published>2010-03-11T10:48:00.004+01:00</published><updated>2011-08-22T09:01:15.426+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TT.DOM'/><title type='text'>TT.DOM: Runtime Proxies</title><content type='html'>Bei TT.DOM steckt der Hauptteil der Logik in der Basisklasse &lt;strong&gt;DataObject&lt;/strong&gt;. Von dieser leitet die jeweilige Datenklasse ab und hat dadurch Zugriff auf die Funktionalität. Doch was ist, wenn die Datenklasse bereits von einer anderen Basisklasse ableitet? Dies kann beispielsweise der Fall sein, wenn die Datenklassen in Form eines Entity Framework Modells vorliegen. Vielleicht wollen Sie auf Severseite auch nicht von einer Basisklasse ableiten, um Interoperabilität zu gewährleisten. Ein anderer Fall ist, wenn Sie sich WCF Proxy-Klassen von Visual Studio generieren lassen. In diesem Fall haben Sie keinen Einfluss auf die Basisklasse der Data Contracts.&lt;br /&gt;Für solche Fälle bietet TT.DOM die Möglichkeit, dynamische Runtime Proxies für die Objekte zu erzeugen. Hierbei handelt es sich um Typen, die per &lt;strong&gt;Reflection.Emit&lt;/strong&gt; zur Laufzeit erzeugt werden und einen Wrapper um die Datenklasse bilden.&lt;br /&gt;Ein Runtime Proxy-Typ leitet von &lt;strong&gt;DataObject&lt;/strong&gt; ab und enthält die selben Eigenschaften wie die jeweilige Datenklasse. In den Gettern und Settern der Eigenschaft werden die Anfragen an das Datenobjekt delegiert, welches zuvor im Konstruktor übergeben wurde. Das Ganze sieht dann in etwa wie folgt aus:&lt;br /&gt;&lt;a href="http://lh5.ggpht.com/_11VTbOPwP_U/S5i8eGfMWmI/AAAAAAAAANw/mLARXwdGwwE/s1600-h/DataObjectProxy%5B3%5D.png"&gt;&lt;img alt="DataObjectProxy" border="0" height="305" src="http://lh4.ggpht.com/_11VTbOPwP_U/S5i8ep8latI/AAAAAAAAAN0/Zf0dRqBT3jU/DataObjectProxy_thumb%5B1%5D.png?imgmax=800" style="border: 0px currentColor; display: inline;" title="DataObjectProxy" width="463" /&gt;&lt;/a&gt; &lt;br /&gt;Das folgende Beispiel zeigt den Code einer Proxyklasse für die fiktive Klasse &lt;strong&gt;Person&lt;/strong&gt;.&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;public class Person_Proxy : DataObject     &lt;br /&gt;{      &lt;br /&gt;&amp;nbsp; private Person _originalObject;      &lt;br /&gt;&lt;br /&gt;&amp;nbsp; public Person_Proxy(Person person1)      &lt;br /&gt;&amp;nbsp; {      &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; this._originalObject = person1;      &lt;br /&gt;&amp;nbsp; }      &lt;br /&gt;&lt;br /&gt;&amp;nbsp; public string FirstName      &lt;br /&gt;&amp;nbsp; {      &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; get { return this._originalObject.FirstName; }      &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; set      &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {      &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; base.OnPropertyChanging("FirstName");      &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this._originalObject.FirstName = value;      &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; base.OnPropertyChanged("FirstName");      &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }      &lt;br /&gt;&amp;nbsp; }      &lt;br /&gt;&amp;nbsp; ...      &lt;br /&gt;}&lt;/span&gt;&lt;br /&gt;&lt;h4&gt;Proxyliste erzeugen&lt;/h4&gt;Die einfachste Art Runtime Proxies zu erzeugen, ist über die Extension Method &lt;strong&gt;.ToDataObjectListProxy()&lt;/strong&gt;, welche auf alle Listen vom Typ &lt;strong&gt;IEnumerable&lt;/strong&gt; angewendet werden kann. Hierbei wird ein Runtime Proxy für den jeweiligen Objekttyp erstellt und die Objekte in eine Liste vom Typ &lt;strong&gt;DataObjectList&amp;lt;T&amp;gt;&lt;/strong&gt; gefüllt. Da &lt;strong&gt;T&lt;/strong&gt; an dieser stelle den jeweiligen Proxy-Typ repräsentiert, können Sie die Liste nicht direkt verwenden (da ja der Proxy-Typ zur Entwurfszeit noch nicht existiert). Stattdessen gibt &lt;strong&gt;.ToDataObjectListProxy()&lt;/strong&gt; eine Instanz von &lt;strong&gt;IDataObjectProxyList&lt;/strong&gt; zurück, über die Sie die Member von &lt;strong&gt;DataObjectList&amp;lt;T&amp;gt;&lt;/strong&gt; ansprechen können.&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;List&amp;lt;Person&amp;gt; results = personService.GetPersons();     &lt;br /&gt;IDataObjectProxyList list = results.ToDataObjectListProxy("Id");      &lt;br /&gt;list.BeginEdit();      &lt;br /&gt;... &lt;/span&gt;&lt;br /&gt;&lt;h4&gt;Proxies manuell erzeugen&lt;/h4&gt;Zudem besteht auch die Möglichkeit Runtime Proxies manuell zu erzeugen. Hierfür stellt TT.DOM die Klasse &lt;strong&gt;ProxyFactory&lt;/strong&gt; zu Verfügung. Diese stellt Methoden zur Erzeugung von Proxytypen, Objekten und Listen bereit.&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;&lt;strong&gt;// Proxytyp erstellen       &lt;br /&gt;&lt;/strong&gt;ProxyFactory factory = new ProxyFactory();      &lt;br /&gt;Type proxyType =       &lt;br /&gt;&amp;nbsp; factory.CreateProxyType(typeof(Person), attributes);      &lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: Courier New;"&gt;&lt;strong&gt;// Proxyobjekt erstellen       &lt;br /&gt;&lt;/strong&gt;DataObject obj = (DataObject)      &lt;br /&gt;&amp;nbsp; factory.CreateProxy(proxyType, person1);      &lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: Courier New;"&gt;&lt;strong&gt;// Proxyliste erstellen       &lt;br /&gt;&lt;/strong&gt;IDataObjectProxyList proxyList =       &lt;br /&gt;&amp;nbsp; factory.CreateProxyCollection(proxyType, sourceList);      &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;// Objekt der Liste hinzufügen       &lt;br /&gt;&lt;/strong&gt;Person p = new Person() { FirstName = "Jörg" };      &lt;br /&gt;factory.Add(proxyList, p, typeof(Person)); &lt;/span&gt;&lt;br /&gt;Bei der Erstellung eines Proxytyps können Sie zusätzliche Anzeigeattribute, wie &lt;strong&gt;Browsable&lt;/strong&gt;, &lt;strong&gt;ReadOnly&lt;/strong&gt;, oder &lt;strong&gt;DisplayName&lt;/strong&gt; angeben, mit denen die Eigenschaften des Proxytyps entsprechend dekoriert werden. Hierdurch können Sie Einfluss auf die Datenbindung nehmen (wie &lt;a href="http://headwriteline.blogspot.com/2006/10/entwurfszeit-attribute-teil-4-data.html"&gt;hier&lt;/a&gt; beschrieben). Zudem können Sie programmatisch Validierungsregeln einbringen, die von der Proxyklasse über das Interface &lt;strong&gt;IDataErrorInfo&lt;/strong&gt; abgebildet werden, doch dazu mehr in einem separaten Post.&lt;br /&gt;&lt;h4&gt;Verwendung der Proxyobjekte&lt;/h4&gt;Die Verwendung der Runtime Proxies bietet sich vor allem in Szenarien an, in denen die Objekte vor allem an die Oberfläche gebunden werden. Beim programmatischen Zugriff ergeben sich einige Besonderheiten. Da der Proxytyp nicht von der Datenklasse ableitet, können Sie nicht auf diese casten, was zur Folge hat, dass Sie nicht typisiert auf dessen Eigenschaften zugreifen können. Stattdessen bieten &lt;strong&gt;DataObject&lt;/strong&gt; und &lt;strong&gt;IDataObjectProxyList&lt;/strong&gt; entsprechende Zugriffsmethoden an.&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;DataObject.GetValue(string propertyName);     &lt;br /&gt;DataObject.SetValue(string propertyName, object value);&lt;/span&gt;&lt;br /&gt;Alternativ können Sie sich aber auch das zugehörige Datenobjekt ermitteln.&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;Person p = proxyList.GetDataObject(0);     &lt;br /&gt;string firstName = p.FirstName;&lt;/span&gt;&lt;br /&gt;Dies bietet sich besonders beim lesenden Zugriff an. Der schreibende Zugriff sollte jedoch immer über die &lt;strong&gt;SetValue()&lt;/strong&gt;-Methode durchgeführt werden, da nur in diesem Fall die Änderung vom Change Tracking bzw. von der Undo-/Redo-Funktionalität berücksichtigt wird.&lt;br /&gt;Das ist der Preis, den Sie für die Flexibilität zahlen müssen ;)&lt;br /&gt;&lt;h4&gt;Ableitung vs. Delegation&lt;/h4&gt;Das TT.DOM-Proxyverfahren unterscheidet sich von den üblichen Proxy-Generierungskonzepten. So leiten z.B. die Proxies von EF4 direkt von der jeweiligen Datenklasse ab und delegieren die Änderungen an einen zentralen State Manager weiter. Dies hat den Vorteil, dass Sie die Proxies auf den Typ Ihrer Datenklasse casten und somit typisiert auf dessen Eigenschaften zugreifen können.&lt;br /&gt;Damit dieses Verfahren jedoch funktioniert, muss die Datenklasse sämtliche Eigenschaften als &lt;strong&gt;virtual&lt;/strong&gt; definieren. Da dies jedoch nicht immer vorausgesetzt werden kann und auch nicht vom WCF Proxy Generator unterstützt wird, habe ich mich bei meiner Implementierung dagegen entschieden. Zudem ist es auch beim EF4-Ansatz zwingend erforderlich neue Objektinstanzen über eine Factory zu erzeugen, um Change Tracking zu gewährleisten.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-7602831204632399272?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/7602831204632399272/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=7602831204632399272' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/7602831204632399272'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/7602831204632399272'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2010/03/ttdom-runtime-proxies.html' title='TT.DOM: Runtime Proxies'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_11VTbOPwP_U/S5i8ep8latI/AAAAAAAAAN0/Zf0dRqBT3jU/s72-c/DataObjectProxy_thumb%5B1%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-8506296195770793685</id><published>2010-03-10T16:55:00.002+01:00</published><updated>2011-08-22T09:01:01.676+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TT.DOM'/><title type='text'>TT.DOM: Change Tracking</title><content type='html'>Wie im letzten &lt;a href="http://headwriteline.blogspot.com/2010/03/ttdom-datenbindung.html"&gt;Post&lt;/a&gt; bereits beschrieben, stellt TT.DOM mit der Basisklasse &lt;strong&gt;DataObject&lt;/strong&gt; eine Reihe von Datenbindungsfunktionen bereit.&lt;br /&gt;Darüber hinaus ist &lt;strong&gt;DataObject&lt;/strong&gt; aber auch in der Lage, automatisch die Originalwerte der geänderten Eigenschaften eines Objekts zu speichern. Dies ist vor allem für eine spätere Datenbankaktualisierung hilfreich. Die Änderungsverfolgung muss jedoch explizit aktiviert werden, um zu vermeiden, dass Änderungen bereits beim Befüllen der Objekte protokolliert werden. Hierfür bietet &lt;strong&gt;DataObject&lt;/strong&gt; und &lt;strong&gt;DataObjectList&amp;lt;T&amp;gt;&lt;/strong&gt; die Methode &lt;strong&gt;BeginEdit()&lt;/strong&gt;. &lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;List&amp;lt;Person&amp;gt; persons = service.GetPersons();      &lt;br /&gt;var list = persons.ToDataObjectList("Id");       &lt;br /&gt;list.&lt;strong&gt;BeginEdit()&lt;/strong&gt;;&lt;/span&gt;&lt;br /&gt;Zudem kann die Änderungsverfolgung auch durch Setzen der &lt;strong&gt;Mode&lt;/strong&gt;-Eigenschaft auf Objektebene festgelegt werden.&lt;br /&gt;Um festzustellen, welche Datenobjekte geändert wurden, können Sie die &lt;strong&gt;State&lt;/strong&gt;-Eigenschaft abfragen. Diese enthält je nach Änderung den Wert &lt;strong&gt;Unchanged&lt;/strong&gt;, &lt;strong&gt;Insert&lt;/strong&gt;, &lt;strong&gt;Update&lt;/strong&gt; oder &lt;strong&gt;Delete&lt;/strong&gt;.&lt;br /&gt;Über die Methode &lt;strong&gt;GetChanges()&lt;/strong&gt; können die geänderten Objekte abgefragt werden.&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;List&amp;lt;Person&amp;gt; changes = list.GetChanges();&lt;/span&gt;&lt;br /&gt;Alternativ können auch Änderungen eines bestimmten Typs abgefragt werden.&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;List&amp;lt;Person&amp;gt; updates =&amp;nbsp; &lt;br /&gt;&amp;nbsp; list.GetChanges(DataObjectStateType.Update);&lt;/span&gt;&lt;br /&gt;Wollen Sie die Änderungen an einen WCF-Service übertragen, können Sie die Methode &lt;strong&gt;SaveChanges()&lt;/strong&gt; nutzen. Diese nimmt drei Function Delegates für die Methoden Update Insert und Delete entgegen.&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;list.SaveChanges&amp;lt;Customer&amp;gt;(      &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; c =&amp;gt; service.UpdateCustomer(c),       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; c =&amp;gt; service.InsertCustomer(c),       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; c =&amp;gt; service.DeleteCustomer(c));&lt;/span&gt;&lt;br /&gt;Hierbei wird davon ausgegangen, dass ein WCF-Service Proxy mit folgender Signatur existiert:&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;public Person UpdatePerson(Person p);      &lt;br /&gt;public Person InsertPerson(Person p);       &lt;br /&gt;public void DeletePerson(Person p);&lt;/span&gt;&lt;br /&gt;Alternativ können Sie auch alle Änderungen an den Service übertragen und serverseitig auf den jeweiligen Änderungstyp filtern.&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;List&amp;lt;Person&amp;gt; changes = list.GetChanges();      &lt;br /&gt;service.UpdatePersons(changes);&lt;/span&gt;&lt;br /&gt;Auf Serverseite können Sie daraufhin den Status der Objekte, sowie deren Originalwerte ermitteln.&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;public List&amp;lt;Person&amp;gt; UpdatePersons(List&amp;lt;Person&amp;gt; changes)      &lt;br /&gt;{       &lt;br /&gt;&amp;nbsp; foreach (Person p in changes)       &lt;br /&gt;&amp;nbsp; {       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; switch (&lt;strong&gt;p.State&lt;/strong&gt;)       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; case DataObjectStateType.Update:       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var orgValue = &lt;strong&gt;p.GetOriginalValue("Name");&lt;/strong&gt;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Datensatz in DB aktualisieren       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; …       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }       &lt;br /&gt;&amp;nbsp; }       &lt;br /&gt;}&lt;/span&gt;&lt;br /&gt;Hierbei sollte die Service-Methode nicht nur eine Liste der Objekte entgegen nehmen, sondern auch zurückgeben. Dies ist erforderlich, da auf Datenbankseite z.B. Identity-Werte oder Timestamps vergeben werden, die an den Client zurück synchronisiert werden müssen.&lt;br /&gt;Hierfür können Sie auf Clientseite die Methode &lt;strong&gt;MergeItems()&lt;/strong&gt; aufrufen und die lokale Liste mit der serverseitigen synchronisieren.&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;List&amp;lt;Person&amp;gt; changes = list.GetChanges();      &lt;br /&gt;List&amp;lt;Person&amp;gt; refrehedList =       &lt;br /&gt;&amp;nbsp; service.UpdatePersons(changes);       &lt;br /&gt;&lt;strong&gt;list.MergeItems(refreshedList);&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;Wenn Sie jedoch oben genannte &lt;strong&gt;SaveChanges()&lt;/strong&gt;-Methode aufrufen, können Sie sich diesen separaten Schritt sparen, da dieser automatisch durchgeführt wird.&lt;br /&gt;&lt;h4&gt;&lt;strong&gt;Undo/Redo&lt;/strong&gt;&lt;/h4&gt;Neben dem Speichern der Originalwerte, kann &lt;strong&gt;DataObject&lt;/strong&gt; und &lt;strong&gt;DataObjectList&amp;lt;T&amp;gt;&lt;/strong&gt; auch beliebige Änderungen rückgängig machen bzw. wiederholen. Beide Klassen bieten hierfür die Methoden &lt;strong&gt;Undo()&lt;/strong&gt; und &lt;strong&gt;Redo()&lt;/strong&gt;. Darüber hinaus können Sie auch einen benannten Undo-Punkt definieren, zu dem zurückgesprungen werden soll. Hierfür legen Sie zunächst über die Methode &lt;strong&gt;SetUndoPoint()&lt;/strong&gt; einen Punkt an und geben diesem einen beliebigen Namen. Einer Überladung der &lt;strong&gt;Undo()&lt;/strong&gt;-Methode können Sie daraufhin den Namen übergeben und alle bis dahin durchgeführten Änderungen werden entsprechen zurückgerollt.&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;&lt;strong&gt;list.SetUndoPoint("MyUndoPoint");        &lt;br /&gt;&lt;/strong&gt;list[0].Name += "*";       &lt;br /&gt;list.Add(new Person() { Name = "Bob" };       &lt;br /&gt;list.Remove(1);       &lt;br /&gt;&lt;strong&gt;list.Undo("MyUndoPoint");&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;Wenn Sie mitbekommen wollen, ob sich die Undo- oder Redo-Liste geändert hat, können Sie sich auf das &lt;strong&gt;UndoListChanged&lt;/strong&gt; bzw. &lt;strong&gt;RedoListChanged&lt;/strong&gt;-Event anmelden.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-8506296195770793685?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/8506296195770793685/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=8506296195770793685' title='2 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/8506296195770793685'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/8506296195770793685'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2010/03/ttdom-change-tracking.html' title='TT.DOM: Change Tracking'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-7248184721556739681</id><published>2010-03-09T07:34:00.002+01:00</published><updated>2011-08-22T09:00:52.302+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TT.DOM'/><title type='text'>TT.DOM: Datenbindung</title><content type='html'>Wie &lt;a href="http://headwriteline.blogspot.com/2010/03/just-released-thinktecturedataobjectmod.html"&gt;hier&lt;/a&gt; bereits erwähnt, unterstützt &lt;a href="http://dataobjectmodel.codeplex.com/"&gt;Thinktecture.DataObjectModel&lt;/a&gt; (TT.DOM) die Entwicklung flexibler Datenklassen. In den folgenden Posts werde ich die wichtigsten Features des Frameworks vorstellen. Den Anfang mache ich mit dem Thema Datenbindung.&lt;br /&gt;Damit ein Objekt optimal an die Oberfläche gebunden werden kann, sollte die entsprechende Klasse eine Reihe von Interfaces implementieren. Über diese kommuniziert die Datenbindungsinfrastruktur mit den gebundenen Objekten um z.B. Synchronisation, Transaktionssteuerung oder Eingabevalidierung zu realisieren. Die folgende Abbildung zeigt diese Kommunikation:&lt;br /&gt;&lt;a href="http://lh5.ggpht.com/_11VTbOPwP_U/S5Xr9l_1BaI/AAAAAAAAANc/keiDNvpT58I/s1600-h/Neumann_Datenklassen2%5B6%5D.png"&gt;&lt;img alt="Neumann_Datenklassen2" border="0" height="316" src="http://lh4.ggpht.com/_11VTbOPwP_U/S5Xr-PgSKgI/AAAAAAAAANg/miuBbRT0NtM/Neumann_Datenklassen2_thumb%5B5%5D.png?imgmax=800" style="border: 0px currentColor; display: inline;" title="Neumann_Datenklassen2" width="459" /&gt;&lt;/a&gt; &lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;INotifyPropertyChanged&lt;/strong&gt; dient zur Synchronisation zwischen Datenquelle und Ziel. Auf diese Weise werden Änderungen, die programmatisch an den Objekten durchgeführt werden, an das gebundene Steuerelement gemeldet, sodass dieses die Anzeige entsprechend aktualisieren kann. &lt;/li&gt;&lt;li&gt;&lt;strong&gt;INotifyPropertyChanging&lt;/strong&gt; dient zur Signalisierung von Änderungen, bevor diese durchgeführt werden. Dies Interface hat keine direkten Auswirkungen für die Bindung, ist jedoch für Change Tracking und Transaktionssteuerung wichtig. &lt;/li&gt;&lt;li&gt;&lt;strong&gt;IEditableObject&lt;/strong&gt; stellt ein transaktionales Verhalten für die Datenbindung bereit. So können Sie beispielsweise mehrere Zellen in einem Grid geändert und per ESC wieder zurück gerollt werden. &lt;/li&gt;&lt;li&gt;&lt;strong&gt;IDataErrorInfo&lt;/strong&gt; ist für die clientseitige Validierung zuständig. So kann der Benutzer bereits während der Eingabe auf fehlerhafte Werte aufmerksam gemacht werden. &lt;/li&gt;&lt;/ul&gt;Wie Sie sehen, gibt es eine Menge zu tun um eine Datenklassen für die Datenbindung zu optimieren. &lt;br /&gt;Hier kommt TT.DOM ins Spiel. Es definiert die abstrakte Basisklasse &lt;strong&gt;DataObject&lt;/strong&gt;, welche die oben genannten Interfaces implementiert. Sie können nun Ihre Datenklassen von &lt;strong&gt;DataObject&lt;/strong&gt; ableiten und haben fast automatisch die entsprechenden Funktionalitäten. Das Einzige was Sie tun müssen, ist Änderungen an Ihren Properties an die Basisklasse zu melden.&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;public class Person : &lt;strong&gt;DataObject&lt;/strong&gt;       &lt;br /&gt;{       &lt;br /&gt;&amp;nbsp; private string _name;       &lt;br /&gt;&amp;nbsp; public string Name       &lt;br /&gt;&amp;nbsp; {       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; get { return _name; }       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; set&lt;/span&gt;     &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-family: Courier New;"&gt;{      &lt;br /&gt;&amp;nbsp;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; base.OnPropertyChanging("Name");        &lt;br /&gt;&lt;/strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _name = value;       &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;strong&gt;base.OnPropertyChanged(“Name”)&lt;/strong&gt;; }       &lt;br /&gt;&amp;nbsp; }       &lt;br /&gt;}&lt;/span&gt;&lt;br /&gt;Wollen Sie zusätzlich Validierungsregeln im Stile von &lt;strong&gt;IDataErrorInfo&lt;/strong&gt; in der Datenklasse hinterlegen, überschreiben Sie zusätzlich den Indexer der Basisklasse und hinterlegen die Validierungsregeln nach folgendem Muster.&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;public class Person : &lt;strong&gt;DataObject&lt;/strong&gt;     &lt;br /&gt;{     &lt;br /&gt;&amp;nbsp; ...     &lt;br /&gt;&amp;nbsp; &lt;strong&gt;public override string this[string columnName]&lt;/strong&gt;     &lt;br /&gt;&amp;nbsp; {     &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; get     &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {     &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ((columnName == "" || columnName == "Name") &amp;amp;&amp;amp;     &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string.IsNullOrEmpty(this.FirstName))     &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {     &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return "\"Name\" ist ein Pflichtfeld!";     &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }     &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return string.Empty;     &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }     &lt;br /&gt;&amp;nbsp; }     &lt;br /&gt;}&lt;/span&gt;   &lt;br /&gt;&lt;h4&gt;&lt;/h4&gt;&lt;h4&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/h4&gt;&lt;h4&gt;&lt;/h4&gt;Auf diese Weise haben Sie Ihre Klasse ohne viel Aufwand mit Synchronisation, Transaktionssteuerung und Eingabevalidierung ausgestattet. &lt;br /&gt;Wie Sie später noch sehen werden, bietet TT.DOM auch die Möglichkeit die Validierungsregeln programmatisch zur Laufzeit zu hinterlegen.&lt;br /&gt;&lt;h4&gt;Listenbindung&lt;/h4&gt;Auch auf Listenebene müssen Sie für eine Synchronisation zwischen Datenquelle und Ziel sorgen. In Windows Forms und WPF können Sie hierfür das Interface &lt;strong&gt;IBindingList&lt;/strong&gt; bzw. dessen Standardimplementierung &lt;strong&gt;BindingList&amp;lt;T&amp;gt;&lt;/strong&gt; verwenden. Darüber hinaus stellt TT.DOM die Klasse &lt;strong&gt;DataObjectList&amp;lt;T&amp;gt;&lt;/strong&gt; bereit. Diese leitet von &lt;strong&gt;BindingList&amp;lt;T&amp;gt;&lt;/strong&gt; ab und stellt neben der Datenbindungsfunktionalität Einiges mehr zu Verfügung.&lt;br /&gt;Um das Erstellen und Befüllen von &lt;strong&gt;DataObjectList&amp;lt;T&amp;gt;&lt;/strong&gt; zu vereinfachen, stellt TT.DOM die Extension Method &lt;strong&gt;.ToDataObjectList()&lt;/strong&gt; zu Verfügung. Sie kann auf alle Listen vom Typ &lt;strong&gt;IEnumerable&lt;/strong&gt; angewendet werden.&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;List&amp;lt;Person&amp;gt; persons = service.GetPersons();      &lt;br /&gt;var list = persons.ToDataObjectList("Id");       &lt;br /&gt;…&lt;/span&gt;&lt;br /&gt;Als Parameter wird der oder die Eigenschaften angegeben, die ein Objekt eindeutig identifizieren. Dies ist für eine spätere Synchronisation mit einem Middle Tier-Service notwendig, doch dazu&amp;nbsp; mehr in einem separaten Post ;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-7248184721556739681?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/7248184721556739681/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=7248184721556739681' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/7248184721556739681'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/7248184721556739681'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2010/03/ttdom-datenbindung.html' title='TT.DOM: Datenbindung'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_11VTbOPwP_U/S5Xr-PgSKgI/AAAAAAAAANg/miuBbRT0NtM/s72-c/Neumann_Datenklassen2_thumb%5B5%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-9182428242397442463</id><published>2010-03-07T11:06:00.002+01:00</published><updated>2011-08-22T09:00:39.893+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TT.DOM'/><title type='text'>Just Released: Thinktecture.DataObjectModel</title><content type='html'>Bei der Entwicklung verteilter Anwendungen steht man als Entwickler häufig zwischen den Stühlen. Denn je nach Schicht ist man mit teilweise gegenläufige Anforderungen konfrontiert. Dies betrifft vor allem das Domänenmodell:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Aus Sicht der Middle Tier sollten Datenklassen dem POCO- bzw. DTO-Ansatz folgen, um eine möglichst hohe Interoperabilität zu gewährleisten. &lt;/li&gt;&lt;li&gt;Die Datenbankseite interessiert sich hingegen in erster Linie für die Originalwerte der geänderten Objekte, um die Datenkonsistenz bei parallelen Zugriffen gewährleisten zu können. Zudem ist auch Transaktionsunterstützung von Vorteil. &lt;/li&gt;&lt;li&gt;Auf Clientseite sollen die Objekte möglichst einfach gebunden werden können. Darüber hinaus müssen Änderungen verfolgt werden können, um eine spätere Aktualisierung zu gewährleisten. Der Anwender freut sich hingegen über Inline-Validierung und Undo/Redo-Support. Auch das dynamische Erstellten von Sortier- und Filterregeln zur Laufzeit ist sehr beliebt. &lt;/li&gt;&lt;/ul&gt;Das Problem ist nur, dass die vorhandenen Frameworks (WCF/WPF/EF) keine durchgängige Story für Datenklassen bieten, die allen Seiten gerecht wird. &lt;br /&gt;Daher habe ich in den letzten Monaten an einem Framework gearbeitet, das diesen Missstand beheben soll: Das &lt;a href="http://dataobjectmodel.codeplex.com/"&gt;Thinktecture.DataObjectModel&lt;/a&gt; steht nun in einer ersten Betaversion auf &lt;a href="http://www.codeplex.com/"&gt;CodePlex&lt;/a&gt; zu Verfügung.&lt;br /&gt;Die wichtigsten Features:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Support für Data Binding      &lt;br /&gt;(inkl. Validierung, Change Tracking und Undo/Redo-Support) &lt;/li&gt;&lt;li&gt;Dynamische Attributierung von Properties      &lt;br /&gt;(DisplayName, ReadOnly, Browsable, Ordinal, …) &lt;/li&gt;&lt;li&gt;Implementierung von Views      &lt;br /&gt;(inkl. Sortieren, Filtern, Computed Columns, etc.) &lt;/li&gt;&lt;li&gt;Automatische Speicherung von Originalwerten für die Behandlung von Konkurrenzsituationen auf Datenbankseite. &lt;/li&gt;&lt;li&gt;Übertragen von Objekten, inkl. Änderungen an WCF-Services &lt;/li&gt;&lt;li&gt;Unterstützung von System.Transactions. So können alle Objekte automatisch an lokalen oder verteilten Transaktionen teilnehmen. &lt;/li&gt;&lt;li&gt;… &lt;/li&gt;&lt;/ul&gt;Für die Verwendung kann die entsprechende Datenklasse entweder von einer Basisklasse ableiten, oder sie wird zur Laufzeit über einen Runtime Proxy mit der beschriebenen Funktionalität ausgestattet. Auf diese Weise können zum Beispiel auch Modelle vom Entity Framework oder anderen O/R-Mappern flexibel erweitert werden.&lt;br /&gt;Weitere Informationen finden Sie auf &lt;a href="http://dataobjectmodel.codeplex.com/"&gt;http://dataobjectmodel.codeplex.com&lt;/a&gt;. Hier gibt’s nicht nur die Sourcen, sondern auch einige Beispiele für Windows Forms und WPF.&lt;br /&gt;Darüber hinaus erscheint in den nächsten Monaten eine vierteilige Artikelserie in der &lt;a href="http://dotnetpro.de/"&gt;dotnetpro&lt;/a&gt;, in der ich das Framework detailliert beschreiben werde.&lt;br /&gt;Falls Sie Fragen oder Anregungen haben, geben Sie Feedback über das Forum der Codeplex-Seite oder per Mail (joerg neumann &lt;em&gt;at&lt;/em&gt; thinktecture de)!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-9182428242397442463?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/9182428242397442463/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=9182428242397442463' title='4 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/9182428242397442463'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/9182428242397442463'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2010/03/just-released-thinktecturedataobjectmod.html' title='Just Released: Thinktecture.DataObjectModel'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-3844343626763331546</id><published>2010-03-05T13:20:00.001+01:00</published><updated>2010-03-05T13:20:30.479+01:00</updated><title type='text'>WPF: ICO vs. PNG</title><content type='html'>&lt;p&gt;Viele Entwickler verwenden in ihren WPF-Anwendungen noch immer die guten, alten Windows Icons. Diese werden von WPF jedoch nicht optimal gerendert, wie das folgende Beispiel zeigt:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_11VTbOPwP_U/S5D3BzQ_T3I/AAAAAAAAAMo/7zieKl7wOeE/s1600-h/IcoVsPng5.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="IcoVsPng" border="0" alt="IcoVsPng" src="http://lh6.ggpht.com/_11VTbOPwP_U/S5D3CDj9R-I/AAAAAAAAAMs/kTu1dE174p4/IcoVsPng_thumb1.png?imgmax=800" width="244" height="216" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Neben der allgemeinen Unschärfe beim Rendern von Icons, sorgt ein weiterer Umstand für unschöne Ergebnisse: Wenn die Icon-Datei mehrere Icons unterschiedlicher Größe enthält, wählt WPF standardmäßig das Erste aus (meist 16x16 Pixel) und vergrößert es entsprechend. &lt;/p&gt;  &lt;p&gt;Stattdessen sollten Sie besser PNG-Bitmaps verwenden. Diese werden nicht nur “sauberer” dargestellt, sondern bieten auch die von Icons bekannte Transparenz.&lt;/p&gt;  &lt;p&gt;Für die Konvertierung von ICO nach PNG benötigen Sie jedoch einen leistungsfähigen (und daher meist kostenpflichtigen) Icon-Editor. Haben Sie den nicht, können Sie alternativ auch Power Point verwenden. Und das geht wie folgt:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Konvertieren Sie zunächst die ICO-Datei mit Paint nach PNG. &lt;/li&gt;    &lt;li&gt;Dann öffnen Sie diese in Power Point &lt;/li&gt;    &lt;li&gt;Klicken Sie im Ribbon “Format” den Punkt “Neu einfärben” und dann “Transparente Farbe bestimmen” an. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_11VTbOPwP_U/S5D3CqEGhLI/AAAAAAAAAMw/bd3OKptz1Gs/s1600-h/PPTTransparent3.png"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="PPTTransparent" border="0" alt="PPTTransparent" src="http://lh5.ggpht.com/_11VTbOPwP_U/S5D3Da-bNsI/AAAAAAAAAM0/sO_Zh1q0BwE/PPTTransparent_thumb1.png?imgmax=800" width="234" height="244" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Daraufhin selektieren Sie den Hintergrund des Icons und speichern das ganze wieder als PNG-Datei ab.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Problematisch kann es jedoch werden, wenn die Hintergrundfarbe ebenfalls im Symbol selbst verwendet wird, da die entsprechenden Bereich dann ebenfalls transparent dargestellt werden. Daher sollten Sie den Hintergrund ggf. vorher mit einer anderen Farbe füllen.&lt;/p&gt;  &lt;p&gt;So richtig schön ist das ganze Verfahren zwar nicht, dafür aber kostenlos ;)&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-3844343626763331546?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/3844343626763331546/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=3844343626763331546' title='1 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/3844343626763331546'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/3844343626763331546'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2010/03/wpf-ico-vs-png.html' title='WPF: ICO vs. PNG'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_11VTbOPwP_U/S5D3CDj9R-I/AAAAAAAAAMs/kTu1dE174p4/s72-c/IcoVsPng_thumb1.png?imgmax=800' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-5808405112244097329</id><published>2010-03-02T12:05:00.001+01:00</published><updated>2010-03-02T12:05:08.399+01:00</updated><title type='text'>WPF Threading ohne Intellisense</title><content type='html'>&lt;p&gt;In meinen WPF-Schulungen kommt es immer wieder zu Verwirrungen bzgl. einiger Methoden, die im Zusammenhang mit Threading zum Einsatz kommen. Daher habe die Problematik hier noch einmal zusammengefasst.&lt;/p&gt;  &lt;p&gt;Die Klasse &lt;em&gt;DispatcherObject&lt;/em&gt; bietet mit &lt;em&gt;CheckAccess()&lt;/em&gt; und &lt;em&gt;VerifyAccess()&lt;/em&gt; zwei Methoden, mit denen abgefragt werden kann, ob der Zugriff auf ein Objekt aus dem aktuellen Thread aus möglich ist.&lt;/p&gt;  &lt;p&gt;Das Problem ist nur, dass beide Methoden nicht über Intellisense zugreifbar sind! Dies führt dazu, dass viele Entwickler sie nicht kennen. Warum die Methoden nicht angezeigt werden, offenbart ein Blick in den Source Code:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font face="Courier New"&gt;[EditorBrowsable(EditorBrowsableState.Never)]&lt;/font&gt;       &lt;br /&gt;&lt;/strong&gt;&lt;font face="Courier New"&gt;public bool CheckAccess()      &lt;br /&gt;{       &lt;br /&gt;&amp;#160; …       &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Hier sorgt das &lt;em&gt;EditorBrowsable&lt;/em&gt;-Attribut dafür, dass die entsprechende Methode weder in Intellisense, noch im Object Browser angezeigt werden.&lt;/p&gt;  &lt;p&gt;Das gleiche gilt übrigens auch für die gleichnamigen Methoden der &lt;em&gt;Dispatcher&lt;/em&gt;-Klasse. Darüber hinaus werden alle Überladungen der Methoden &lt;em&gt;Dispatcher.Invoke()&lt;/em&gt; und &lt;em&gt;Dispatcher.BeginInvoke()&lt;/em&gt; nicht angezeigt, die einen Parameter vom Typ &lt;em&gt;DispatcherPriority&lt;/em&gt; definieren.&lt;/p&gt;  &lt;p&gt;Interessant ist an dieser Stelle, das die genannten Methoden den Anschein erwecken, als wären sie nicht vorhanden, jedoch ausführlich (inkl. Beispielen) in der MSDN beschrieben werden.&lt;/p&gt;  &lt;p&gt;Verstehen muss man das nicht, oder?&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-5808405112244097329?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/5808405112244097329/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=5808405112244097329' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/5808405112244097329'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/5808405112244097329'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2010/03/wpf-threading-ohne-intellisense.html' title='WPF Threading ohne Intellisense'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-6609637214275592277</id><published>2010-02-27T14:23:00.001+01:00</published><updated>2010-03-05T13:21:20.848+01:00</updated><title type='text'>API-Design vom Feinsten</title><content type='html'>&lt;p&gt;Neulich bin ich in MEF auf eine echte API-Design-Perle gestoßen.    &lt;br /&gt;Der folgende Code führt eine Composition der Parts durch: &lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;public partial class MainWindow : Window      &lt;br /&gt;{       &lt;br /&gt;&amp;#160; ...       &lt;br /&gt;&amp;#160; private void Compose()       &lt;br /&gt;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; string path = Path.GetDirectoryName(       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Assembly.GetExecutingAssembly().Location);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; DirectoryCatalog catalog =       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; new DirectoryCatalog(path);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; CompositionContainer container =       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; new CompositionContainer(catalog);       &lt;br /&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160; container.SatisfyImportsOnce(this);        &lt;br /&gt;&lt;/strong&gt;&amp;#160; }       &lt;br /&gt;&amp;#160; ...       &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Das Problem hierbei ist, dass der oben stehende Code nicht in jedem Fall kompiliert werden kann. Schauen wir uns die entscheidende Stelle mal genauer an: &lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;container.SatisfyImportsOnce(this);&lt;/font&gt; &lt;/p&gt;  &lt;p&gt;Die Methode &lt;strong&gt;SatisfyImportsOnce()&lt;/strong&gt; erwartet einen Parameter vom Typ &lt;em&gt;ComposablePart&lt;/em&gt;. Nun leitet die oben deklarierte Klasse &lt;em&gt;MainWindow&lt;/em&gt; jedoch nicht von &lt;em&gt;ComposablePart&lt;/em&gt; ab. Somit ist schnell klar, warum der Code sich nicht kompilieren lässt – möchte man denken.     &lt;br /&gt;Er lässt sich jedoch fehlerfrei kompilieren, wenn man den Namespace &lt;em&gt;System.ComponentModel.Composition&lt;/em&gt; eingebunden hat!     &lt;br /&gt;Dieser enthält nämlich eine Extension Method, die ebenfalls &lt;em&gt;SatisfyImportsOnce()&lt;/em&gt; heißt, jedoch einen Parameter vom Typ &lt;em&gt;object&lt;/em&gt; erwartet! &lt;em&gt;CompositionContainer&lt;/em&gt; ist jedoch im Namespace &lt;em&gt;System.ComponentModel.Composition.Hosting&lt;/em&gt; beheimatet, sodass die Verbindung zur Extension Method nicht unbedingt klar ist.&lt;/p&gt;  &lt;p&gt;Ein schönes Beispiel dafür, wie man Sprach-Features dafür nutzen kann, den Entwickler maximal zu verwirren ;)&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-6609637214275592277?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/6609637214275592277/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=6609637214275592277' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/6609637214275592277'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/6609637214275592277'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2010/02/api-design-vom-feinsten.html' title='API-Design vom Feinsten'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-1513164870822235359</id><published>2010-02-27T12:33:00.001+01:00</published><updated>2010-02-27T13:26:18.294+01:00</updated><title type='text'>Slides &amp; Samples von der BASTA! Spring</title><content type='html'>&lt;p&gt;Die &lt;a href="http://basta.net/"&gt;BASTA! Spring&lt;/a&gt; war mal wieder ein echtes Highlight im Konferenzkalender. Vielen Dank an die Teilnehmer meiner Sessions für das positive Feedback!     &lt;br /&gt;Die Slides &amp;amp; Samples meiner Sessions findet Ihr hier:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://cid-4029b6652bf3f13f.skydrive.live.com/self.aspx/%c3%96ffentlich/Neumann%5E_Baier%5E_WCF.pdf"&gt;WCF vs. Client&lt;/a&gt; (zusammen mit &lt;a href="http://www.leastprivilege.com/"&gt;Dominick Baier&lt;/a&gt;) &lt;/li&gt;    &lt;li&gt;&lt;a href="http://cid-4029b6652bf3f13f.skydrive.live.com/self.aspx/%c3%96ffentlich/MEF.zip"&gt;Entwicklung modularer Anwendungen mit MEF&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://cid-4029b6652bf3f13f.skydrive.live.com/self.aspx/%c3%96ffentlich/Neumann%5E_SL%5E_WPF%5E_Grundlagen.pdf"&gt;WPF/Silverlight Grundlagen&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://cid-4029b6652bf3f13f.skydrive.live.com/self.aspx/%c3%96ffentlich/Neumann%5E_DB%5E_Silverlight.pdf"&gt;Moderne Datenbankschnittstellen für Silverlight-Anwendungen&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://cid-4029b6652bf3f13f.skydrive.live.com/self.aspx/%c3%96ffentlich/WPFTippsTricks.zip"&gt;WPF Tipps &amp;amp; Tricks&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;PS: Die BASTA! geht auf Tour. Vom 18. bis 19. Mai findet in München die erste &lt;strong&gt;BASTA! on Tour&lt;/strong&gt; statt. Mehr Infos gibt's &lt;a href="http://it-republik.de/konferenzen/basta_ontour2010/"&gt;hier&lt;/a&gt;. Ich werde dort zwei Sessions zum Thema Client Development, sowie einen ganztägigen WPF-Workshop durchführen.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-1513164870822235359?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/1513164870822235359/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=1513164870822235359' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/1513164870822235359'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/1513164870822235359'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2010/02/slides-samples-von-der-basta-spring.html' title='Slides &amp;amp; Samples von der BASTA! Spring'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-2897688462977425322</id><published>2009-11-05T10:24:00.001+01:00</published><updated>2009-11-05T10:24:29.180+01:00</updated><title type='text'>Slides vom .NET Information Day</title><content type='html'>&lt;p&gt;Die Slides meiner Session “&lt;b&gt;UI*3: WinForms, WPF und Silverlight im Vergleich&lt;/b&gt;” vom &lt;a href="http://dotnet-informationday.de/"&gt;.NET Information Day&lt;/a&gt; gibt’s &lt;a href="http://www.esnips.com/doc/e3f40b99-6f74-4fac-b9e4-5c00df4ca270/Neumann_UI"&gt;hier&lt;/a&gt;.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-2897688462977425322?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/2897688462977425322/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=2897688462977425322' title='2 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/2897688462977425322'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/2897688462977425322'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2009/11/slides-vom-net-information-day.html' title='Slides vom .NET Information Day'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-5308401084497744907</id><published>2009-11-05T10:21:00.001+01:00</published><updated>2009-11-05T10:21:59.121+01:00</updated><title type='text'>Slides von der Prio</title><content type='html'>&lt;p&gt;Wie versprochen, &lt;a href="http://www.esnips.com/doc/4128aab7-4ad8-4090-9d25-9029a6a0811b/Technology-Shoot-Out"&gt;hier&lt;/a&gt; die Slides einer Session “&lt;b&gt;Technology Shoot-Out: WinForms vs. WPF vs. Silverlight&lt;/b&gt;” von der diesjährigen &lt;a href="http://www.prioconference.de"&gt;Prio Conference&lt;/a&gt;.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-5308401084497744907?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/5308401084497744907/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=5308401084497744907' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/5308401084497744907'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/5308401084497744907'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2009/11/slides-von-der-prio.html' title='Slides von der Prio'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-9111104687422336521</id><published>2009-10-19T09:04:00.001+02:00</published><updated>2009-10-19T09:04:26.021+02:00</updated><title type='text'>Slides von der Advanced Developer Conference</title><content type='html'>&lt;p&gt;Die Slides meiner Sessions von der &lt;a href="http://adc09.de"&gt;Advanced Developer Conference&lt;/a&gt; finden Sie hier:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://www.esnips.com/doc/5ea4f1ca-9705-4151-8a8e-997148bef633/Neumann_TechnologyShootOut"&gt;Jeder gegen jeden: UI-Frameworks im Vergleich&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.esnips.com/doc/7d723100-d898-4ec7-bd84-8eb66c89193d/Neumann_MEF_MAF"&gt;Flexibel erweiterbare Anwendungen mit MEF &amp;amp; MAF&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-9111104687422336521?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/9111104687422336521/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=9111104687422336521' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/9111104687422336521'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/9111104687422336521'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2009/10/slides-von-der-advanced-developer.html' title='Slides von der Advanced Developer Conference'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-4503748495101309142</id><published>2009-10-01T12:02:00.001+02:00</published><updated>2009-11-02T09:38:01.776+01:00</updated><title type='text'>Slides von der BASTA!</title><content type='html'>&lt;p&gt;Wie angekündigt, hier die Slides meiner Sessions von der &lt;a href="www.basta.net"&gt;BASTA!&lt;/a&gt;:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;b&gt;&lt;a href="http://www.esnips.com/doc/de5af648-d145-4c59-8ecd-81699e4d32bf/Neumann_DataAccessPatterns"&gt;Advanced Data Access Patterns&lt;/a&gt;&lt;/b&gt; &lt;/li&gt;    &lt;li&gt;&lt;b&gt;&lt;a href="http://www.esnips.com/doc/a123482b-a460-4785-95a2-527ef94f8638/Neumann_AddIn"&gt;Design und Realisierung von sicheren Add-in-Modellen&lt;/a&gt;&lt;/b&gt; &lt;/li&gt;    &lt;li&gt;&lt;b&gt;&lt;a href="http://www.esnips.com/doc/51c6cde3-998d-4955-ad21-d1e923dba452/Neumann_Transaktionen"&gt;Transactions 2.0&lt;/a&gt; &lt;/b&gt;&lt;/li&gt;    &lt;li&gt;&lt;b&gt;&lt;a href="http://www.esnips.com/doc/7126bc87-1cea-469f-85f4-91538ca54c52/Neumann_WpfDataBinding"&gt;Dynamische Verbindungen mit WPF Data Binding&lt;/a&gt;         &lt;br /&gt;&lt;/b&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Danke an alle Teilnehmer für das positive Feedback!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-4503748495101309142?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/4503748495101309142/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=4503748495101309142' title='2 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/4503748495101309142'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/4503748495101309142'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2009/10/slides-von-der-basta.html' title='Slides von der BASTA!'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-6114304793738082397</id><published>2009-08-18T08:40:00.001+02:00</published><updated>2009-08-18T08:40:48.505+02:00</updated><title type='text'>dot.NET Code Camp in Bad Ems</title><content type='html'>&lt;p&gt;Im Oktober gibt es beim &lt;a href="http://entwickler-akademie.de/ak/show.php3?id=44&amp;amp;ccid=3"&gt;dot.NET Code Camp&lt;/a&gt; wieder geballtes Wissen in kompakter Form. &lt;a href="http://www.cubido.de/Blog/tabid/176/BlogID/8/Default.aspx"&gt;Rainer Stropek&lt;/a&gt;, &lt;a href="http://www.heise.de/developer/blog/dotnet-doktor/"&gt;Holger Schwichtenberg&lt;/a&gt; und ich vermitteln 5 Tage lang die wichtigsten Grundlagen zu C# 3.0, WPF, Silverlight und WCF. Mehr Infos gibt's &lt;a href="http://entwickler-akademie.de/ak/show.php3?id=44&amp;amp;ccid=3"&gt;hier&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;&lt;img src="http://entwickler.com/ak/codecamps/graf/dotnet-net35-csharp.jpg" /&gt; &lt;/p&gt;  &lt;p&gt;Dot.NET Code Camp - .NET 3.5 &amp;amp; C#    &lt;br /&gt;26.10.-30.10 in Bad Ems &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-6114304793738082397?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/6114304793738082397/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=6114304793738082397' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/6114304793738082397'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/6114304793738082397'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2009/08/dotnet-code-camp-in-bad-ems.html' title='dot.NET Code Camp in Bad Ems'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-8678234900559797387</id><published>2009-08-14T10:18:00.001+02:00</published><updated>2009-08-14T10:18:33.278+02:00</updated><title type='text'>SQL Server 2008-Buch</title><content type='html'>&lt;p&gt;Seit vorletzter Woche ist die neue Auflage meines &lt;a href="http://www.amazon.de/gp/reader/3836213958/ref=sib_dp_pt#reader-link"&gt;SQL Server-Buches&lt;/a&gt; bei &lt;a href="http://www.galileo-press.de/"&gt;Galileo Press&lt;/a&gt; erschienen, das ich zusammen mit Dirk Mertins und Andreas Kühnel geschrieben habe.&lt;/p&gt;  &lt;p&gt;Auszug aus dem Klappentext:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;i&gt;Dieses Buch wendet sich an alle Entwickler, die die neue Version der Microsoft-Datenbank nutzen wollen. Im Vordergrund steht die Integration des .NET-Frameworks, das die Programmierung mit den .NET-Sprachen ermöglicht. Vom ersten Datenbankentwurf und den SQL-Grundlagen, der Migration von SQL Server 2000 bis hin zu den neuen Features und konkreten Programmierbeispielen beschreiben die Autoren alles Notwendige, um den SQL Server 2008 als Programmierplattform und Datenmanagement-Server zu nutzen. In der neuen Auflage wurde das Buch aktualisiert und um viele Themen wie Indizierte Sichten, Partionierung von Tabellen, Event Notification unter ADO.NET etc erweitert. &lt;/i&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.amazon.de/gp/reader/3836213958/ref=sib_dp_pt#reader-link"&gt;&lt;img title="Cover" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="244" alt="Cover" src="http://lh4.ggpht.com/_11VTbOPwP_U/SoUd2CYaVMI/AAAAAAAAALw/ZnSqavbdRoA/Cover%5B5%5D.png?imgmax=800" width="166" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-8678234900559797387?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/8678234900559797387/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=8678234900559797387' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/8678234900559797387'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/8678234900559797387'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2009/08/sql-server-2008-buch.html' title='SQL Server 2008-Buch'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_11VTbOPwP_U/SoUd2CYaVMI/AAAAAAAAALw/ZnSqavbdRoA/s72-c/Cover%5B5%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-3246837255636873086</id><published>2009-07-02T09:26:00.001+02:00</published><updated>2009-07-02T09:26:17.287+02:00</updated><title type='text'>Re-MVPed</title><content type='html'>&lt;p&gt;My MVP award for the &amp;quot;Client App Dev&amp;quot; category has been renewed for another year. Thanks!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-3246837255636873086?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/3246837255636873086/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=3246837255636873086' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/3246837255636873086'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/3246837255636873086'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2009/07/re-mvped.html' title='Re-MVPed'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-6612300607674910387</id><published>2009-03-02T09:19:00.001+01:00</published><updated>2009-03-02T09:19:54.811+01:00</updated><title type='text'>Slides &amp; Samples von der BASTA Spring</title><content type='html'>&lt;p&gt;Die Slides &amp;amp; Samples meiner Sessions von der &lt;a href="http://it-republik.de/dotnet/basta/"&gt;BASTA! Spring&lt;/a&gt; finden Sie hier:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://www.esnips.com/doc/9f32a745-b67b-4b23-9381-5a1f1de397f7/Custom-Controls-mit-WPF-und-Silverlight"&gt;Custom Controls mit WPF und Silverlight&lt;/a&gt;&amp;#160;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.esnips.com/doc/59d7ae2a-30ab-49d3-a27c-d811dd9eb389/Transaktionen-mit-Visual-Basic"&gt;Transaktionen mit Visual Basic&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;An dieser Stelle nochmal einen Dank an Tobias Richling, der mir bei meiner Custom Controls Session zur Seite stand, da meine Stimme erk&amp;#228;ltungsbedingt auszufallen drohte.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-6612300607674910387?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/6612300607674910387/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=6612300607674910387' title='2 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/6612300607674910387'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/6612300607674910387'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2009/03/slides-samples-von-der-basta-spring.html' title='Slides &amp;amp; Samples von der BASTA Spring'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-8710177570565963368</id><published>2009-02-14T17:37:00.001+01:00</published><updated>2009-02-14T17:37:46.896+01:00</updated><title type='text'>CSharpCodeProvider and referenced .net 3.5 assemblies</title><content type='html'>&lt;p class="MsoNormal" style="margin: 7.5pt 0cm"&gt;&lt;span lang="EN-US" style="font-family: " mso-fareast-language:="mso-fareast-language:" mso-ansi-language:="mso-ansi-language:" 10.0pt;="10.0pt;" mso-bidi-font-size:="mso-bidi-font-size:" ms?,?sans-serif?;="ms?,?sans-serif?;" trebuchet="trebuchet" de?="DE?" en-us;="EN-US;"&gt;Yesterday I've been working a little with CodeDom and the &lt;b&gt;CSharpCodeProvider&lt;/b&gt; to invoke dynamically created code. Because I'm working with some WCF types in the dynamic code, I've added a reference to &lt;b&gt;System.ServiceModel&lt;/b&gt; and some other assemblies.&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin: 7.5pt 0cm"&gt;...    &lt;br /&gt;&lt;span lang="EN-US" style="color: #2b91af; font-family: consolas; mso-bidi-font-size: 10.0pt; mso-ansi-language: en-us; mso-fareast-language: de"&gt;&lt;font face="Courier New"&gt;CodeDomProvider&lt;/font&gt;&lt;/span&gt;&lt;font face="Courier New"&gt;&lt;span lang="EN-US" style="font-family: consolas; mso-bidi-font-size: 10.0pt; mso-ansi-language: en-us; mso-fareast-language: de"&gt; codeProvider =       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;CSharpCodeProvider&lt;/span&gt;(providerOptions);         &lt;br /&gt;&lt;/span&gt;&lt;span lang="EN-US" style="color: #2b91af; font-family: consolas; mso-bidi-font-size: 10.0pt; mso-ansi-language: en-us; mso-fareast-language: de"&gt;CompilerParameters&lt;/span&gt;&lt;/font&gt;&lt;span lang="EN-US" style="font-family: consolas; mso-bidi-font-size: 10.0pt; mso-ansi-language: en-us; mso-fareast-language: de"&gt;&lt;font face="Courier New"&gt; compilerParams =       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;CompilerParameters&lt;/span&gt;();         &lt;br /&gt;&lt;/font&gt;&lt;/span&gt;&lt;span lang="EN-US" style="font-family: consolas; mso-bidi-font-size: 10.0pt; mso-ansi-language: en-us; mso-fareast-language: de"&gt;&lt;font face="Courier New"&gt;compilerParams.GenerateInMemory = &lt;span style="color: blue"&gt;true&lt;/span&gt;;         &lt;br /&gt;&lt;/font&gt;&lt;/span&gt;&lt;font face="Courier New"&gt;&lt;span lang="EN-US" style="font-family: consolas; mso-bidi-font-size: 10.0pt; mso-ansi-language: en-us; mso-fareast-language: de"&gt;compilerParams.ReferencedAssemblies.Add(       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #a31515"&gt;&amp;quot;System.ServiceModel.dll&amp;quot;&lt;/span&gt;);        &lt;br /&gt;... &lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin: 7.5pt 0cm"&gt;&lt;font face="Courier New"&gt;&lt;span lang="EN-US" style="color: #2b91af; font-family: consolas; mso-bidi-font-size: 10.0pt; mso-ansi-language: en-us; mso-fareast-language: de"&gt;CompilerResults&lt;/span&gt;&lt;span lang="EN-US" style="font-family: consolas; mso-bidi-font-size: 10.0pt; mso-ansi-language: en-us; mso-fareast-language: de"&gt; results = codeProvider.CompileAssemblyFromDom(       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; compilerParams, codeUnit);&lt;/span&gt;&lt;span lang="EN-US" style="mso-bidi-font-size: 10.0pt; mso-ansi-language: en-us"&gt; &lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US" style="mso-bidi-font-size: 10.0pt; mso-ansi-language: en-us; mso-fareast-language: de; mso-bidi-font-family: tahoma"&gt;At runtime, the following exception was returned via the &lt;b style="mso-bidi-font-weight: normal"&gt;CompilerResults.Error&lt;/b&gt; collection: &lt;/span&gt;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US" style="mso-bidi-font-size: 10.0pt; mso-ansi-language: en-us; mso-fareast-language: de; mso-bidi-font-family: tahoma"&gt;&lt;/span&gt;&lt;span lang="EN-US" style="mso-bidi-font-size: 10.0pt; mso-ansi-language: en-us; mso-fareast-language: de; mso-bidi-font-family: tahoma"&gt;Metadata file 'System.ServiceModel.dll' could not be found.&lt;/span&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US" style="mso-bidi-font-size: 10.0pt; mso-ansi-language: en-us; mso-fareast-language: de; mso-bidi-font-family: tahoma"&gt;I've been wondering, because all other assembly references works fine and the code executed as expected when I don't use WCF types in the dynamic code. &lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US" style="mso-bidi-font-size: 10.0pt; mso-ansi-language: en-us; mso-fareast-language: de; mso-bidi-font-family: tahoma"&gt;The answer lies in the &lt;b&gt;CSharpCodeProvider&lt;/b&gt; class. By default it uses the .net 2.0 compiler and don't knows about the Reference Assemblies folder (&lt;i style="mso-bidi-font-style: normal"&gt;c:\Program Files\Reference Assemblies\Microsoft\Framework\...&lt;/i&gt;) where the additional .net 3.0 and .net 3.5 assemblies can be found.       &lt;br /&gt;To force &lt;b style="mso-bidi-font-weight: normal"&gt;CSharpCodeProvider&lt;/b&gt; to use the .net 3.5 compiler, a special provider option must be set:       &lt;br style="mso-special-character: line-break" /&gt;      &lt;br style="mso-special-character: line-break" /&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align: none"&gt;&lt;span lang="EN-US" style="color: #2b91af; font-family: consolas; mso-bidi-font-size: 10.0pt; mso-ansi-language: en-us; mso-fareast-language: de"&gt;&lt;font face="Courier New"&gt;Dictionary&lt;/font&gt;&lt;/span&gt;&lt;span lang="EN-US" style="font-family: consolas; mso-bidi-font-size: 10.0pt; mso-ansi-language: en-us; mso-fareast-language: de"&gt;&lt;font face="Courier New"&gt;&amp;lt;&lt;span style="color: blue"&gt;string&lt;/span&gt;, &lt;span style="color: blue"&gt;string&lt;/span&gt;&amp;gt; providerOptions =        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Dictionary&lt;/span&gt;&amp;lt;&lt;span style="color: blue"&gt;string&lt;/span&gt;, &lt;span style="color: blue"&gt;string&lt;/span&gt;&amp;gt;();         &lt;br /&gt;&lt;/font&gt;&lt;/span&gt;&lt;font face="Courier New"&gt;&lt;span lang="EN-US" style="font-family: consolas; mso-bidi-font-size: 10.0pt; mso-ansi-language: en-us; mso-fareast-language: de"&gt;providerOptions.Add(&lt;span style="color: #a31515"&gt;&amp;quot;&lt;strong&gt;CompilerVersion&lt;/strong&gt;&amp;quot;&lt;/span&gt;, &lt;span style="color: #a31515"&gt;&amp;quot;&lt;strong&gt;v3.5&lt;/strong&gt;&amp;quot;&lt;/span&gt;);         &lt;br /&gt;&lt;/span&gt;&lt;span lang="EN-US" style="color: #2b91af; font-family: consolas; mso-bidi-font-size: 10.0pt; mso-ansi-language: en-us; mso-fareast-language: de"&gt;CSharpCodeProvider&lt;/span&gt;&lt;span lang="EN-US" style="font-family: consolas; mso-bidi-font-size: 10.0pt; mso-ansi-language: en-us; mso-fareast-language: de"&gt; provider =        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;CSharpCodeProvider&lt;/span&gt;(providerOptions);&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align: none"&gt;&lt;span lang="EN-US" style="font-family: consolas; mso-bidi-font-size: 10.0pt; mso-ansi-language: en-us; mso-fareast-language: de"&gt;&lt;font face="Courier New"&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-8710177570565963368?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/8710177570565963368/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=8710177570565963368' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/8710177570565963368'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/8710177570565963368'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2009/02/csharpcodeprovider-and-referenced-net.html' title='CSharpCodeProvider and referenced .net 3.5 assemblies'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-4691146935073354839</id><published>2008-11-17T09:10:00.001+01:00</published><updated>2008-11-17T09:10:57.330+01:00</updated><title type='text'>Artikel in der aktuellen dotnetpro</title><content type='html'>&lt;p&gt;In der aktuellen Ausgabe der &lt;a href="http://www.dotnetpro.de/"&gt;dotnetpro&lt;/a&gt; (12/2008) ist der dritte Teil meiner dreiteiligen Serie &amp;#252;ber das Managed Add-In Framework (MAF) erschienen. Aus dem Abstrakt: &lt;/p&gt;  &lt;p&gt;&lt;b&gt;Fertig zum Einsatz: Ein Command-Modell f&amp;#252;r das Managed Add-in Framework&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;Im zweiten Teil der Serie ging es bereits um die Integration von Windows-Forms-basierten Add-ins. In diesem Teil werden nun Dialoge zur Verwaltung und Aktivierung von Add-ins vorgestellt. Au&amp;#223;erdem wird ein Command-Modell entwickelt, welches den Add-ins eine leichte Integration in die Men&amp;#252;- und Toolbars der Anwendung erm&amp;#246;glicht.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_11VTbOPwP_U/SSEnD8CKPHI/AAAAAAAAALY/wy6AQRisRDw/dnp_122008%5B3%5D.jpg"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="194" alt="dnp_122008" src="http://lh4.ggpht.com/_11VTbOPwP_U/SSEnEJ3K68I/AAAAAAAAALc/95leqw951Nw/dnp_122008_thumb%5B1%5D.jpg" width="141" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-4691146935073354839?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/4691146935073354839/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=4691146935073354839' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/4691146935073354839'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/4691146935073354839'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2008/11/artikel-in-der-aktuellen-dotnetpro.html' title='Artikel in der aktuellen dotnetpro'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_11VTbOPwP_U/SSEnEJ3K68I/AAAAAAAAALc/95leqw951Nw/s72-c/dnp_122008_thumb%5B1%5D.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-3606049390907016351</id><published>2008-11-12T09:02:00.001+01:00</published><updated>2008-11-12T09:02:29.831+01:00</updated><title type='text'>Slides &amp; Samples von der Prio</title><content type='html'>&lt;p&gt;Die Slides &amp;amp; Samples meiner Sessions von der &lt;a href="http://prioconference.de"&gt;Prio&lt;/a&gt; finden Sie hier:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://www.esnips.com/doc/f14f9a18-fa7f-4adb-8df8-780d38848480/Neumann_WPF"&gt;WPF for Architects&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.esnips.com/doc/9c371cf4-8333-48c7-a904-997b5b930c75/Prio_Neumann_WCF"&gt;WCF Client Patterns&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.esnips.com/doc/d4e505c4-f5f0-46b4-96d9-a6a7e355dd59/Prio_Neumann_AddIns"&gt;Vom Monolithen zu flexiblen Anwendungen&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.esnips.com/doc/6a6882c6-e7fa-4c20-810a-1d2581308999/Prio_Neumann_Offline"&gt;Smart Clients on the Road&lt;/a&gt;      &lt;br /&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-3606049390907016351?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/3606049390907016351/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=3606049390907016351' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/3606049390907016351'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/3606049390907016351'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2008/11/slides-samples-von-der-prio.html' title='Slides &amp;amp; Samples von der Prio'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-7537763799160892297</id><published>2008-10-15T08:49:00.001+02:00</published><updated>2008-10-15T08:49:33.816+02:00</updated><title type='text'>Artikel in der aktuellen dotnetpro</title><content type='html'>&lt;p&gt;In der aktuellen Ausgabe der &lt;a href="http://www.dotnetpro.de/"&gt;dotnetpro&lt;/a&gt; (11/2008) ist der zweite Teil meiner dreiteiligen Serie &amp;#252;ber das Managed Add-In Framework (MAF) erschienen. Aus dem Abstrakt: &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Windows-Forms-Support f&amp;#252;r das Managed Add-in Framework     &lt;br /&gt;&lt;/strong&gt;Im ersten Teil der Serie wurden die grundlegenden Elemente des Managed Add-in-Frameworks (MAF) erl&amp;#228;utert. Nun geht es um die Entwicklung grafischer Add-ins. dotnetpro r&amp;#252;stet die fehlende Unterst&amp;#252;tzung f&amp;#252;r Windows-Formsbasierte Add-ins nach. Auf diese Weise k&amp;#246;nnen auch Bestandsanwendungen von dem neuen Modell profitieren.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/NeumannJN/SPWSfGLDi3I/AAAAAAAAAIk/mWGfiCOYzuQ/dnp_112008%5B4%5D.jpg"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="163" alt="dnp_112008" src="http://lh3.ggpht.com/NeumannJN/SPWSfaQEy7I/AAAAAAAAAIo/SoLiML15HUA/dnp_112008_thumb%5B2%5D.jpg" width="131" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-7537763799160892297?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/7537763799160892297/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=7537763799160892297' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/7537763799160892297'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/7537763799160892297'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2008/10/artikel-in-der-aktuellen-dotnetpro.html' title='Artikel in der aktuellen dotnetpro'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/NeumannJN/SPWSfaQEy7I/AAAAAAAAAIo/SoLiML15HUA/s72-c/dnp_112008_thumb%5B2%5D.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-1872992750913924844</id><published>2008-10-15T08:39:00.001+02:00</published><updated>2008-10-15T08:39:13.290+02:00</updated><title type='text'>Slides &amp; Samples von der ADC</title><content type='html'>&lt;p&gt;Die Slides &amp;amp; Samples meiner Sessions von der &lt;a href="http://adc08.de/"&gt;Advanced Developer Conference&lt;/a&gt; finden Sie hier:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://www.esnips.com/doc/75150eb1-8139-4e37-8b49-0838221eade6/Neumann_MAF"&gt;Erweiterbare Anwendungen mit dem Managed Add-In Framework&lt;/a&gt;      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.esnips.com/doc/8e718eaf-2c85-441d-8e38-d1b23d0bc999/Neumann_Monitoring"&gt;Am Puls der Anwendung: Instrumentierung und Monitoring&lt;/a&gt;      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.esnips.com/doc/4eb10c2c-3d97-4601-bb7c-f2bac454d628/Neumann_SqlCompactSync"&gt;SQL Server Compact &amp;amp; ADO.NET Synchronization Services&lt;/a&gt;      &lt;br /&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-1872992750913924844?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/1872992750913924844/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=1872992750913924844' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/1872992750913924844'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/1872992750913924844'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2008/10/slides-samples-von-der-adc.html' title='Slides &amp;amp; Samples von der ADC'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-9086629647552215897</id><published>2008-09-27T13:24:00.001+02:00</published><updated>2008-09-27T13:24:51.842+02:00</updated><title type='text'>Slides &amp; Samples von der BASTA</title><content type='html'>&lt;p&gt;Die Slides &amp;amp; Samples meiner &lt;a href="http://it-republik.de/dotnet/basta/"&gt;BASTA&lt;/a&gt;-Sessions finden Sie hier:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://www.esnips.com/doc/4b7454d6-f104-4c67-8d06-425719995208/Neumann_WCF"&gt;WCF Client Patterns&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.esnips.com/doc/96d021a1-b1c1-4246-92bf-e2b4e822d910/Neumann_Offline"&gt;Bin dann mal weg! Entwicklung von Offline-Clients&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.esnips.com/doc/2bd425a7-8fe7-4165-9699-aa45131d7979/Neumann_AddIns"&gt;Anwendungen flexibel erweitern&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.esnips.com/doc/136998df-3998-498a-8e96-806c2490c6ab/Baier_Neumann_Deployment"&gt;Smart Client Deployment&lt;/a&gt;      &lt;br /&gt;zusammen mit &lt;a href="http://it-republik.de/dotnet/basta/"&gt;Dominick Baier&lt;/a&gt;      &lt;br /&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-9086629647552215897?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/9086629647552215897/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=9086629647552215897' title='4 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/9086629647552215897'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/9086629647552215897'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2008/09/slides-samples-von-der-basta.html' title='Slides &amp;amp; Samples von der BASTA'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-4760966104289693969</id><published>2008-09-16T08:57:00.001+02:00</published><updated>2008-09-16T08:57:20.643+02:00</updated><title type='text'>Slides &amp; Samples von der NRW08</title><content type='html'>&lt;p&gt;Die Slides und Samples meiner Session &lt;strong&gt;Occasionally Connected Clients&lt;/strong&gt; finden Sie &lt;a href="http://www.esnips.com/doc/d1478276-c606-4dbf-80ec-c0886afdf972/Occasionally-Connected-Clients"&gt;hier&lt;/a&gt;.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-4760966104289693969?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/4760966104289693969/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=4760966104289693969' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/4760966104289693969'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/4760966104289693969'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2008/09/slides-samples-von-der-nrw08.html' title='Slides &amp;amp; Samples von der NRW08'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-2073952735365289283</id><published>2008-09-11T09:25:00.001+02:00</published><updated>2008-09-11T09:25:21.637+02:00</updated><title type='text'>Artikel in der aktuellen dotnetpro</title><content type='html'>&lt;p&gt;In der aktuellen Ausgabe der &lt;a href="www.dotnetpro.de"&gt;dotnetpro&lt;/a&gt; (&lt;a href="http://www.dotnetpro.de/articles/articlearchive1729.aspx"&gt;10/2008&lt;/a&gt;) ist der erste Teil meiner dreiteiligen Serie &amp;#252;ber das Managed Add-In Framework (MAF) erschienen. Aus dem Abstrakt:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Dynamisch erweitern: Das Managed Add-in Framework in .NET 3.5      &lt;br /&gt;&lt;/strong&gt;Es ist gar nicht so einfach, erweiterbare Anwendungen zu entwickeln. Das Spektrum der Aufgaben reicht vom Auffinden der Add-ins &amp;#252;ber die dynamische Bindung bis hin zu Versionierung und Absicherung. F&amp;#252;r all diese Aufgaben bietet Microsoft das neue Managed Add-in Framework (MAF), das Teil von .NET 3.5 ist. dotnetpro stellt es vor und beleuchtet seine St&amp;#228;rken und Schw&amp;#228;chen.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.dotnetpro.de/articles/articlearchive1729.aspx"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="178" alt="dnp_102008" src="http://lh6.ggpht.com/NeumannJN/SMjH4Ws8IOI/AAAAAAAAAIg/QkYMS9j0ZNQ/dnp_102008%5B5%5D.jpg" width="142" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-2073952735365289283?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/2073952735365289283/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=2073952735365289283' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/2073952735365289283'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/2073952735365289283'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2008/09/artikel-in-der-aktuellen-dotnetpro.html' title='Artikel in der aktuellen dotnetpro'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/NeumannJN/SMjH4Ws8IOI/AAAAAAAAAIg/QkYMS9j0ZNQ/s72-c/dnp_102008%5B5%5D.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-5296320605831863926</id><published>2008-08-21T11:26:00.001+02:00</published><updated>2008-08-21T11:26:24.404+02:00</updated><title type='text'>.NET 3.5-Buch bei Hanser erschienen</title><content type='html'>&lt;p&gt;Im August ist beim Hanser Verlag das Buch &amp;#8222;&lt;strong&gt;.NET 3.5: WPF, WCF, LINQ, C# 2008, VB 2008 und ASP.NET AJAX&lt;/strong&gt;&amp;#8220; erschienen, das ich zusammen mit Holger Schwichtenberg, Walter Doberenz, Matthias Fischer, Jana Frank, Thomas Gewinnus, J&amp;#246;rg Krause und Patrick A. Lorenz geschrieben habe. Ich habe hierbei den Teil &amp;#252;ber die Windows Presentation Foundation beigesteuert.&lt;/p&gt;  &lt;p&gt;Weitere Infos gibt's &lt;a href="http://www.amazon.de/NET-3-5-LINQ-2008-ASP-NET/dp/3446410457/ref=sr_1_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1219310094&amp;amp;sr=8-1"&gt;hier&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.amazon.de/gp/reader/3446410457/ref=sib_dp_pt#reader-link"&gt;&lt;img src="http://ecx.images-amazon.com/images/I/41doDjCaT2L._SL500_BO2,204,203,200_PIsitb-dp-500-arrow,TopRight,45,-64_OU03_AA240_SH20_.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-5296320605831863926?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/5296320605831863926/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=5296320605831863926' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/5296320605831863926'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/5296320605831863926'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2008/08/net-35-buch-bei-hanser-erschienen.html' title='.NET 3.5-Buch bei Hanser erschienen'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-6461082123430221260</id><published>2008-08-21T11:19:00.001+02:00</published><updated>2008-08-22T13:07:03.301+02:00</updated><title type='text'>Artikel im dotnet Magazin</title><content type='html'>&lt;p&gt;In der aktuellen Ausgabe des &lt;a href="http://www.dotnetmagazin.de"&gt;dotnet Magazin&lt;/a&gt; (9/2008) ist der Artikel &amp;#8222;&lt;strong&gt;SQL Server Security f&amp;#252;r Entwickler&lt;/strong&gt;&amp;#8220; erschienen, den ich zusammen mit &lt;a href="http://www.leastprivilege.com/"&gt;Dominick Baier&lt;/a&gt; geschrieben habe. &lt;/p&gt;  &lt;p&gt;&lt;b&gt;Aus dem Abstract:      &lt;br /&gt;&lt;/b&gt;Das R&amp;#252;ckgrat nahezu jeder modernen Anwendung ist eine Datenbank. Dies bedeutet, dass die Gesamtsicherheit einer solchen Anwendung fest mit der Sicherheit der Daten gekoppelt ist. Aus diesem Grund sollten Entwickler ein Grundverst&amp;#228;ndnis f&amp;#252;r das Datenbank-Sicherheitsmodell haben sowie die Gegenma&amp;#223;nahmen f&amp;#252;r die typischsten Daten-Angriffe kennen.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/NeumannJN/SK0zBaMSdTI/AAAAAAAAAIQ/eL7JK8otELE/DM0808%5B4%5D.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="192" alt="DM 9.08 U4_U1.indd" src="http://lh6.ggpht.com/NeumannJN/SK0zCd4n1NI/AAAAAAAAAIU/t0Wtd_NoTgQ/DM0808_thumb%5B2%5D.jpg" width="150" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-6461082123430221260?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/6461082123430221260/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=6461082123430221260' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/6461082123430221260'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/6461082123430221260'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2008/08/artikel-im-dotnet-magazin.html' title='Artikel im dotnet Magazin'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/NeumannJN/SK0zCd4n1NI/AAAAAAAAAIU/t0Wtd_NoTgQ/s72-c/DM0808_thumb%5B2%5D.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-3823654591361219689</id><published>2008-08-21T11:06:00.001+02:00</published><updated>2008-08-21T11:06:01.982+02:00</updated><title type='text'>VIP-Tipp in der aktuellen dotnetpro</title><content type='html'>&lt;p&gt;F&amp;#252;r die aktuelle Ausgabe der &lt;a href="http://www.dotnetpro.de/"&gt;dotnetpro&lt;/a&gt; (09/2008) habe ich einen VIP-Tipp beigesteuert.&lt;/p&gt;  &lt;p&gt;Im VIP-Tipp stellt ein Experte f&amp;#252;nf bis zehn Buchtitel vor, die er pers&amp;#246;nlich f&amp;#252;r besonders lesenswert h&amp;#228;lt. Der VIP-Tipp soll als Entscheidungshilfe f&amp;#252;r Softwareentwickler bei der Auswahl der passenden Fachlekt&amp;#252;re dienen. Die Aktion ist eine Kooperation zwischen der Fachbuchhandlung &lt;a href="www.lob.de/viptip"&gt;Lehmanns&lt;/a&gt;, dem Seminaranbieter &lt;a href="www.prodevcollege.de"&gt;Professional Developer College&lt;/a&gt; und der &lt;a href="www.dotnetpro.de"&gt;dotnetpro&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Neben der Ver&amp;#246;ffentlichung in der dotnetpro, werden die empfohlenen B&amp;#252;cher auch auf der Site von Lehmanns (&lt;a href="www.lob.de/viptip"&gt;www.lob.de/viptip&lt;/a&gt;) beschrieben.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/NeumannJN/SK0v-AWT8hI/AAAAAAAAAII/LTZnrXqYV_A/dnp_092008%5B8%5D.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="129" alt="dnp_092008" src="http://lh6.ggpht.com/NeumannJN/SK0v-amHJ9I/AAAAAAAAAIM/JxnO2heSkG0/dnp_092008_thumb%5B6%5D.jpg" width="105" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-3823654591361219689?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/3823654591361219689/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=3823654591361219689' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/3823654591361219689'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/3823654591361219689'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2008/08/vip-tipp-in-der-aktuellen-dotnetpro.html' title='VIP-Tipp in der aktuellen dotnetpro'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/NeumannJN/SK0v-amHJ9I/AAAAAAAAAIM/JxnO2heSkG0/s72-c/dnp_092008_thumb%5B6%5D.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-8959771453602269779</id><published>2008-07-15T09:00:00.001+02:00</published><updated>2008-07-15T09:00:00.669+02:00</updated><title type='text'>Artikel und Interview in der aktuellen dotnetpro</title><content type='html'>&lt;p&gt;In der aktuellen Ausgabe der &lt;a href="http://www.dotnetpro.de/"&gt;dotnetpro&lt;/a&gt; (08/2008) sind zwei Artikel von mir zum Schwerpunktthema &amp;#8222;GUI&amp;#8220; erschienen.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;b&gt;Fenster mit System        &lt;br /&gt;&lt;/b&gt;Windows Forms hat sich im Bereich der Desktop-Anwendungen als De-facto-Standard etabliert. Doch mit der Windows Presentation Foundation steht bereits ein direkter Konkurrent in den Startl&amp;#246;chern. Kann sich der &amp;#8222;Dauerl&amp;#228;ufer&amp;#8220; in Zukunft behaupten?&lt;/p&gt;    &lt;p&gt;&lt;b&gt;Im Rausch der Oberfl&amp;#228;che        &lt;br /&gt;&lt;/b&gt;Mit der Windows Presentation Foundation will Microsoft nicht nur die GUI-Entwicklung auf eine neue Stufe stellen, sondern auch die Grenzen zwischen Desktop und Web &amp;#252;berwinden. Doch eignet sich das neue System auch f&amp;#252;r schn&amp;#246;de Businessanwendungen?&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Dar&amp;#252;ber hinaus wurde ich von der dotnetpro zum Thema &amp;#8222;Erweiterbare Anwendungen&amp;#8220; interviewed.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;b&gt;Erweiterbare Anwendungen aufbauen        &lt;br /&gt;&lt;/b&gt;Das Microsoft Add-in Framework (MAF) ist eine neue M&amp;#246;glichkeit, Anwendungen erweiterbar auf zubauen. J&amp;#246;rg Neumann wird das Framework auf der prio.conference 2008 vorstellen. dotnetpro sprach mit ihm, welche Vor- und Nachteile es bringt.&lt;/p&gt;&lt;/blockquote&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-8959771453602269779?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/8959771453602269779/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=8959771453602269779' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/8959771453602269779'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/8959771453602269779'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2008/07/artikel-und-interview-in-der-aktuellen.html' title='Artikel und Interview in der aktuellen dotnetpro'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-6617100573586120328</id><published>2008-07-07T10:47:00.002+02:00</published><updated>2008-07-07T10:52:05.172+02:00</updated><title type='text'>MVP'ed</title><content type='html'>&lt;p&gt;Microsoft has awarded me as MVP in the Client App Dev Category.&lt;br /&gt;Thanks!&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;a href="http://bp1.blogger.com/_11VTbOPwP_U/SHHZB7KP7JI/AAAAAAAAAIA/zRJMnC6VENI/s1600-h/MVPLogo.gif"&gt;&lt;img id="BLOGGER_PHOTO_ID_5220192070182890642" style="CURSOR: hand" alt="" src="http://bp1.blogger.com/_11VTbOPwP_U/SHHZB7KP7JI/AAAAAAAAAIA/zRJMnC6VENI/s400/MVPLogo.gif" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-6617100573586120328?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/6617100573586120328/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=6617100573586120328' title='1 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/6617100573586120328'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/6617100573586120328'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2008/07/mvp.html' title='MVP&amp;#39;ed'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp1.blogger.com/_11VTbOPwP_U/SHHZB7KP7JI/AAAAAAAAAIA/zRJMnC6VENI/s72-c/MVPLogo.gif' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-7922540378966598591</id><published>2008-04-25T09:31:00.001+02:00</published><updated>2008-04-25T09:31:53.066+02:00</updated><title type='text'>Slides &amp; Samples von der Jump!</title><content type='html'>&lt;p&gt;Die Slides &amp;amp; Samples meiner Vortr&amp;#228;ge, die ich auf der &lt;a href="http://www.prioconference.de/127.html"&gt;Jump!&lt;/a&gt;-Konferenz gehalten habe, finden Sie hier:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://www.esnips.com/doc/ed55d9b6-716b-4710-acbe-c1be0b3669e8/Jump2008_AddIns"&gt;Vom Monolithen zu flexiblen Anwendungen&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.esnips.com/doc/3ab561a4-2c41-4f43-9956-c3f1dadb17e9/Jump2008_WPFInterop"&gt;Von WinForms nach WPF und zur&amp;#252;ck&lt;/a&gt;      &lt;br /&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-7922540378966598591?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/7922540378966598591/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=7922540378966598591' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/7922540378966598591'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/7922540378966598591'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2008/04/slides-samples-von-der-jump.html' title='Slides &amp;amp; Samples von der Jump!'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-296850919210810035</id><published>2008-04-22T13:12:00.001+02:00</published><updated>2008-04-22T13:12:21.318+02:00</updated><title type='text'>Update für WindowsFormsAddInProxy</title><content type='html'>&lt;p&gt;Neulich machte mich jemand darauf aufmerksam, dass die Pfeiltasten in Input Controls nicht funktionieren, wenn diese vom Add-In bereit gestellt werden.&lt;/p&gt;  &lt;p&gt;Der Grund war, dass die entsprechenden Keyboard-Messages nicht per SendMessage() synchronisiert wurden und somit auf Host-Seite h&amp;#228;ngen blieben.&lt;/p&gt;  &lt;p&gt;Ich habe den Bug gefixed und die aktuelle Version &lt;a href="http://www.esnips.com/doc/2a799f7b-b0fa-4ec2-9ac4-cc0d352f3a7d/SystemAddInWinFormsDemoV3.1"&gt;hier&lt;/a&gt; bereit gestellt.&lt;/p&gt;  &lt;p&gt;PS: Wenn Sie mehr &amp;#252;ber System.AddIn oder meine Windows Forms-Implementierung erfahren m&amp;#246;chten, kommen Sie auf dotnetpro Jump!-Konferenz, die am 24.04. in M&amp;#252;nchen statt findet. Hier halte ich eine Session zu dem Thema und beantworte gerne Ihre Fragen.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-296850919210810035?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/296850919210810035/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=296850919210810035' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/296850919210810035'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/296850919210810035'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2008/04/update-fr-windowsformsaddinproxy.html' title='Update für WindowsFormsAddInProxy'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-2099327741543495329</id><published>2008-03-05T08:45:00.003+01:00</published><updated>2008-03-05T08:52:58.490+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Veröffentlichungen'/><title type='text'>Artikel im devdorado.de-Magazin</title><content type='html'>In der aktuellen Ausgabe des kostenlosen &lt;a href="http://www.zoschke.com/"&gt;devdorado.de&lt;/a&gt;-Magazins ist ein Artikel von mir zum neuen SQL Server 2008 erschienen.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Aus dem Abstract:&lt;/strong&gt;&lt;br /&gt;Vor gerade einmal zwei Jahren lieferte Micorosoft mit dem SQL Server 2005 ein umfangreiches Update seines Datenbanksystems. Die Erweiterungen im SQL Server 2008 fallen aufgrund der kürzeren Entwicklungszeit nicht ganz so üppig aus. Doch auch wenn die ganz großen Neuerungen fehlen, hat Microsoft an vielen Stellen sinnvolle Verbesserungen vorgenommen. Besonders Entwickler profitieren davon.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-2099327741543495329?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/2099327741543495329/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=2099327741543495329' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/2099327741543495329'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/2099327741543495329'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2008/03/artikel-im-devdoradode-magazin.html' title='Artikel im devdorado.de-Magazin'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-5653593011208341593</id><published>2008-02-29T11:53:00.002+01:00</published><updated>2008-03-05T08:53:38.438+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Konferenzen'/><title type='text'>Slides von der BASTA! Spring</title><content type='html'>&lt;p&gt;Auf der &lt;a href="http://basta.net/"&gt;BASTA! Spring&lt;/a&gt; hatte ich neben einigen Vorträgen auch wieder viel Spaß. Die Slides meiner Vorträge finden Sie hier:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.esnips.com/doc/7513b3b8-2586-4891-b02a-7f4795580bc5/WpfInterop_Neumann"&gt;Glücklich vereint: Interoperabilität zwischen WPF und Windows Forms&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.esnips.com/doc/e81327fc-e646-4e4d-99f9-6c30abf09a9d/Offline_Neumann"&gt;Bin dann mal weg! Entwicklung von Offline-Clients&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.esnips.com/doc/90b00cab-3e7d-4d90-9bef-02e1757a8919/SQLServerSecurity"&gt;SQL Server Security für Entwickler&lt;/a&gt;&lt;br /&gt;(zusammen mit &lt;a href="http://www.leastprivilege.com/"&gt;Dominick Baier&lt;/a&gt;)&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.esnips.com/doc/d99c60da-731e-4798-9484-c174be2ad15d/AddIns"&gt;.NET-Anwendungen sicher und robust durch Add-ins erweitern&lt;/a&gt; (zusammen mit &lt;a href="http://www.leastprivilege.com/"&gt;Dominick Baier&lt;/a&gt;) &lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-5653593011208341593?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/5653593011208341593/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=5653593011208341593' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/5653593011208341593'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/5653593011208341593'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2008/02/slides-von-der-basta-spring.html' title='Slides von der BASTA! Spring'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-6545346397407279818</id><published>2008-02-16T12:28:00.001+01:00</published><updated>2008-02-16T12:28:33.913+01:00</updated><title type='text'>Check for online/offline state correctly</title><content type='html'>&lt;p&gt;With the introduction of the &lt;strong&gt;System.Net.NetworkInformation&lt;/strong&gt; namespace in .NET 2.0, you can easily check for the availability of a network. When you want to be notified when the machine gets online or offline, you can add a handler to the &lt;strong&gt;NetworkChange.NetworkAvailabilityChanged&lt;/strong&gt; event.&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: 10pt; color: #2b91af; font-family: " courier="courier" new?;="new?;" mso-fareast-language:="mso-fareast-language:" mso-no-proof:="mso-no-proof:" yes;="yes;" mso-fareast-font-family:="mso-fareast-font-family:" ?Times="?Times" New="New" Roman?;="Roman?;" mso-ansi-language:="mso-ansi-language:" DE;="DE;" mso-bidi-language:="mso-bidi-language:" ar-sa?="AR-SA?"&gt;NetworkChange&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: " courier="courier" new?;="new?;" mso-fareast-language:="mso-fareast-language:" mso-no-proof:="mso-no-proof:" yes;="yes;" mso-fareast-font-family:="mso-fareast-font-family:" ?Times="?Times" New="New" Roman?;="Roman?;" mso-ansi-language:="mso-ansi-language:" DE;="DE;" mso-bidi-language:="mso-bidi-language:" ar-sa?="AR-SA?"&gt;.NetworkAvailabilityChanged +=      &lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: " courier="courier" new?;="new?;" mso-fareast-language:="mso-fareast-language:" mso-no-proof:="mso-no-proof:" yes;="yes;" mso-fareast-font-family:="mso-fareast-font-family:" ?Times="?Times" New="New" Roman?;="Roman?;" mso-ansi-language:="mso-ansi-language:" DE;="DE;" mso-bidi-language:="mso-bidi-language:" ar-sa?="AR-SA?"&gt;&lt;span style="color: blue"&gt;delegate&lt;/span&gt;(&lt;span style="color: blue"&gt;object&lt;/span&gt; sender, &lt;span style="color: #2b91af"&gt;NetworkAvailabilityEventArgs&lt;/span&gt; e)       &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; _isOnline = e.IsAvailable;       &lt;br /&gt;};&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;The problem with this event is, that it isn't triggerd if you have a loopback adapter installed on your machine.&lt;/p&gt;  &lt;p&gt;But the &lt;strong&gt;NetworkChange&lt;/strong&gt; class has a &lt;strong&gt;NetworkAddressChanged&lt;/strong&gt; event, that is fired, when the IP-address of one of your network adapters changes. In the handler you can get the available adapters and check the type via the &lt;strong&gt;NetworkInterface.NetworkInterfaceType&lt;/strong&gt; property. Additionally the &lt;strong&gt;Networkinterface&lt;/strong&gt; class has a static &lt;strong&gt;LoopbackInterfaceIndex&lt;/strong&gt; property that gives you the index of the loopback adapter. With that in mind you can implement an online/offline check like this:&lt;/p&gt;  &lt;p&gt;&lt;span style="color: #2b91af; font-family: " courier="courier" new?;="new?;" mso-fareast-language:="mso-fareast-language:" mso-no-proof:="mso-no-proof:" mso-bidi-font-size:="mso-bidi-font-size:" 10.0pt;="10.0pt;" yes?="yes?" de;="DE;"&gt;NetworkChange&lt;/span&gt;&lt;span style="font-family: " courier="courier" new?;="new?;" mso-fareast-language:="mso-fareast-language:" mso-no-proof:="mso-no-proof:" mso-bidi-font-size:="mso-bidi-font-size:" 10.0pt;="10.0pt;" yes?="yes?" de;="DE;"&gt;.NetworkAddressChanged += &lt;span style="color: blue"&gt;delegate        &lt;br /&gt;&lt;/span&gt;{       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;_&lt;/span&gt;isOnline = &lt;span style="color: blue"&gt;false&lt;/span&gt;;       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;NetworkInterface&lt;/span&gt;[] adapters =       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #2b91af"&gt;NetworkInterface&lt;/span&gt;.GetAllNetworkInterfaces();       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;for&lt;/span&gt; (&lt;span style="color: blue"&gt;int&lt;/span&gt; i = 0; i &amp;lt; adapters.Length; i++)       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;{       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;NetworkInterface&lt;/span&gt; adp = adapters[i];       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (adp.OperationalStatus==&lt;span style="color: #2b91af"&gt;OperationalStatus&lt;/span&gt;.Up &amp;amp;&amp;amp;       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;adp.NetworkInterfaceType !=&lt;span style="color: #2b91af"&gt;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; NetworkInterfaceType&lt;/span&gt;.Loopback &amp;amp;&amp;amp;       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;i + 1 != &lt;span style="color: #2b91af"&gt;NetworkInterface&lt;/span&gt;.LoopbackInterfaceIndex)       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;{       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; _&lt;/span&gt;isOnline = &lt;span style="color: blue"&gt;true&lt;/span&gt;;       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;break&lt;/span&gt;;       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;}       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;}       &lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: " courier="courier" new?;="new?;" mso-fareast-language:="mso-fareast-language:" mso-no-proof:="mso-no-proof:" mso-bidi-font-size:="mso-bidi-font-size:" 10.0pt;="10.0pt;" yes?="yes?" de;="DE;"&gt;};&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;If you want to refresh your UI when the state changes, you must synchronize the threads, because the &lt;strong&gt;NetworkAddressChange&lt;/strong&gt; event calls you from a worker thread. But thanks to the &lt;strong&gt;SynchronizationContext&lt;/strong&gt; class introduced in .Net 2.0 you can easily do that like this: (thanks to &lt;a href="http://www.leastprivilege.com"&gt;Dominick&lt;/a&gt; for the hint):&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: 10pt; color: #2b91af; font-family: " courier="courier" new?;="new?;" mso-fareast-language:="mso-fareast-language:" mso-no-proof:="mso-no-proof:" yes;="yes;" mso-fareast-font-family:="mso-fareast-font-family:" ?Times="?Times" New="New" Roman?;="Roman?;" mso-ansi-language:="mso-ansi-language:" DE;="DE;" mso-bidi-language:="mso-bidi-language:" ar-sa?="AR-SA?"&gt;class&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: " courier="courier" new?;="new?;" mso-fareast-language:="mso-fareast-language:" mso-no-proof:="mso-no-proof:" yes;="yes;" mso-fareast-font-family:="mso-fareast-font-family:" ?Times="?Times" New="New" Roman?;="Roman?;" mso-ansi-language:="mso-ansi-language:" DE;="DE;" mso-bidi-language:="mso-bidi-language:" ar-sa?="AR-SA?"&gt; MyClass      &lt;br /&gt;{       &lt;br /&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;SynchronizationContext&lt;/span&gt; _syncContext;     &lt;br /&gt;    &lt;br /&gt;&lt;span style="font-size: 10pt; color: #2b91af; font-family: " courier="courier" new?;="new?;" mso-fareast-language:="mso-fareast-language:" mso-no-proof:="mso-no-proof:" yes;="yes;" mso-fareast-font-family:="mso-fareast-font-family:" ?Times="?Times" New="New" Roman?;="Roman?;" mso-ansi-language:="mso-ansi-language:" DE;="DE;" mso-bidi-language:="mso-bidi-language:" ar-sa?="AR-SA?"&gt;&amp;#160; &lt;span style="color: blue"&gt;public&lt;/span&gt;&lt;/span&gt; MyClass()     &lt;br /&gt;&amp;#160; {     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; _syncContext = &lt;span style="color: #2b91af"&gt;SynchronizationContext&lt;/span&gt;.Current;     &lt;br /&gt;&amp;#160; }     &lt;br /&gt;    &lt;br /&gt;...     &lt;br /&gt;    &lt;br /&gt;&lt;span style="color: blue"&gt;void &lt;/span&gt;MyMethod()     &lt;br /&gt;{     &lt;br /&gt;&amp;#160; ...     &lt;br /&gt;&amp;#160; _syncContext.Post(&lt;span style="color: blue"&gt;delegate&lt;/span&gt;     &lt;br /&gt;&lt;span style="font-size: 10pt; font-family: " courier="courier" new?;="new?;" mso-fareast-language:="mso-fareast-language:" mso-no-proof:="mso-no-proof:" yes;="yes;" mso-fareast-font-family:="mso-fareast-font-family:" ?Times="?Times" New="New" Roman?;="Roman?;" mso-ansi-language:="mso-ansi-language:" DE;="DE;" mso-bidi-language:="mso-bidi-language:" ar-sa?="AR-SA?"&gt;&amp;#160; {      &lt;br /&gt;&lt;span style="color: blue"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;ToggleOnlineState(isOnline);       &lt;br /&gt;&amp;#160; }, null);       &lt;br /&gt;}&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: " courier="courier" new?;="new?;" mso-fareast-language:="mso-fareast-language:" mso-no-proof:="mso-no-proof:" yes;="yes;" mso-fareast-font-family:="mso-fareast-font-family:" ?Times="?Times" New="New" Roman?;="Roman?;" mso-ansi-language:="mso-ansi-language:" DE;="DE;" mso-bidi-language:="mso-bidi-language:" ar-sa?="AR-SA?"&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;Now you get informed correctly if the machine moves online or offline.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-6545346397407279818?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/6545346397407279818/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=6545346397407279818' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/6545346397407279818'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/6545346397407279818'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2008/02/check-for-onlineoffline-state-correctly.html' title='Check for online/offline state correctly'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-4319200482659736646</id><published>2008-01-30T15:34:00.001+01:00</published><updated>2008-01-30T16:09:09.767+01:00</updated><title type='text'>Ein Command-Modell für System.AddIn, Teil 2</title><content type='html'>&lt;p&gt;Nachdem ich im &lt;a href="http://headwriteline.blogspot.com/2008/01/ein-command-modell-fr-systemaddin-teil.html"&gt;ersten Teil&lt;/a&gt; bereits mein Command-Modell und dessen Integration in die Host-Anwendung beschrieben habe, soll es nun um die Add-In-Seite gehen.&lt;/p&gt;  &lt;p&gt;W&amp;#228;hrend der Aktivierung ruft die &lt;strong&gt;AddInHost&lt;/strong&gt;-Komponente die &lt;strong&gt;InitializeCommands()&lt;/strong&gt;-Methode des Add-In auf. Hierbei wird eine Instanz von &lt;strong&gt;ICommandContext&lt;/strong&gt; &amp;#252;bergeben, &amp;#252;ber die das Add-In Zugriff auf &lt;strong&gt;ICommandService&lt;/strong&gt; und &lt;strong&gt;IUIContextService&lt;/strong&gt; hat. &amp;#220;ber diese Interfaces l&amp;#228;uft im weiteren Verlauf die Kommunikation. Die folgende Abbildung zeigt den grundlegenden Ablauf.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.google.com/NeumannJN/R6CTDJiB8RI/AAAAAAAAAHo/ACWDRU8J7Wc/CommandCommunication%5B9%5D"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="302" alt="CommandCommunication" src="http://lh6.google.com/NeumannJN/R6CTFJiB8SI/AAAAAAAAAHw/tF7gJGQPM-4/CommandCommunication_thumb%5B5%5D" width="466" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Das Add-In muss nun zun&amp;#228;chst die vom Host angebotene Command-Struktur ermitteln, um sich im Anschluss in diese integrieren zu k&amp;#246;nnen.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="color: blue; font-family: " yes?="yes?" mso-no-proof:="mso-no-proof:" DE;="DE;" mso-fareast-language:="mso-fareast-language:" 10.0pt;="10.0pt;" mso-bidi-font-size:="mso-bidi-font-size:" new?;="new?;" courier="courier"&gt;public&lt;/span&gt;&lt;span style="font-family: " yes?="yes?" mso-no-proof:="mso-no-proof:" DE;="DE;" mso-fareast-language:="mso-fareast-language:" 10.0pt;="10.0pt;" mso-bidi-font-size:="mso-bidi-font-size:" new?;="new?;" courier="courier"&gt; &lt;span style="color: blue"&gt;override&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; InitializeCommands(&lt;span style="color: #2b91af"&gt;ICommandContext&lt;/span&gt; context)      &lt;br /&gt;{       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: green"&gt;// CommandService und UICommandService ermitteln        &lt;br /&gt;&lt;/span&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ICommandService&lt;/span&gt; cmdSrv = context.CommandService;       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IUICommandService&lt;/span&gt; cmdUISrv=context.UICommandService;       &lt;br /&gt;      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: green"&gt;// File-Commands ermitteln        &lt;br /&gt;&lt;/span&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ICommand&lt;/span&gt; fileCmd = cmdSrv.GetCommand(&lt;span style="color: #a31515"&gt;&amp;quot;Host.File&amp;quot;&lt;/span&gt;);       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IUICommand&lt;/span&gt; fileUICmd = cmdUISrv.GetUICommand(       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; fileCommand, &lt;span style="color: #2b91af"&gt;UICommandType&lt;/span&gt;.MenuCommand);       &lt;br /&gt;      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: green"&gt;// Toolbar ermitteln        &lt;br /&gt;&lt;/span&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IUICommand&lt;/span&gt; toolbarUICmd = cmdUISrv.GetMainToobar();      &lt;br /&gt;      &lt;br /&gt;...      &lt;br /&gt;      &lt;br /&gt;}&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Hier werden die &lt;strong&gt;ICommand&lt;/strong&gt;- und &lt;strong&gt;IUICommand&lt;/strong&gt;-Objekte des &lt;em&gt;File&lt;/em&gt;-Men&amp;#252;s, sowie die prim&amp;#228;re Toolbar ermittelt. Daraufhin k&amp;#246;nnen neue Elemente eingef&amp;#252;gt werden:&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="color: green; font-family: " yes?="yes?" mso-no-proof:="mso-no-proof:" DE;="DE;" mso-fareast-language:="mso-fareast-language:" 10.0pt;="10.0pt;" mso-bidi-font-size:="mso-bidi-font-size:" new?;="new?;" courier="courier"&gt;// &amp;quot;Neu&amp;quot;-Command erstellen     &lt;br /&gt;&lt;/span&gt;&lt;span style="color: #2b91af; font-family: " yes?="yes?" mso-no-proof:="mso-no-proof:" DE;="DE;" mso-fareast-language:="mso-fareast-language:" 10.0pt;="10.0pt;" mso-bidi-font-size:="mso-bidi-font-size:" new?;="new?;" courier="courier"&gt;ICommand&lt;/span&gt;&lt;span style="font-family: " yes?="yes?" mso-no-proof:="mso-no-proof:" DE;="DE;" mso-fareast-language:="mso-fareast-language:" 10.0pt;="10.0pt;" mso-bidi-font-size:="mso-bidi-font-size:" new?;="new?;" courier="courier"&gt; fileNewCmd = cmdSrv.CreateCommand(      &lt;br /&gt;&lt;span style="color: #a31515"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;&amp;quot;FirstAddIn.File.New&amp;quot;&lt;/span&gt;,       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;fileCmd);&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;Hierbei werden ein eindeutiger Name, sowie das jeweils &amp;#252;bergeordnete &lt;strong&gt;Command&lt;/strong&gt;-Objekt angegeben. Dazu passend k&amp;#246;nnen nun entsprechende Men&amp;#252;- und Toolbar-&lt;strong&gt;UICommand&lt;/strong&gt;s erstellt werden:&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: 10pt; color: green; font-family: " mso-no-proof:="mso-no-proof:" de;="DE;" mso-fareast-language:="mso-fareast-language:" new?;="new?;" courier="courier" AR-SA?="AR-SA?" mso-bidi-language:="mso-bidi-language:" mso-ansi-language:="mso-ansi-language:" Roman?;="Roman?;" New="New" ?Times="?Times" mso-fareast-font-family:="mso-fareast-font-family:" yes;="yes;"&gt;// &amp;quot;Neu&amp;quot;-UICommand erstellen      &lt;br /&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; color: #2b91af; font-family: " mso-no-proof:="mso-no-proof:" de;="DE;" mso-fareast-language:="mso-fareast-language:" new?;="new?;" courier="courier" AR-SA?="AR-SA?" mso-bidi-language:="mso-bidi-language:" mso-ansi-language:="mso-ansi-language:" Roman?;="Roman?;" New="New" ?Times="?Times" mso-fareast-font-family:="mso-fareast-font-family:" yes;="yes;"&gt;IUICommand&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: " mso-no-proof:="mso-no-proof:" de;="DE;" mso-fareast-language:="mso-fareast-language:" new?;="new?;" courier="courier" AR-SA?="AR-SA?" mso-bidi-language:="mso-bidi-language:" mso-ansi-language:="mso-ansi-language:" Roman?;="Roman?;" New="New" ?Times="?Times" mso-fareast-font-family:="mso-fareast-font-family:" yes;="yes;"&gt; fileNewUICmd = UICmdSrv.CreateMenuItem(      &lt;br /&gt;&amp;#160; fileNewCmd,       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: #a31515"&gt;&amp;quot;&amp;amp;Neu&amp;quot;&lt;/span&gt;,       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;fileUICmd,       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;0,       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ToolStripItemDisplayStyle&lt;/span&gt;.ImageAndText,       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;UICmdSrv.GetIconArray(Properties.&lt;span style="color: #2b91af"&gt;Resources&lt;/span&gt;.New));&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;In diesem Fall wird ein Men&amp;#252;element erstellt und hierbei das zugeh&amp;#246;rige &lt;strong&gt;ICommand&lt;/strong&gt;-Objekt, ein Anzeigetext, das &amp;#252;bergeordnetes &lt;strong&gt;IUICommand&lt;/strong&gt;-Objekt, ein Index, sowie der Darstellungsstil und ein Symbol angegeben. Da Bilder in Form von Byte-Arrays &amp;#252;ber die AppDomain-Grenze geschickt werden, m&amp;#252;ssen sie &amp;#252;ber die &lt;strong&gt;GetIconArray()&lt;/strong&gt;-, bzw. &lt;strong&gt;GetImageArray()&lt;/strong&gt;-Methode entsprechend konvertiert werden.&lt;/p&gt;  &lt;p&gt;Dar&amp;#252;ber hinaus k&amp;#246;nnen zus&amp;#228;tzliche Eigenschaften wie &lt;strong&gt;Visible&lt;/strong&gt;, &lt;strong&gt;Checked&lt;/strong&gt; oder &lt;strong&gt;ShortcutKeys&lt;/strong&gt; festgelegt werden.&lt;/p&gt;  &lt;p&gt;Die Erstellung von Toolbar-Elementen erfolgt analog, nur dass hierf&amp;#252;r die &lt;strong&gt;CreateToolbar()&lt;/strong&gt;-Methode aufzurufen ist. Dar&amp;#252;ber hinaus k&amp;#246;nnen mit der &lt;strong&gt;CreateSeparator()&lt;/strong&gt;-Methode Separatorelemente f&amp;#252;r Men&amp;#252; und Toolbar erstellt werden.&lt;/p&gt;  &lt;p&gt;Wurde ein Command auf Host-Seite aktiviert, so ruft der Host die &lt;strong&gt;NotifyCommandExecuted()&lt;/strong&gt;-Methode des Add-In auf und &amp;#252;bergibt hierbei die jeweilige &lt;strong&gt;ICommand&lt;/strong&gt;-Instanz.&lt;/p&gt;  &lt;p&gt;Das Add-In kann daraufhin beispielsweise seine Oberfl&amp;#228;che anzeigen. Hierf&amp;#252;r bietet die &lt;strong&gt;CommandContext&lt;/strong&gt;-Klasse die &lt;strong&gt;ShowSurface()&lt;/strong&gt;-Methode, welche als Parameter eine &lt;strong&gt;WindowProxy&lt;/strong&gt;-Instanz &amp;#252;bergeben bekommt (Details &lt;a href="http://headwriteline.blogspot.com/2008/01/test.html"&gt;hier&lt;/a&gt;).&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: 10pt; font-family: " mso-no-proof:="mso-no-proof:" de;="DE;" mso-fareast-language:="mso-fareast-language:" new?;="new?;" courier="courier" AR-SA?="AR-SA?" mso-bidi-language:="mso-bidi-language:" mso-ansi-language:="mso-ansi-language:" Roman?;="Roman?;" New="New" ?Times="?Times" mso-fareast-font-family:="mso-fareast-font-family:" yes;="yes;"&gt;&lt;span style="color: blue; font-family: " yes?="yes?" mso-no-proof:="mso-no-proof:" DE;="DE;" mso-fareast-language:="mso-fareast-language:" 10.0pt;="10.0pt;" mso-bidi-font-size:="mso-bidi-font-size:" new?;="new?;" courier="courier"&gt;public&lt;/span&gt;&lt;span style="font-family: " yes?="yes?" mso-no-proof:="mso-no-proof:" DE;="DE;" mso-fareast-language:="mso-fareast-language:" 10.0pt;="10.0pt;" mso-bidi-font-size:="mso-bidi-font-size:" new?;="new?;" courier="courier"&gt; &lt;span style="color: blue"&gt;override&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; NotifyCommandExecuted(&lt;span style="color: #2b91af"&gt;ICommand&lt;/span&gt; command)        &lt;br /&gt;{         &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (command == m_fileNewCommand)         &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;{         &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;m_surface = &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Surface&lt;/span&gt;();         &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;m_context.ShowSurface(&lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;WindowProxy&lt;/span&gt;(m_surface));         &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;}         &lt;br /&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: 10pt; font-family: " mso-no-proof:="mso-no-proof:" de;="DE;" mso-fareast-language:="mso-fareast-language:" new?;="new?;" courier="courier" AR-SA?="AR-SA?" mso-bidi-language:="mso-bidi-language:" mso-ansi-language:="mso-ansi-language:" Roman?;="Roman?;" New="New" ?Times="?Times" mso-fareast-font-family:="mso-fareast-font-family:" yes;="yes;"&gt;&lt;span style="font-family: " yes?="yes?" mso-no-proof:="mso-no-proof:" DE;="DE;" mso-fareast-language:="mso-fareast-language:" 10.0pt;="10.0pt;" mso-bidi-font-size:="mso-bidi-font-size:" new?;="new?;" courier="courier"&gt;&lt;font face="ver"&gt;&lt;strong&gt;Surface&lt;/strong&gt; ist ein User Control, welches von &lt;strong&gt;AddInSurface&lt;/strong&gt; ableitet und die Oberfl&amp;#228;che des Add-In enth&amp;#228;lt. Die Einzelheiten dieser Komponente habe ich bereits &lt;a href="http://headwriteline.blogspot.com/2008/01/test.html"&gt;hier&lt;/a&gt; beschrieben.&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;Die Sourcen inkl. Beispielanwendung gibt's &lt;a href="http://www.esnips.com/doc/57be0ea5-d34f-4fd0-8225-927e373e6333/AddInCommandDemo"&gt;hier&lt;/a&gt;.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-4319200482659736646?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/4319200482659736646/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=4319200482659736646' title='3 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/4319200482659736646'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/4319200482659736646'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2008/01/ein-command-modell-fr-systemaddin-teil_30.html' title='Ein Command-Modell für System.AddIn, Teil 2'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-186741300330852638</id><published>2008-01-30T11:55:00.001+01:00</published><updated>2008-01-30T11:57:50.846+01:00</updated><title type='text'>Ein Command-Modell für System.AddIn, Teil 1</title><content type='html'>&lt;p&gt;Nachdem ich &lt;a href="http://headwriteline.blogspot.com/2008/01/test.html"&gt;hier&lt;/a&gt; und &lt;a href="http://headwriteline.blogspot.com/2008/01/grafische-verwaltung-von-add-ins.html"&gt;hier&lt;/a&gt; bereits die Grundlage f&amp;#252;r erweiterbare Anwendungen auf Basis von Windows Forms gelegt habe, m&amp;#246;chte ich nun einen Schritt weiter gehen. Denn die Integration von Add-Ins in die Host-Anwendung macht erst so richtig Sinn, wenn ein gemeinsames Command-Modell existiert, &amp;#252;ber das eine Bereitstellung von Men&amp;#252;- und Toolbar-Elementen m&amp;#246;glich ist.&lt;/p&gt;  &lt;p&gt;Im ersten Teil m&amp;#246;chte ich zun&amp;#228;chst das Modell und die Host-Integration beschreiben, w&amp;#228;hrend es im zweiten Teil um die Add-In-Seite gehen soll.&lt;/p&gt;  &lt;p&gt;Die Basis des Command-Modells bilden die Interfaces &lt;strong&gt;ICommand&lt;/strong&gt; und &lt;strong&gt;UICommand&lt;/strong&gt;, deren Member in der folgenden Abbildung dargestellt sind:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.google.com/NeumannJN/R6BXZZiB8FI/AAAAAAAAAGI/fZZFmfAVXc8/Commands%5B6%5D"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="355" alt="Commands" src="http://lh4.google.com/NeumannJN/R6BXapiB8GI/AAAAAAAAAGQ/3qkidnyQ8rg/Commands_thumb%5B4%5D" width="395" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;W&amp;#228;hrend &lt;strong&gt;ICommand&lt;/strong&gt; die allgemeinen Eigenschaften einer hierarchischen Command-Struktur definiert, legt &lt;strong&gt;IUICommand&lt;/strong&gt; die grafische Repr&amp;#228;sentation fest.&lt;/p&gt;  &lt;p&gt;Hierbei bildet der Host zun&amp;#228;chst seine Men&amp;#252;- und Toolbar-Struktur &amp;#252;ber Commands ab und &amp;#252;bergibt diese an die Add-Ins. Diese k&amp;#246;nnen sich daraufhin in die Hierarchie integrieren und eigene Commands anbieten. F&amp;#252;r die Manipulation der Struktur werden die Interfaces &lt;strong&gt;ICommandService&lt;/strong&gt; und &lt;strong&gt;IUICommandService&lt;/strong&gt; bereitgestellt. Beide werden &amp;#252;ber &lt;strong&gt;ICommandContext&lt;/strong&gt; zusammengefasst und w&amp;#228;hrend der Aktivierung an das Add-In &amp;#252;bergeben.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.google.com/NeumannJN/R6BXbpiB8HI/AAAAAAAAAGY/FLRUx9l4VGk/CommandServices%5B6%5D"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="382" alt="CommandServices" src="http://lh6.google.com/NeumannJN/R6BXdJiB8II/AAAAAAAAAGg/-lRsybpcg_A/CommandServices_thumb%5B4%5D" width="467" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;W&amp;#228;hrend mit &lt;strong&gt;ICommandService&lt;/strong&gt; die ben&amp;#246;tigten Command-Objekte erstellt werden, ist &lt;strong&gt;IUICommandService&lt;/strong&gt; f&amp;#252;r die Generierung einer grafischen Repr&amp;#228;sentation in Form von Men&amp;#252;- und Toolbar-Elementen verantwortlich. &amp;#220;ber die &lt;strong&gt;ShowSurface()&lt;/strong&gt;-Methode von &lt;strong&gt;ICommandContext&lt;/strong&gt; hat das Add-In zus&amp;#228;tzlich die M&amp;#246;glichkeit seine Oberfl&amp;#228;che an den Host zu &amp;#252;bertragen (beispielsweise wenn ein Command aktiviert wurde).&lt;/p&gt;  &lt;p&gt;Die Kommunikation zwischen Host und Add-Ins erfolgt &amp;#252;ber das &lt;strong&gt;IAddInCommandContract&lt;/strong&gt;-Interface, welches von der entsprechenden Host-View-Klasse implementiert wird. Zus&amp;#228;tzlich findet sich dessen Signatur auch im jeweiligen Add-In-Contract (hier &lt;strong&gt;IAddInContract&lt;/strong&gt; genannt).&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.google.com/NeumannJN/R6BXeJiB8JI/AAAAAAAAAGo/9P1JL_4wrtQ/CommandContracts%5B5%5D"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="306" alt="CommandContracts" src="http://lh5.google.com/NeumannJN/R6BXe5iB8KI/AAAAAAAAAGw/Ioo55eyvdZI/CommandContracts_thumb%5B3%5D" width="471" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Nachdem ein Add-In geladen wurde, ruft der Host die &lt;strong&gt;InitializeCommands()&lt;/strong&gt;-Methode auf und &amp;#252;bergibt ein &lt;strong&gt;ICommandContext&lt;/strong&gt;-Objekt. Daraufhin registriert sich das Add-In in der Command-Hierarchie. Beim Ausl&amp;#246;sen eines Commands informiert der Host das Add-In &amp;#252;ber die &lt;strong&gt;NotifyCommandExecuted()&lt;/strong&gt;-Methode. Optional hat die Host-Anwendung &amp;#252;ber die &lt;strong&gt;GetSurface()&lt;/strong&gt;-Methode die M&amp;#246;glichkeit, die Oberfl&amp;#228;che des Add-In explizit anzufordern.&lt;/p&gt;  &lt;p&gt;Was nun noch fehlt ist eine Komponente die auf Host-Seite die Integration der Commands in die jeweilige Men&amp;#252;- und Toolbar-Struktur &amp;#252;bernimmt. Hier kommt &lt;strong&gt;AddInHost&lt;/strong&gt; zum Einsatz. Es leitet von &lt;strong&gt;Component&lt;/strong&gt; ab und kann daher direkt aus der Toolbox auf eine Form gezogen werden. &lt;strong&gt;AddInHost&lt;/strong&gt; bekommt &amp;#252;ber die Eigenschaften &lt;strong&gt;MainMenuStrip&lt;/strong&gt; und &lt;strong&gt;MainToolStrip&lt;/strong&gt; die prim&amp;#228;re Men&amp;#252;leiste bzw. Toolbar &amp;#252;bergeben. Zus&amp;#228;tzlich kann ihr eine Instanz von &lt;strong&gt;WindowProxyPanel&lt;/strong&gt; &amp;#252;bergeben werden, welches zur Darstellung der Add-In-Oberfl&amp;#228;che dient (Details &lt;a href="http://headwriteline.blogspot.com/2008/01/test.html"&gt;hier&lt;/a&gt;). Auf diese Weise kann &lt;strong&gt;AddInHost&lt;/strong&gt; nicht nur die entsprechenden Commands in Men&amp;#252; und Toolbar anlegen, sondern die Oberfl&amp;#228;che auch automatisch binden, wenn das Add-In dies &amp;#252;ber &lt;strong&gt;ICommandContext.ShowSurface()&lt;/strong&gt; veranlasst. Zus&amp;#228;tzlich bietet die Komponente &amp;#252;ber die &lt;strong&gt;ShowAddInManager()&lt;/strong&gt;-Methode die M&amp;#246;glichkeit den Add-In-Konfigurationsdialog zu &amp;#246;ffnen, der f&amp;#252;r das Laden und Entladen der Add-Ins zust&amp;#228;ndig ist (Details &lt;a href="http://headwriteline.blogspot.com/2008/01/grafische-verwaltung-von-add-ins.html"&gt;hier&lt;/a&gt;).&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.google.com/NeumannJN/R6BXf5iB8LI/AAAAAAAAAG4/b1WBTHhyQWg/CommandComponents%5B5%5D"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="382" alt="CommandComponents" src="http://lh4.google.com/NeumannJN/R6BXhpiB8MI/AAAAAAAAAHA/JN764qEaSng/CommandComponents_thumb%5B3%5D" width="471" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Durch die enge Verzahnung der Komponenten, wird die Implementierung des Add-In-Supports f&amp;#252;r die Host-Anwendung zum Kinderspiel. Sie muss lediglich die folgenden Komponenten zu Verf&amp;#252;gung stellen:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;MenuStrip&lt;/li&gt;    &lt;li&gt;ToolStrip&lt;/li&gt;    &lt;li&gt;WindowProxyPanel&lt;/li&gt;    &lt;li&gt;AddInHost&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Nachdem alle Komponenten mit &lt;strong&gt;AddInHost&lt;/strong&gt; verbunden wurden, sind lediglich die folgenden Codezeilen erforderlich:&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align: none"&gt;&lt;span style="color: green; font-family: " courier new"; mso-bidi-font-size: 10.0pt; mso-fareast-language: DE; mso-no-proof: yes"&gt;// Add-In-Pfad zuweisen     &lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: " courier new"; mso-bidi-font-size: 10.0pt; mso-fareast-language: DE; mso-no-proof: yes"&gt;addInHost1.AddInPath = &lt;span style="color: #2b91af"&gt;Environment&lt;/span&gt;.CurrentDirectory;      &lt;br /&gt;      &lt;br /&gt;&lt;/span&gt;&lt;span style="color: green; font-family: " courier new"; mso-bidi-font-size: 10.0pt; mso-fareast-language: DE; mso-no-proof: yes"&gt;// Add-In-Store erstellen/aktualisieren     &lt;br /&gt;&lt;/span&gt;&lt;span style="color: #2b91af; font-family: " courier new"; mso-bidi-font-size: 10.0pt; mso-fareast-language: DE; mso-no-proof: yes"&gt;AddInStore&lt;/span&gt;&lt;span style="font-family: " courier new"; mso-bidi-font-size: 10.0pt; mso-fareast-language: DE; mso-no-proof: yes"&gt;.Rebuild(addInHost1.AddInPath);     &lt;br /&gt;      &lt;br /&gt;&lt;/span&gt;&lt;span style="color: green; font-family: " courier new"; mso-bidi-font-size: 10.0pt; mso-fareast-language: DE; mso-no-proof: yes"&gt;// Registrierte Add-Ins vom Typ AddInHostView ermitteln     &lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: " courier new"; mso-bidi-font-size: 10.0pt; mso-fareast-language: DE; mso-no-proof: yes"&gt;addInHost1.AvailableAddIns = &lt;span style="color: #2b91af"&gt;AddInStore&lt;/span&gt;.FindAddIns(      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;typeof&lt;/span&gt;(&lt;span style="color: #2b91af"&gt;AddInHostView&lt;/span&gt;), addInHost1.AddInPath);      &lt;br /&gt;      &lt;br /&gt;&lt;/span&gt;&lt;span style="color: green; font-family: &amp;#39;Courier New&amp;#39;; mso-bidi-font-size: 10.0pt; mso-fareast-language: de; mso-no-proof: yes"&gt;// Commands f&amp;#252;r Men&amp;#252;- u. Toolbar-Elemente erstellen     &lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: " courier new"; mso-bidi-font-size: 10.0pt; mso-fareast-language: DE; mso-no-proof: yes"&gt;addInHost1.CreateCommands();&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align: none"&gt;Hier wird zun&amp;#228;chst der Add-In-Store neu erstellt und daraufhin die verf&amp;#252;gbaren Add-Ins &amp;#252;ber &lt;strong&gt;AddInStore.FindAddIns()&lt;/strong&gt; ermittelt. Die zur&amp;#252;ckgegebene Liste von &lt;strong&gt;AddInToken&lt;/strong&gt;-Objekten kann daraufhin an &lt;strong&gt;AddInHost&lt;/strong&gt; &amp;#252;bergeben werden.&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align: none"&gt;Durch den Aufruf von &lt;strong&gt;CreateCommands()&lt;/strong&gt; erstellt &lt;strong&gt;AddInHost&lt;/strong&gt; automatisch entsprechende &lt;strong&gt;ICommand&lt;/strong&gt;- und &lt;strong&gt;IUICommand&lt;/strong&gt;-Objekte f&amp;#252;r die vorhandenen Men&amp;#252;- und Toolbar-Elemente.&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align: none"&gt;F&amp;#252;r die Erstellung eines Commands wird ein eindeutiger Name ben&amp;#246;tigt, &amp;#252;ber den das Add-In sp&amp;#228;ter Referenzieren kann. Hierf&amp;#252;r stellt &lt;strong&gt;AddInHost&lt;/strong&gt; die Extender Property &lt;strong&gt;CommandName&lt;/strong&gt; bereit. Sie wird automatisch jedem &lt;strong&gt;ToolStripItem&lt;/strong&gt;-Element der Form angeh&amp;#228;ngt und erm&amp;#246;glicht so eine leichte Zuordnung.&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align: none"&gt;&lt;a href="http://lh4.google.com/NeumannJN/R6BXipiB8NI/AAAAAAAAAHI/2KQPHMsD_VE/CommandNameExtender%5B2%5D"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="285" alt="CommandNameExtender" src="http://lh3.google.com/NeumannJN/R6BXjZiB8OI/AAAAAAAAAHQ/r1fkqERTTY8/CommandNameExtender_thumb%5B2%5D" width="465" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align: none"&gt;Dar&amp;#252;ber hinaus k&amp;#246;nnen gleichartige Men&amp;#252;- und Toolbar-Elemente unter einem Command zusammengefasst werden. Wenn ein Add-In beispielsweise den Command &amp;quot;Host.File.New&amp;quot; deaktiviert (&lt;strong&gt;Command.Enabled&lt;/strong&gt;-Eigenschaft), wird sowohl das Men&amp;#252;, als auch der zugeh&amp;#246;rige Toolbar-Button automatisch deaktiviert.&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align: none"&gt;Zus&amp;#228;tzlich abonniert &lt;strong&gt;AddInHost &lt;/strong&gt;das &lt;strong&gt;Click&lt;/strong&gt;-Event des jeweiligen Elements und informiert seinerseits &amp;#252;ber das &lt;strong&gt;CommandExecuted&lt;/strong&gt;-Event &amp;#252;ber dessen Aktivierung. Daher ben&amp;#246;tigen Sie lediglich einen Event Handler f&amp;#252;r alle Men&amp;#252;- und Toolbar-Elemente.&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align: none"&gt;Das &amp;#214;ffnen des Add-In-Manager-Dialogs kann beispielsweise &amp;#252;ber einen Men&amp;#252;punkt erfolgen und durch den folgenden Event Handler verarbeitet werden:&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align: none"&gt;&lt;span style="font-size: 10pt; color: blue; font-family: " courier new"; mso-fareast-language: DE; mso-no-proof: yes; mso-fareast-font-family: 'Times New Roman'; mso-ansi-language: DE; mso-bidi-language: AR-SA"&gt;private&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: " courier new"; mso-fareast-language: DE; mso-no-proof: yes; mso-fareast-font-family: 'Times New Roman'; mso-ansi-language: DE; mso-bidi-language: AR-SA"&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; addInHost1_CommandExecuted(      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;object&lt;/span&gt; sender, &lt;span style="color: #2b91af"&gt;CommandExecutedEventArgs&lt;/span&gt; e)      &lt;br /&gt;{      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (e.Command.Name == &lt;span style="color: #a31515"&gt;&amp;quot;Host.Extras.AddInManager&amp;quot;&lt;/span&gt;)      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;{      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: green"&gt;// Add-In-Manager-Dialog anzeigen       &lt;br /&gt;&lt;/span&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;addInHost1.ShowAddInManager(&lt;span style="color: blue"&gt;this&lt;/span&gt;, &lt;span style="color: blue"&gt;false&lt;/span&gt;);&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: " courier new"; mso-fareast-language: DE; mso-no-proof: yes; mso-fareast-font-family: 'Times New Roman'; mso-ansi-language: DE; mso-bidi-language: AR-SA"&gt;     &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;}      &lt;br /&gt;}&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align: none"&gt;Der Dialog k&amp;#252;mmert sich nun automatisch darum, die vom Benutzer ausgew&amp;#228;hlten Add-Ins zu aktivieren und &amp;#252;ber die &lt;strong&gt;InitializeCommands()&lt;/strong&gt;-Methode die entsprechenden Commands anzufordern. &lt;strong&gt;AddInHost&lt;/strong&gt; integriert daraufhin die bereitgestellten Commands in Men&amp;#252; und Toolbar und somit schlie&amp;#223;t sich der Kreis.&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align: none"&gt;F&amp;#252;r den Host wird die Sache somit denkbar einfach. Welche Arbeiten auf Add-In-Seite zu verrichten sind, erkl&amp;#228;re ich im zweiten Teil.&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align: none"&gt;Sourcen inkl. Beispielanwendung gibt's &lt;a href="http://www.esnips.com/doc/57be0ea5-d34f-4fd0-8225-927e373e6333/AddInCommandDemo"&gt;hier&lt;/a&gt;.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-186741300330852638?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/186741300330852638/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=186741300330852638' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/186741300330852638'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/186741300330852638'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2008/01/ein-command-modell-fr-systemaddin-teil.html' title='Ein Command-Modell für System.AddIn, Teil 1'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-2756126441248749504</id><published>2008-01-29T10:09:00.001+01:00</published><updated>2008-01-29T10:09:53.277+01:00</updated><title type='text'>Thinktectured'</title><content type='html'>&lt;p&gt;Now it's &lt;a href="http://blogs.thinktecture.com/cweyer/archive/2008/01/24/415101.aspx"&gt;official&lt;/a&gt;: I'm joining &lt;a href="http://www.thinktecture.com/"&gt;Thinktecture&lt;/a&gt;. I know &lt;a href="http://blogs.thinktecture.com/cweyer/default.aspx"&gt;Christian&lt;/a&gt;, &lt;a href="http://blogs.thinktecture.com/ingo/"&gt;Ingo&lt;/a&gt;, &lt;a href="http://www.leastprivilege.com/"&gt;Dominick&lt;/a&gt; and &lt;a href="http://www.dotnetjunkies.com/WebLog/nenoloje/"&gt;Neno&lt;/a&gt; a lot of years and I'm glad to work with these fantastic guys!&lt;/p&gt;  &lt;p&gt;Watch my &lt;a href="http://www.thinktecture.com/staff/joerg"&gt;profile&lt;/a&gt; for further information.&lt;/p&gt;  &lt;p&gt;Let's Rock!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-2756126441248749504?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/2756126441248749504/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=2756126441248749504' title='1 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/2756126441248749504'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/2756126441248749504'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2008/01/thinktectured.html' title='Thinktectured&amp;#39;'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-6729599615535266669</id><published>2008-01-21T13:50:00.001+01:00</published><updated>2008-01-21T13:50:54.959+01:00</updated><title type='text'>Grafische Verwaltung von Add-Ins</title><content type='html'>&lt;p&gt;Wie ich &lt;a href="http://headwriteline.blogspot.com/2008/01/test.html"&gt;hier&lt;/a&gt; bereits beschrieben habe, bietet System.AddIn keine Unterst&amp;#252;tzung f&amp;#252;r Windows Forms-basierte Add-Ins. Gleiches gilt auch f&amp;#252;r die grafische Verwaltung in einer Anwendung. Einen Add-In-Manager-Dialog, wie man ihn aus Visual Studio oder Office kennt, ist zurzeit nicht verf&amp;#252;gbar.&lt;/p&gt;  &lt;p&gt;Daher habe ich einen generischen Dialog entwickelt, der die Aktivierung und Verwaltung von Add-Ins zur Laufzeit stark vereinfacht. Zus&amp;#228;tzlich stelle ich zwei Dialoge bereit, in denen Aktivierungsoptionen eingestellt werden k&amp;#246;nnen, bzw. die Informationen &amp;#252;ber geladene Add-Ins bieten. Diese sind jedoch in erster Linie f&amp;#252;r den Entwickler und weniger f&amp;#252;r den Anwender gedacht, doch dazu sp&amp;#228;ter mehr.&lt;/p&gt;  &lt;p&gt;Da ja bekanntlich ein Bild mehr als tausend Worte sagt, hier die Bestandteile in grafischer Form:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.google.com/NeumannJN/R5SVGse4kxI/AAAAAAAAAEw/5MDozzpxUqg/AddInManager4"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="321" alt="AddInManager" src="http://lh6.google.com/NeumannJN/R5SVHce4kyI/AAAAAAAAAE4/kZD2hd0nhOc/AddInManager_thumb2" width="467" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p class="MsoNormal" style="margin-left: 36pt; text-indent: -18pt; mso-list: l0 level1 lfo1"&gt;&lt;span style="mso-fareast-font-family: tahoma; mso-bidi-font-family: tahoma"&gt;&lt;span style="mso-list: ignore"&gt;1)&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;&lt;span style="mso-fareast-language: de; mso-no-proof: yes"&gt;AddInManagerForm&lt;/span&gt;&lt;/b&gt;&lt;span style="mso-fareast-language: de; mso-no-proof: yes"&gt; beinhaltet den eigentlichen Verwaltungsdialog. F&amp;#252;r die Darstellung der Add-In-Liste greift er auf das &lt;b style="mso-bidi-font-weight: normal"&gt;AddInManagerControl&lt;/b&gt; zur&amp;#252;ck. In ihr werden die verf&amp;#252;gbaren Add-Ins gelistet.&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-left: 36pt; text-indent: -18pt; mso-list: l0 level1 lfo1"&gt;&lt;span style="mso-fareast-font-family: tahoma; mso-bidi-font-family: tahoma"&gt;&lt;span style="mso-list: ignore"&gt;2)&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;&lt;span style="mso-fareast-language: de; mso-no-proof: yes"&gt;AddInManagerControl&lt;/span&gt;&lt;/b&gt; ist ein User Control f&amp;#252;r die Anzeige der verf&amp;#252;gbaren Add-Ins, bzw. zu dessen Aktivierung.&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-left: 36pt; text-indent: -18pt; mso-list: l0 level1 lfo1"&gt;&lt;span style="mso-fareast-font-family: tahoma; mso-bidi-font-family: tahoma"&gt;&lt;span style="mso-list: ignore"&gt;3)&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;&lt;span style="mso-fareast-language: de; mso-no-proof: yes"&gt;AddInActivationOptionsForm&lt;/span&gt;&lt;/b&gt;&lt;span style="mso-fareast-language: de; mso-no-proof: yes"&gt; bietet Steuerungsoptionen zur Add-In-Aktivierung. Hier kann beispielsweise eingestellt werden, ob das Add-In in einer AppDomain oder einem separaten Prozess gehostet werden soll.&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-left: 36pt; text-indent: -18pt; mso-list: l0 level1 lfo1"&gt;&lt;span style="mso-fareast-font-family: tahoma; mso-bidi-font-family: tahoma"&gt;&lt;span style="mso-list: ignore"&gt;4)&amp;#160; &lt;/span&gt;&lt;/span&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;&lt;span style="mso-fareast-language: de; mso-no-proof: yes"&gt;AddInDetailsForm&lt;/span&gt;&lt;/b&gt;&lt;span style="mso-fareast-language: de; mso-no-proof: yes"&gt; stellt Informationen &amp;#252;ber bereits geladene Add-Ins zu Verf&amp;#252;gung. Er stellt beispielsweise Informationen &amp;#252;ber die zugeh&amp;#246;rige Add-In-Assembly bereit.&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;/p&gt;  &lt;p&gt;Alle Komponenten sind in der &lt;b style="mso-bidi-font-weight: normal"&gt;WindowsFormsAddInProxy.dll&lt;/b&gt; vereint, die ich bereits &lt;a href="http://headwriteline.blogspot.com/2008/01/test.html"&gt;hier&lt;/a&gt; und &lt;a href="http://headwriteline.blogspot.com/2008/01/windows-forms-support-fr-systemaddin.html"&gt;hier&lt;/a&gt; beschrieben habe.&lt;/p&gt;  &lt;h3&gt;Verwendung&lt;/h3&gt;  &lt;p class="MsoNormal"&gt;Durch die Verwendung des Add-In-Manager-Dialogs reduziert sich der Code in der Anwendung deutlich, da dieser nicht nur eine grafische Oberfl&amp;#228;che bereitstellt, sondern ebenfalls die entsprechende Aktivierung und Deaktivierung &amp;#252;bernimmt. Damit dies funktioniert, m&amp;#252;ssen jedoch einige Voraussetzungen erf&amp;#252;llt sein.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Zun&amp;#228;chst m&amp;#252;ssen zwei Listen gef&amp;#252;hrt werden, die alle verf&amp;#252;gbaren, bzw. geladenen Add-Ins enthalten. Diese k&amp;#246;nnen beispielsweise als statische Member in der &lt;b style="mso-bidi-font-weight: normal"&gt;Program&lt;/b&gt;-Klasse hinterlegt werden.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="color: blue; font-family: " 10.0pt?="10.0pt?" mso-bidi-font-size:="mso-bidi-font-size:" yes;="yes;" mso-no-proof:="mso-no-proof:" DE;="DE;" mso-fareast-language:="mso-fareast-language:" new?;="new?;" courier="courier"&gt;static&lt;/span&gt;&lt;span style="font-family: " 10.0pt?="10.0pt?" mso-bidi-font-size:="mso-bidi-font-size:" yes;="yes;" mso-no-proof:="mso-no-proof:" DE;="DE;" mso-fareast-language:="mso-fareast-language:" new?;="new?;" courier="courier"&gt; &lt;span style="color: blue"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Program        &lt;br /&gt;&lt;/span&gt;{       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;public&lt;/span&gt; &lt;span style="color: blue"&gt;static&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Collection&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;AddInToken&lt;/span&gt;&amp;gt; AvailableAddIns;       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;public&lt;/span&gt; &lt;span style="color: blue"&gt;static&lt;/span&gt; &lt;span style="color: #2b91af"&gt;AddInDictionary&lt;/span&gt; LoadedAddIns;       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;public&lt;/span&gt; &lt;span style="color: blue"&gt;static&lt;/span&gt; &lt;span style="color: blue"&gt;string&lt;/span&gt; AddInPath;       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;[&lt;span style="color: #2b91af"&gt;STAThread&lt;/span&gt;]       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;static&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; Main()       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;{       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;LoadedAddIns = &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;AddInDictionary&lt;/span&gt;();       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&lt;/span&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;AddInPath = &lt;span style="color: #2b91af"&gt;Environment&lt;/span&gt;.CurrentDirectory;       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: green"&gt;// Vorhandene Add-Ins ermitteln        &lt;br /&gt;&lt;/span&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;AvailableAddIns =       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;AddInStore&lt;/span&gt;.FindAddIns(&lt;span style="color: blue"&gt;typeof&lt;/span&gt;(&lt;span style="color: #2b91af"&gt;AddInHostView&lt;/span&gt;),       &lt;br /&gt;&lt;span style="color: #2b91af"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;Program&lt;/span&gt;.AddInPath);       &lt;br /&gt;      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Application&lt;/span&gt;.EnableVisualStyles();       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Application&lt;/span&gt;.SetCompatibleTextRenderingDefault(&lt;span style="color: blue"&gt;false&lt;/span&gt;);       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Application&lt;/span&gt;.Run(&lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;MainForm&lt;/span&gt;());       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;}       &lt;br /&gt;} &lt;/span&gt;    &lt;p&gt;&lt;/p&gt; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;/p&gt;  &lt;p&gt;Beim Programmstart werden zun&amp;#228;chst die verf&amp;#252;gbaren Add-Ins in der &lt;b style="mso-bidi-font-weight: normal"&gt;Main()&lt;/b&gt;-Methode ermittelt. F&amp;#252;r die Liste der geladenen Add-Ins kommt eine Instanz der &lt;b style="mso-bidi-font-weight: normal"&gt;AddInDictionary&lt;/b&gt;-Klasse zum Einsatz. Diese leitet von &lt;b style="mso-bidi-font-weight: normal"&gt;Dictionary&amp;lt;AddInToken, IAddInManager&amp;gt;&lt;/b&gt; ab und&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;enth&amp;#228;lt f&amp;#252;r jedes geladene Add-In ein Token und die entsprechende Instanz. &lt;b style="mso-bidi-font-weight: normal"&gt;IAddInManger&lt;/b&gt; ist ein Marker-Interface, das keinerlei Logik enth&amp;#228;lt und ausschlie&amp;#223;lich f&amp;#252;r den generischen Umgang mit den entsprechenden Add-In-View-Instanzen verwendet wird. Dies ist n&amp;#246;tig, da &lt;b style="mso-bidi-font-weight: normal"&gt;AddInManagerForm&lt;/b&gt; keinerlei Informationen &amp;#252;ber die konkreten View-Klassen hat. Diese m&amp;#252;ssen nun lediglich von &lt;b style="mso-bidi-font-weight: normal"&gt;IAddInManger&lt;/b&gt; ableiten und k&amp;#246;nnen daraufhin generisch verwaltet werden. Im Beispielprojekt sieht die wie folgt aus:&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="color: blue; font-family: " 10.0pt?="10.0pt?" mso-bidi-font-size:="mso-bidi-font-size:" yes;="yes;" mso-no-proof:="mso-no-proof:" DE;="DE;" mso-fareast-language:="mso-fareast-language:" new?;="new?;" courier="courier"&gt;public&lt;/span&gt;&lt;span style="font-family: " 10.0pt?="10.0pt?" mso-bidi-font-size:="mso-bidi-font-size:" yes;="yes;" mso-no-proof:="mso-no-proof:" DE;="DE;" mso-fareast-language:="mso-fareast-language:" new?;="new?;" courier="courier"&gt; &lt;span style="color: blue"&gt;abstract&lt;/span&gt; &lt;span style="color: blue"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af"&gt;AddInHostView&lt;/span&gt; : &lt;span style="color: #2b91af"&gt;IAddInManager        &lt;br /&gt;&lt;/span&gt;{       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;public&lt;/span&gt; &lt;span style="color: blue"&gt;abstract&lt;/span&gt; &lt;span style="color: #2b91af"&gt;WindowProxyBase&lt;/span&gt; GetSurface();       &lt;br /&gt;} &lt;/span&gt;    &lt;p&gt;&lt;/p&gt; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;/p&gt;  &lt;p&gt;Nach dieser Vorarbeit kann der Dialog aufgerufen werden:&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="color: #2b91af; font-family: " 10.0pt?="10.0pt?" mso-bidi-font-size:="mso-bidi-font-size:" yes;="yes;" mso-no-proof:="mso-no-proof:" DE;="DE;" mso-fareast-language:="mso-fareast-language:" new?;="new?;" courier="courier"&gt;AddInManagerForm&lt;/span&gt;&lt;span style="font-family: " 10.0pt?="10.0pt?" mso-bidi-font-size:="mso-bidi-font-size:" yes;="yes;" mso-no-proof:="mso-no-proof:" DE;="DE;" mso-fareast-language:="mso-fareast-language:" new?;="new?;" courier="courier"&gt; frm = &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;AddInManagerForm&lt;/span&gt;();       &lt;br /&gt;frm.AddInPath = &lt;span style="color: #2b91af"&gt;Program&lt;/span&gt;.AddInPath;       &lt;br /&gt;frm.AvailableAddIns = &lt;span style="color: #2b91af"&gt;Program&lt;/span&gt;.AvailableAddIns;       &lt;br /&gt;frm.LoadedAddIns = &lt;span style="color: #2b91af"&gt;Program&lt;/span&gt;.LoadedAddIns;       &lt;br /&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (frm.ShowDialog(&lt;span style="color: blue"&gt;this&lt;/span&gt;) == &lt;span style="color: #2b91af"&gt;DialogResult&lt;/span&gt;.OK)       &lt;br /&gt;{       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: green"&gt;// ...        &lt;br /&gt;&lt;/span&gt;} &lt;/span&gt;    &lt;p&gt;&lt;/p&gt; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;/p&gt;  &lt;p&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;AddInMangerForm&lt;/b&gt; muss nun der Pfad des Add-In-Verzeichnisses, sowie die Liste der verf&amp;#252;gbaren und geladenen Add-Ins &amp;#252;bergeben werden, alles Weitere &amp;#252;bernimmt der Dialog.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.google.com/NeumannJN/R5SVH8e4kzI/AAAAAAAAAFA/DcOTEsyC9sI/AddInManagerForm%5B4%5D"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="336" alt="AddInManagerForm" src="http://lh5.google.com/NeumannJN/R5SVIMe4k0I/AAAAAAAAAFI/ROCyedt90Fw/AddInManagerForm_thumb%5B2%5D" width="427" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;/p&gt;  &lt;p&gt;Aktiviert nun der Benutzer ein Add-In, wird dieses automatisch geladen und ist im Anschluss &amp;#252;ber &lt;b style="mso-bidi-font-weight: normal"&gt;Program.LoadedAddIns&lt;/b&gt; verf&amp;#252;gbar. In der Beispielanwendung werden die geladenen Add-Ins in eine Liste aufgenommen, &amp;#252;ber die sie gebunden werden k&amp;#246;nnen.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="color: green; font-family: " 10.0pt?="10.0pt?" mso-bidi-font-size:="mso-bidi-font-size:" yes;="yes;" mso-no-proof:="mso-no-proof:" DE;="DE;" mso-fareast-language:="mso-fareast-language:" new?;="new?;" courier="courier"&gt;...      &lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue; font-family: " 10.0pt?="10.0pt?" mso-bidi-font-size:="mso-bidi-font-size:" yes;="yes;" mso-no-proof:="mso-no-proof:" DE;="DE;" mso-fareast-language:="mso-fareast-language:" new?;="new?;" courier="courier"&gt;if&lt;/span&gt;&lt;span style="font-family: " 10.0pt?="10.0pt?" mso-bidi-font-size:="mso-bidi-font-size:" yes;="yes;" mso-no-proof:="mso-no-proof:" DE;="DE;" mso-fareast-language:="mso-fareast-language:" new?;="new?;" courier="courier"&gt; (frm.ShowDialog(&lt;span style="color: blue"&gt;this&lt;/span&gt;) == &lt;span style="color: #2b91af"&gt;DialogResult&lt;/span&gt;.OK)       &lt;br /&gt;{       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: green"&gt;// Liste der geladenen Add-Ins f&amp;#252;llen        &lt;br /&gt;&lt;/span&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;this&lt;/span&gt;.addInsListView.Items.Clear();       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;foreach&lt;/span&gt; (&lt;span style="color: #2b91af"&gt;AddInToken&lt;/span&gt; token &lt;span style="color: blue"&gt;in&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Program&lt;/span&gt;.LoadedAddIns.Keys)       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;{       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ListViewItem&lt;/span&gt; item =       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;this&lt;/span&gt;.addInsListView.Items.Add(token.Name);       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;item.Tag = token;       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;}       &lt;br /&gt;} &lt;/span&gt;    &lt;p&gt;&lt;/p&gt; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.google.com/NeumannJN/R5SVI8e4k1I/AAAAAAAAAFQ/SRbkzekkvto/AddInList%5B6%5D"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="324" alt="AddInList" src="http://lh6.google.com/NeumannJN/R5SVJce4k2I/AAAAAAAAAFY/79pjkdqSImc/AddInList_thumb%5B4%5D" width="460" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Zum Binden der Oberfl&amp;#228;che wird zun&amp;#228;chst die entsprechende View-Instanz &amp;#252;ber &lt;b style="mso-bidi-font-weight: normal"&gt;Program.LoadedAddIns&lt;/b&gt; ermittelt und auf dieser die &lt;b style="mso-bidi-font-weight: normal"&gt;GetSurface()&lt;/b&gt;-Methode aufgerufen.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="color: blue; font-family: " 10.0pt?="10.0pt?" mso-bidi-font-size:="mso-bidi-font-size:" yes;="yes;" mso-no-proof:="mso-no-proof:" DE;="DE;" mso-fareast-language:="mso-fareast-language:" new?;="new?;" courier="courier"&gt;private&lt;/span&gt;&lt;span style="font-family: " 10.0pt?="10.0pt?" mso-bidi-font-size:="mso-bidi-font-size:" yes;="yes;" mso-no-proof:="mso-no-proof:" DE;="DE;" mso-fareast-language:="mso-fareast-language:" new?;="new?;" courier="courier"&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; bindAddInButton_Click(&lt;span style="color: blue"&gt;object&lt;/span&gt; sender, &lt;span style="color: #2b91af"&gt;EventArgs&lt;/span&gt; e)       &lt;br /&gt;{       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;AddInToken&lt;/span&gt; token =       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;this&lt;/span&gt;.addInsListView.SelectedItems[0].Tag &lt;span style="color: blue"&gt;as&lt;/span&gt; &lt;span style="color: #2b91af"&gt;AddInToken&lt;/span&gt;;       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;AddInHostView&lt;/span&gt; instance =       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #2b91af"&gt;Program&lt;/span&gt;.LoadedAddIns[token] &lt;span style="color: blue"&gt;as&lt;/span&gt; &lt;span style="color: #2b91af"&gt;AddInHostView&lt;/span&gt;;       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (instance != &lt;span style="color: blue"&gt;null&lt;/span&gt;)       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;{       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: green"&gt;// Oberfl&amp;#228;che des selektierten Add-Ins binden        &lt;br /&gt;&lt;/span&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;WindowProxyBase&lt;/span&gt; window = instance.GetSurface();       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (window != &lt;span style="color: blue"&gt;null&lt;/span&gt;)       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;{       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;this&lt;/span&gt;.windowsProxyPanel1.SetWindow(window);       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;this&lt;/span&gt;.windowsProxyPanel1.Select();       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;}       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;}       &lt;br /&gt;} &lt;/span&gt;    &lt;p&gt;&lt;/p&gt; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;/p&gt;  &lt;p&gt; Das Resultat sehen Sie hier:&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.google.com/NeumannJN/R5SVJ8e4k3I/AAAAAAAAAFg/GrEkg9CUrcw/AddInBinding%5B9%5D"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="317" alt="AddInBinding" src="http://lh6.google.com/NeumannJN/R5SVKce4k4I/AAAAAAAAAFo/EFs9lO9_Lmw/AddInBinding_thumb%5B7%5D" width="464" border="0" /&gt;&lt;/a&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;h3&gt;Zus&amp;#228;tzliche Optionen&lt;/h3&gt;  &lt;p class="MsoNormal"&gt;Wie oben bereits erw&amp;#228;hnt, kann die Aktivierung eines Add-Ins durch einen Optionsdialog unterst&amp;#252;tzt werden. Hier k&amp;#246;nnen Hosting-Modell (AppDomain oder Prozess) und der Sicherheitskontext eingestellt werden.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;a href="http://lh4.google.com/NeumannJN/R5SVK8e4k5I/AAAAAAAAAFw/fTpYGzsjbz0/ActivationOptionsForm%5B8%5D"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="351" alt="ActivationOptionsForm" src="http://lh6.google.com/NeumannJN/R5SVLce4k6I/AAAAAAAAAF4/oTkLaFWQ46A/ActivationOptionsForm_thumb%5B6%5D" width="347" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p class="MsoNormal"&gt;Der Dialog ist jedoch in erster Linie f&amp;#252;r den Entwickler und Anwendungsbetreuer gedacht und sollte dem Endbenutzer nicht zu Verf&amp;#252;gung stehen. Daher kann die Anzeige &amp;#252;ber die &lt;b style="mso-bidi-font-weight: normal"&gt;ShowActivationOptions&lt;/b&gt;-Eigenschaft der &lt;b style="mso-bidi-font-weight: normal"&gt;AddInManagerForm&lt;/b&gt;-Klasse gesteuert werden.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Wurde die Option deaktiviert, so k&amp;#246;nnen Sie &amp;#252;ber die Eigenschaften &lt;b style="mso-bidi-font-weight: normal"&gt;AddInActivationType&lt;/b&gt; und &lt;b style="mso-bidi-font-weight: normal"&gt;AddInSecurityLevel&lt;/b&gt; der Aktivierungstyp, bzw. der Sicherheitskontext festgelegt werden.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;/p&gt;  &lt;p&gt;Die Sourcen, inkl. Beispielprojekt finden Sie &lt;a href="http://www.esnips.com/doc/e768fd51-18c7-40ca-b72a-117b4447278a/AddInManagerDemo"&gt;hier&lt;/a&gt;. F&amp;#252;r Feedback bin ich wie immer dankbar.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-6729599615535266669?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/6729599615535266669/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=6729599615535266669' title='1 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/6729599615535266669'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/6729599615535266669'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2008/01/grafische-verwaltung-von-add-ins.html' title='Grafische Verwaltung von Add-Ins'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-7385212091254237252</id><published>2008-01-14T10:15:00.001+01:00</published><updated>2008-01-14T10:15:12.987+01:00</updated><title type='text'>Update von WindowsFormsAddInProxy</title><content type='html'>&lt;p&gt;Jesse Kaplan, einer der Architekten von System.AddIn, hat mich darauf aufmerksam gemacht, dass &lt;strong&gt;IWindowProxy&lt;/strong&gt; in meiner Implementierung nicht unbedingt notwendig ist, da in &lt;strong&gt;System.AddIn.Contract&lt;/strong&gt; bereits ein entsprechendes Interface existiert. Daher habe ich &lt;strong&gt;IWindowProxy&lt;/strong&gt; kurzerhand &amp;#252;ber Bord geworfen und verwende nun statt dessen &lt;strong&gt;INativeHandleContract&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;Anstelle einer &lt;strong&gt;Handle&lt;/strong&gt;-Eigenschaft, definiert es die &lt;strong&gt;GetHandle()&lt;/strong&gt;-Methode. Das Prinzip bleibt jedoch das Gleiche: Die &amp;#220;bertragung eines Window Handles &amp;#252;ber die AppDomain-Grenze.&lt;/p&gt;  &lt;p&gt;Die aktualisierten Sourcen, inkl. Demo finden Sie &lt;a href="http://www.esnips.com/doc/df637ef7-854a-49eb-ae30-5bccb91292da/SystemAddInWinFormsDemo"&gt;hier&lt;/a&gt;. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-7385212091254237252?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/7385212091254237252/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=7385212091254237252' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/7385212091254237252'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/7385212091254237252'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2008/01/update-von-windowsformsaddinproxy.html' title='Update von WindowsFormsAddInProxy'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-1191367651213474769</id><published>2008-01-07T15:44:00.001+01:00</published><updated>2008-01-07T15:44:17.095+01:00</updated><title type='text'>Windows Forms Support für System.AddIn, Teil 2</title><content type='html'>&lt;p&gt; Nachdem ich im &lt;a href="http://headwriteline.blogspot.com/2008/01/test.html"&gt;ersten Teil&lt;/a&gt; den grundlegenden Aufbau der &lt;b&gt;WindowsFormsAddInProxy.dll&lt;/b&gt; beschrieben habe, soll es nun um die Details der Implementierung gehen. Zum besseren Verst&amp;#228;ndnis der beteiligten Komponenten, hier zun&amp;#228;chst einmal der Aufbau der Assembly:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.google.com/NeumannJN/R4I6t8e4ktI/AAAAAAAAAEQ/a3JG1yUDdVQ/WindowsFormsAddInProxy%5B4%5D"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="279" alt="WindowsFormsAddInProxy" src="http://lh4.google.com/NeumannJN/R4I6uce4kuI/AAAAAAAAAEY/GKD6iLEVfiA/WindowsFormsAddInProxy_thumb%5B2%5D" width="460" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Wie ich im ersten Teil bereits erw&amp;#228;hnte, ist das Hauptproblem bei der &amp;#220;bertragung von UI-Elementen &amp;#252;ber AppDomain-Grenzen, dass Windows Forms-Klassen weder serialisierbar sind, noch per Reference &amp;#252;bertragen werden k&amp;#246;nnen. Daher wird lediglich das Handle der Add-In-Oberfl&amp;#228;che &amp;#252;bertragen und auf Host-Seite &amp;#8222;umgeh&amp;#228;ngt&amp;#8220;. Hierf&amp;#252;r stellt die Win32-API die &lt;b style="mso-bidi-font-weight: normal"&gt;SetParent()&lt;/b&gt;-Methode zu Verf&amp;#252;gung. Sie nimmt das jeweilige Handle, sowie das Handle des gew&amp;#252;nschten Elternfensters entgegen. Die Add-In-Oberfl&amp;#228;che wird somit zum Kindelement des entsprechenden Host-Controls.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Aus Sicherheitsgr&amp;#252;nden ist das Umh&amp;#228;ngen von Handles jedoch nur innerhalb eines Win32-Prozesses m&amp;#246;glich. Somit kann diese Technik nicht eingesetzt werden, wenn die Add-Ins in einem separaten Prozess gehosted werden. F&amp;#252;r Client-seitige Add-Ins ist die AppDomain-Isolation jedoch vollkommen ausreichend.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;F&amp;#252;r das &amp;#220;bertragen des Handle ist das &lt;b style="mso-bidi-font-weight: normal"&gt;IWindowProxy&lt;/b&gt;-Interface zust&amp;#228;ndig, welches einzig die &lt;b style="mso-bidi-font-weight: normal"&gt;Handle&lt;/b&gt;-Eigenschaft definiert. &lt;b style="mso-bidi-font-weight: normal"&gt;IWindowProxy&lt;/b&gt; kann nun im jeweiligen Add-In-Contract verwendet werden, um Oberfl&amp;#228;chen-Inhalte &amp;#252;ber die AppDomain-Grenze zu transferieren. Im Beispielprojekt wird &lt;b style="mso-bidi-font-weight: normal"&gt;IWindowProxy&lt;/b&gt; in der &lt;b style="mso-bidi-font-weight: normal"&gt;GetSurface()&lt;/b&gt;-Methode eingesetzt, mit der der Host die Oberfl&amp;#228;che des Add-In ermittelt.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Die eigentliche Kommunikation findet jedoch &amp;#252;ber die Klassen &lt;b style="mso-bidi-font-weight: normal"&gt;AddInSurface&lt;/b&gt; (Add-In-Seite) und &lt;b style="mso-bidi-font-weight: normal"&gt;WindowProxyPanel&lt;/b&gt; (Host-Seite) statt. Letztere bekommt &amp;#252;ber die &lt;b style="mso-bidi-font-weight: normal"&gt;SetWindow()&lt;/b&gt;-Methode eine &lt;b style="mso-bidi-font-weight: normal"&gt;WindowProxyBase&lt;/b&gt;-Instanz &amp;#252;bergeben und &amp;#8222;kapert&amp;#8220; daraufhin das zugeh&amp;#246;rige Fenster.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="color: blue; font-family: " courier new"; mso-bidi-font-size: 10.0pt; mso-fareast-language: DE; mso-no-proof: yes"&gt;public&lt;/span&gt;&lt;span style="font-family: " courier new"; mso-bidi-font-size: 10.0pt; mso-fareast-language: DE; mso-no-proof: yes"&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; SetWindow(&lt;span style="color: #2b91af"&gt;WindowProxyBase&lt;/span&gt; window)      &lt;br /&gt;{      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (window != &lt;span style="color: blue"&gt;null&lt;/span&gt; &amp;amp;&amp;amp; window.Handle != &lt;span style="color: #2b91af"&gt;IntPtr&lt;/span&gt;.Zero)      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;{      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;SetParent(window.Handle, &lt;span style="color: blue"&gt;this&lt;/span&gt;.Handle);      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;}      &lt;br /&gt;}&lt;/span&gt;&lt;/p&gt;  &lt;h4&gt;Weitere Herausforderungen&lt;/h4&gt;  &lt;p&gt;Somit ist das Hauptproblem schon mal gel&amp;#246;st. Doch nach einem kurzen Test treten weitere Herausforderungen auf. Da das Umh&amp;#228;ngen des Handles per Win32-Funktion erfolgte, hat die Windows Forms-Infrastruktur keine Information &amp;#252;ber die Existenz des Controls. Daher werden viele Nachrichten nicht ordnungsgem&amp;#228;&amp;#223; an dieses weiter geleitet. Dies f&amp;#252;hrt zu Problemen in den folgenden Bereichen:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Automatisches Resizing &lt;/li&gt;    &lt;li&gt;Vererbung von Font-Einstellungen &lt;/li&gt;    &lt;li&gt;Fokussteuerung &lt;/li&gt;    &lt;li&gt;Verarbeitung von Accelerator Keys &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Zur L&amp;#246;sung dieser Probleme m&amp;#252;ssen die Nachrichten manuell von &lt;b&gt;WindowProxyPanel&lt;/b&gt; an &lt;b&gt;AddInSurface&lt;/b&gt; weitergeleitet werden. Die folgende Abbildung zeigt die Kommunikation zwischen den beiden Controls:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.google.com/NeumannJN/R4I6vce4kvI/AAAAAAAAAEg/ymk8tVSbocQ/HandleCapturing%5B5%5D"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="230" alt="HandleCapturing" src="http://lh6.google.com/NeumannJN/R4I6v8e4kwI/AAAAAAAAAEo/luqM62gWUok/HandleCapturing_thumb%5B3%5D" width="474" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;h4&gt;1. Automatisches Resizing&lt;/h4&gt;  &lt;p class="MsoNormal"&gt;Das Resizing-Problem ist relativ einfach gel&amp;#246;st. Hierf&amp;#252;r muss in &lt;b style="mso-bidi-font-weight: normal"&gt;WindowProxyPanel&lt;/b&gt; lediglich die &lt;b style="mso-bidi-font-weight: normal"&gt;OnResize()&lt;/b&gt;-Methode &amp;#252;berschrieben und in ihr die aktuelle Gr&amp;#246;&amp;#223;e &amp;#252;ber die Win32-Funktion &lt;b style="mso-bidi-font-weight: normal"&gt;MoveWindow()&lt;/b&gt; aktualisiert werden.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="color: blue; font-family: " courier new"; mso-bidi-font-size: 10.0pt; mso-fareast-language: DE; mso-no-proof: yes"&gt;protected&lt;/span&gt;&lt;span style="font-family: " courier new"; mso-bidi-font-size: 10.0pt; mso-fareast-language: DE; mso-no-proof: yes"&gt; &lt;span style="color: blue"&gt;override&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; OnResize(&lt;span style="color: #2b91af"&gt;EventArgs&lt;/span&gt; e)      &lt;br /&gt;{      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;base&lt;/span&gt;.OnResize(e);      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (m_window != &lt;span style="color: blue"&gt;null&lt;/span&gt; &amp;amp;&amp;amp;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; m_window.Handle != &lt;span style="color: #2b91af"&gt;IntPtr&lt;/span&gt;.Zero)      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;{      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;MoveWindow(m_window.Handle, 0, 0,      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;this&lt;/span&gt;.Width, &lt;span style="color: blue"&gt;this&lt;/span&gt;.Height, &lt;span style="color: blue"&gt;true&lt;/span&gt;);      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;}      &lt;br /&gt;}      &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;h4&gt;2. Vererbung von Font-Einstellungen&lt;/h4&gt;  &lt;p class="MsoNormal"&gt;In Windows Forms werden Font- Einstellungen automatisch an die entsprechenden Kindelemente vererbt, wenn diese nicht explizit einen Font festlegen. Diese Vererbungslogik muss ebenfalls manuell nachgebaut werden, da die Windows Forms-Infrastruktur ja nichts von unserem Kindfenster weis. &lt;/p&gt;  &lt;p class="MsoNormal"&gt;Dies ist jedoch mit einem einfachen &lt;b style="mso-bidi-font-weight: normal"&gt;SendMessage()&lt;/b&gt;-Aufruf erledigt:&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-family: " courier new"; mso-bidi-font-size: 10.0pt; mso-fareast-language: DE; mso-no-proof: yes"&gt;SendMessage(m_window.Handle, WM_SETFONT, &lt;span style="color: blue"&gt;this&lt;/span&gt;.Font.ToHfont().ToInt32(), 0);      &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Der Aufruf findet sowohl in der &lt;b style="mso-bidi-font-weight: normal"&gt;SetWindow()&lt;/b&gt;-Methode, als auch in der &amp;#252;berschriebenen &lt;b style="mso-bidi-font-weight: normal"&gt;OnFontChanged()&lt;/b&gt;-Methode statt, um auch Font-&amp;#196;nderungen zur Laufzeit entsprechend durchzureichen. In der &amp;#252;berschriebenen &lt;b style="mso-bidi-font-weight: normal"&gt;WndProc()&lt;/b&gt;-Methode von &lt;b style="mso-bidi-font-weight: normal"&gt;AddInSurface&lt;/b&gt; wird die &lt;b style="mso-bidi-font-weight: normal"&gt;WM_SETFONT&lt;/b&gt;-Message daraufhin abgefangen und der Font entsprechend gesetzt. &lt;/p&gt;  &lt;h4&gt;3. Fokussteuerung&lt;/h4&gt;  &lt;p class="MsoNormal"&gt;Eine richtig dicke Nuss hatte ich mit der Fokussteuerung zu knacken. Zwar kann in der entsprechenden &lt;b style="mso-bidi-font-weight: normal"&gt;AddInSurface&lt;/b&gt;-Ableitung die &lt;b style="mso-bidi-font-weight: normal"&gt;TabIndex&lt;/b&gt;-Eigenschaft der enthaltenen Controls gesetzt werden, die Kontrolle hat hierbei jedoch das hostende Fenster. Und da dieses das Control nicht kennt (da es nicht in seiner Controls-Hierarchie auftaucht) werden die entsprechenden Elemente auch nicht bei Fokus&amp;#228;nderungen ber&amp;#252;cksichtigt.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Zur L&amp;#246;sung ist die &lt;b style="mso-bidi-font-weight: normal"&gt;WndProc()&lt;/b&gt;-Methode sowohl in &lt;b style="mso-bidi-font-weight: normal"&gt;WindowProxyPanel&lt;/b&gt; als auch in &lt;b style="mso-bidi-font-weight: normal"&gt;AddInSurface&lt;/b&gt; &amp;#252;berschrieben. &amp;#220;ber sie kann direkt in die Win32 Message Loop des Fensters eingegriffen werden. Zum Verarbeitung der Tab-Taste wird die Message &lt;b style="mso-bidi-font-weight: normal"&gt;WM_GETDLGCODE&lt;/b&gt; in &lt;b style="mso-bidi-font-weight: normal"&gt;WindowProxyPanel&lt;/b&gt; abgefangen und manuell an &lt;b style="mso-bidi-font-weight: normal"&gt;AddInSurface&lt;/b&gt; weitergeleitet. &lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="color: blue; font-family: " courier new"; mso-bidi-font-size: 10.0pt; mso-fareast-language: DE; mso-no-proof: yes"&gt;protected&lt;/span&gt;&lt;span style="font-family: " courier new"; mso-bidi-font-size: 10.0pt; mso-fareast-language: DE; mso-no-proof: yes"&gt; &lt;span style="color: blue"&gt;override&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; WndProc(&lt;span style="color: blue"&gt;ref&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Message&lt;/span&gt; m)      &lt;br /&gt;{      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;const&lt;/span&gt; &lt;span style="color: blue"&gt;int&lt;/span&gt; WM_GETDLGCODE = 0x87;      &lt;br /&gt;      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (m_window != &lt;span style="color: blue"&gt;null&lt;/span&gt; &amp;amp;&amp;amp;      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;m_window.Handle != &lt;span style="color: #2b91af"&gt;IntPtr&lt;/span&gt;.Zero)      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;{      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (m.Msg == WM_GETDLGCODE)      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;{      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;SendMessage(      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; m_window.Handle, WM_GETDLGCODE,      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; m.WParam.ToInt32(),m.LParam.ToInt32());      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;return&lt;/span&gt;;      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;}      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;}      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;base&lt;/span&gt;.WndProc(&lt;span style="color: blue"&gt;ref&lt;/span&gt; m);      &lt;br /&gt;}      &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Auf Add-In-Seite wird diese Message wiederum in &lt;b style="mso-bidi-font-weight: normal"&gt;AddInSurface&lt;/b&gt; gefangen und an eine Methode zur Fokussteuerung &amp;#252;bergeben:&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="color: blue; font-family: " courier new"; mso-bidi-font-size: 10.0pt; mso-fareast-language: DE; mso-no-proof: yes"&gt;protected&lt;/span&gt;&lt;span style="font-family: " courier new"; mso-bidi-font-size: 10.0pt; mso-fareast-language: DE; mso-no-proof: yes"&gt; &lt;span style="color: blue"&gt;override&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; WndProc(&lt;span style="color: blue"&gt;ref&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Message&lt;/span&gt; m)      &lt;br /&gt;{      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;const&lt;/span&gt; &lt;span style="color: blue"&gt;int&lt;/span&gt; WM_GETDLGCODE = 0x87;      &lt;br /&gt;&lt;span style="color: blue"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;const&lt;/span&gt; &lt;span style="color: blue"&gt;int&lt;/span&gt; VK_TAB = 0x09;      &lt;br /&gt;      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (m.Msg == WM_GETDLGCODE)      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;{      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (GetAsyncKeyState(VK_TAB) != 0)      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;{      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;this&lt;/span&gt;.TabInto(      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #2b91af"&gt;Control&lt;/span&gt;.ModifierKeys != &lt;span style="color: #2b91af"&gt;Keys&lt;/span&gt;.Shift);      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;}      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;}      &lt;br /&gt;      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;base&lt;/span&gt;.WndProc(&lt;span style="color: blue"&gt;ref&lt;/span&gt; m);      &lt;br /&gt;}      &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&amp;#220;ber die Win32-Funktion &lt;b style="mso-bidi-font-weight: normal"&gt;GetAsyncKeyState()&lt;/b&gt; wird hierbei gepr&amp;#252;ft, ob die Tab-Taste gedr&amp;#252;ckt wurde. Ist dies der Fall, wird die selbst implementierte &lt;b style="mso-bidi-font-weight: normal"&gt;TabInto()&lt;/b&gt;-Methode aufgerufen, welche f&amp;#252;r die eigentliche Fokussteuerung zust&amp;#228;ndig ist. Hierbei wird &amp;#252;ber &lt;b style="mso-bidi-font-weight: normal"&gt;Control.MofifierKeys&lt;/b&gt; abgefragt, ob zus&amp;#228;tzlich die Shift-Taste gedr&amp;#252;ckt wurde, um eine entsprechende R&amp;#252;ckw&amp;#228;rtsbewegung des Fokus zu veranlassen.&lt;/p&gt;  &lt;h4&gt;4. Verarbeitung von Accelerator Key&lt;/h4&gt;  &lt;p class="MsoNormal"&gt;Accelerator Keys werden ja bekanntlich aktiviert, indem die Alt-Taste zusammen mit einem bestimmten Zeichen gedr&amp;#252;ckt wird. Sie werden beispielsweise in Labels deklariert um dem Benutzer ein schnelles Springen in das zugeh&amp;#246;rige Control zu erm&amp;#246;glichen. Auch diese Steuerung ist auf Ebene der &lt;b style="mso-bidi-font-weight: normal"&gt;Form&lt;/b&gt;-Klasse implementiert, sodass hier ebenfalls eine manuelle Implementierung n&amp;#246;tig ist. Diese ist in &lt;b style="mso-bidi-font-weight: normal"&gt;AddInSurface&lt;/b&gt; zu finden und ist der Fokussteuerung sehr &amp;#228;hnlich. Doch bevor auf das Dr&amp;#252;cken von Accelerator Keys reagiert werden kann, m&amp;#252;ssen diese erst einmal ermittelt werden. Hierf&amp;#252;r wurde die &lt;b style="mso-bidi-font-weight: normal"&gt;OnHandleCreated()&lt;/b&gt;-Methode &amp;#252;berschrieben, die bei der initialen Erstellung des Control aufgerufen wird. &lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="color: blue; font-family: " courier new"; mso-bidi-font-size: 10.0pt; mso-fareast-language: DE; mso-no-proof: yes"&gt;protected&lt;/span&gt;&lt;span style="font-family: " courier new"; mso-bidi-font-size: 10.0pt; mso-fareast-language: DE; mso-no-proof: yes"&gt; &lt;span style="color: blue"&gt;override&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; OnHandleCreated(&lt;span style="color: #2b91af"&gt;EventArgs&lt;/span&gt; e)      &lt;br /&gt;{      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;base&lt;/span&gt;.OnHandleCreated(e);      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;this&lt;/span&gt;.InitializeAcceleratorKeys(&lt;span style="color: blue"&gt;this&lt;/span&gt;);      &lt;br /&gt;}      &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Hier wird die &lt;b style="mso-bidi-font-weight: normal"&gt;InitializeAcceleratorKeys()-&lt;/b&gt;Methode aufgerufen, in der die enthaltenen Controls Collections rekursiv durchlaufen und nach Accelerator Keys durchsucht werden. Die gefundenen Keys werden daraufhin in einem Dictionary gespeichert, welches sp&amp;#228;ter ausgewertet werden kann.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;Das Abfangen von gedr&amp;#252;ckten Accelerator Keys erfolgt wie gesagt sehr &amp;#228;hnlich wie bei der Focus-Steuerung. &lt;b style="mso-bidi-font-weight: normal"&gt;WindowProxyPanel&lt;/b&gt; sendet die &lt;b style="mso-bidi-font-weight: normal"&gt;WM_GETDLGCODE&lt;/b&gt;-Message, welche von &lt;b style="mso-bidi-font-weight: normal"&gt;AddInSurface&lt;/b&gt; abgefangen und verarbeitet wird. Der entsprechende Code sieht hierbei wie folgt aus:&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="color: blue; font-family: " courier new"; mso-bidi-font-size: 10.0pt; mso-fareast-language: DE; mso-no-proof: yes"&gt;protected&lt;/span&gt;&lt;span style="font-family: " courier new"; mso-bidi-font-size: 10.0pt; mso-fareast-language: DE; mso-no-proof: yes"&gt; &lt;span style="color: blue"&gt;override&lt;/span&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; WndProc(&lt;span style="color: blue"&gt;ref&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Message&lt;/span&gt; m)      &lt;br /&gt;{      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;const&lt;/span&gt; &lt;span style="color: blue"&gt;int&lt;/span&gt; WM_GETDLGCODE = 0x87;      &lt;br /&gt;      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (m.Msg == WM_GETDLGCODE)      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;{      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (&lt;span style="color: #2b91af"&gt;Control&lt;/span&gt;.ModifierKeys == &lt;span style="color: #2b91af"&gt;Keys&lt;/span&gt;.Alt)      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;{      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;this&lt;/span&gt;.ProcessAcceleratorKeys();      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;}      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;}      &lt;br /&gt;      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;base&lt;/span&gt;.WndProc(&lt;span style="color: blue"&gt;ref&lt;/span&gt; m);      &lt;br /&gt;}      &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;In der &lt;b style="mso-bidi-font-weight: normal"&gt;ProcessAcceleratorKeys()&lt;/b&gt;-Methode wird daraufhin das Dictionary der Accelerator Keys durchlaufen und der Fokus entsprechend gesetzt.&lt;/p&gt;  &lt;p&gt;Den Source Code von &lt;b&gt;WindowsFormsAddInProxy&lt;/b&gt; k&amp;#246;nnen Sie inkl. Demoprojekt &lt;a href="http://www.esnips.com/doc/69208092-bb7e-45b9-9539-0d56e1a98948/SystemAddInWinFormsDemo"&gt;hier&lt;/a&gt; herunter laden. F&amp;#252;r Feedback bin ich stets dankbar.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;PS:&lt;/strong&gt; Wenn Sie mehr &amp;#252;ber System.AddIn erfahren m&amp;#246;chten, schauen Sie auf der diesj&amp;#228;hrigen &lt;a href="http://www.basta.net"&gt;BASTA! Spring Edition&lt;/a&gt; vorbei. Dort f&amp;#252;hren &lt;a href="http://www.leastprivilege.com/"&gt;Dominick Baier&lt;/a&gt; und ich in der Session &lt;a href="http://basta.net/tracks.asp?tid=668&amp;amp;language=de#session-5"&gt;&amp;#8222;.NET-Anwendungen sicher und robust durch Add-ins erweitern&lt;/a&gt;&amp;#8220; in das Thema ein.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-1191367651213474769?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/1191367651213474769/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=1191367651213474769' title='2 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/1191367651213474769'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/1191367651213474769'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2008/01/windows-forms-support-fr-systemaddin.html' title='Windows Forms Support für System.AddIn, Teil 2'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-1670068809411569284</id><published>2008-01-07T09:29:00.001+01:00</published><updated>2008-01-07T15:29:03.005+01:00</updated><title type='text'>Windows Forms Support für System.AddIn, Teil 1</title><content type='html'>&lt;p&gt;.NET 3.5 f&amp;#252;hrt mit &lt;b&gt;System.AddIn&lt;/b&gt; ist ein neues System zur Erstellung von erweiterbaren Anwendungen ein. &lt;a href="http://blogs.msdn.com/dparys/default.aspx"&gt;Dariusz&lt;/a&gt; hat die grundlegenden Details bereits &lt;a href="http://blogs.msdn.com/dparys/archive/2007/10/17/net-3-5-feature-system-addin.aspx"&gt;hier&lt;/a&gt; und &lt;a href="http://blogs.msdn.com/dparys/archive/2007/12/06/system-addin-eventing-zwischen-host-und-addin.aspx"&gt;hier&lt;/a&gt; beschrieben. Das System hat im Moment jedoch einen Haken: Wenn ein Add-In eine grafischen Oberfl&amp;#228;che anbietet m&amp;#246;chte, muss dieses &amp;#8211; ebenso wie die hostende Anwendung &amp;#8211; auf WPF basieren. Eine Unterst&amp;#252;tzung f&amp;#252;r Windows Forms existiert zurzeit nicht, was verwunderlich ist, da Windows Forms momentan eine deutlich gr&amp;#246;&amp;#223;ere Verbreitung hat.&lt;/p&gt;  &lt;p&gt;Da ich das System aber gerne jetzt und nicht erst in der n&amp;#228;chsten WPF-Anwendung nutzen wollte, habe ich mir ein Herz gefasst und die n&amp;#246;tige Windows Forms-Funktionalit&amp;#228;t selbst implementiert. Doch bevor ich zu den technischen Details komme, zun&amp;#228;chst einige Grundlagen zum besseren Verst&amp;#228;ndnis.&lt;/p&gt;  &lt;h4&gt;System.AddIn-Architektur&lt;/h4&gt;  &lt;p&gt;Bei System.AddIn kommunizieren Host und Add-Ins durch eine sogenannte Pipeline, die aus Contracts, Views und Adaptern besteht, wie die folgende Abbildung zeigt.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.google.com/NeumannJN/R4IDk8e4kjI/AAAAAAAAADA/7wtIKxJQd60/SystemAddInPipeline%5B23%5D"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="120" alt="SystemAddInPipeline" src="http://lh3.google.com/NeumannJN/R4IDlMe4kkI/AAAAAAAAADI/srIXAJmKFis/SystemAddInPipeline_thumb%5B13%5D" width="458" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;In der Mitte der Pipeline stehen die Contracts, &amp;#252;ber die Host und Add-Ins miteinander kommunizieren. Dar&amp;#252;ber hinaus verf&amp;#252;gen beide Seiten jeweils &amp;#252;ber Views und Adapter. Diese dienen der Isolation und erm&amp;#246;glichen eine sichere und Versions-unabh&amp;#228;ngige Kommunikation. &lt;/p&gt;  &lt;p&gt;Die Add-Ins werden in einer separaten AppDomain oder einem separaten Prozess ausgef&amp;#252;hrt. Die Kommunikation findet hierbei &amp;#252;ber den IPC-Channel von .NET-Remoting statt. &lt;/p&gt;  &lt;p&gt;Das Hauptproblem bei der &amp;#220;bertragung von UI-Elementen besteht nun darin, dass die Klassen im &lt;b&gt;System.Windows.Forms&lt;/b&gt;-Namespace nicht serialisierbar sind und somit nicht direkt &amp;#252;bertragen werden k&amp;#246;nnen. Die leiten zwar von &lt;b&gt;MarshalByRefObject&lt;/b&gt; ab, k&amp;#246;nnen aber auch nicht per Referenz &amp;#252;bertragen werden. Doch wie sonst soll die Kommunikation erfolgen?&lt;/p&gt;  &lt;h4&gt;Der Windows Forms Support&lt;/h4&gt;  &lt;p&gt;Der Trick besteht darin, die Windows Forms-Elemente nicht in serialisierter Form &amp;#252;ber die Leitung zu schicken, sondern lediglich das Handle der Container-Instanz (z.B. eines User Controls). Dieses kann daraufhin vom Host &amp;#8222;umgeh&amp;#228;ngt&amp;#8220; werden. Der Contract f&amp;#252;r die Kommunikation k&amp;#246;nnte somit wie folgt aussehen:&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align: none"&gt;&lt;span style="color: blue; font-family: " courier new"; mso-bidi-font-size: 10.0pt; mso-fareast-language: DE; mso-no-proof: yes"&gt;public&lt;/span&gt;&lt;span style="font-family: " courier new"; mso-bidi-font-size: 10.0pt; mso-fareast-language: DE; mso-no-proof: yes"&gt; &lt;span style="color: blue"&gt;interface&lt;/span&gt; &lt;span style="color: #2b91af"&gt;IWindowProxy       &lt;br /&gt;&lt;/span&gt;{      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IntPtr&lt;/span&gt; Handle { &lt;span style="color: blue"&gt;get&lt;/span&gt;; &lt;span style="color: blue"&gt;set&lt;/span&gt;; }      &lt;br /&gt;}      &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p&gt;Analog zur Pipeline-Architektur wird zus&amp;#228;tzlich eine abstrakte Basisklasse f&amp;#252;r die View-Ebene, sowie eine entsprechende Ableitung zur Verwendung in Add-In und Host ben&amp;#246;tigt. Hierzu dienen die Klassen &lt;b&gt;WindowProxyBase&lt;/b&gt; und &lt;b&gt;WindowProxy&lt;/b&gt;, welche dieselbe Signatur wie &lt;b&gt;IWindowProxy&lt;/b&gt; aufweisen. &lt;/p&gt;  &lt;p&gt;Zus&amp;#228;tzlich werden Adapter-Klassen f&amp;#252;r die Add-In- und die Host-Seite ben&amp;#246;tigt. Hierf&amp;#252;r werden die Klassen &lt;b&gt;WindowProxyViewToContractAddInAdapter&lt;/b&gt; und &lt;b&gt;WindowProxyViewToContractHostAdapter&lt;/b&gt; bereit gestellt.&lt;/p&gt;  &lt;p&gt;Da das alles auf den ersten Blick etwas verwirrend wirken kann, soll das folgende Schaubild f&amp;#252;r die n&amp;#246;tige Transparenz sorgen. Es zeigt den Aufbau der &lt;b&gt;WindowFormsAddInProxy.dll&lt;/b&gt;, die alle n&amp;#246;tigen Klassen enth&amp;#228;lt und von den jeweiligen Pipeline-Assemblies referenziert wird:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.google.com/NeumannJN/R4IDmMe4klI/AAAAAAAAADQ/V9uNMBN3I1A/WindowsFormsAddInProxy%5B15%5D"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="290" alt="WindowsFormsAddInProxy" src="http://lh5.google.com/NeumannJN/R4IDmse4kmI/AAAAAAAAADY/Yl_NkrTJPiQ/WindowsFormsAddInProxy_thumb%5B7%5D" width="467" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;h4&gt;Das Demo-Projekt&lt;/h4&gt;  &lt;p&gt;Hat man den Aufbau erst einmal verstanden, ist die Verwendung in einem Add-In-Projekt relativ einfach. Zur Veranschaulichung habe ich ein kleines Demoprojekt erstellt, in dem ein sehr einfacher Contract verwendet wird:&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align: none"&gt;&lt;span style="font-family: " courier new"; mso-bidi-font-size: 10.0pt; mso-fareast-language: DE; mso-no-proof: yes"&gt;[&lt;span style="color: #2b91af"&gt;AddInContract&lt;/span&gt;]      &lt;br /&gt;&lt;span style="color: blue"&gt;public&lt;/span&gt; &lt;span style="color: blue"&gt;interface&lt;/span&gt; &lt;span style="color: #2b91af"&gt;IAddInContract&lt;/span&gt; : &lt;span style="color: #2b91af"&gt;IContract       &lt;br /&gt;&lt;/span&gt;{      &lt;br /&gt;&lt;span style="color: #2b91af"&gt;&lt;span style="mso-tab-count: 1"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;IWindowProxy&lt;/span&gt; GetSurface();      &lt;br /&gt;}      &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p&gt;Die &lt;b&gt;GetSurface()&lt;/b&gt;-Methode wird vom Host aufgerufen, um die Oberfl&amp;#228;che des jeweiligen Add-In zu ermitteln. Sie liefert eine &lt;b&gt;IWindowProxy&lt;/b&gt;-Instanz zur&amp;#252;ck, sprich das Handle eines User Controls.&lt;/p&gt;  &lt;p&gt;Analog dazu werden zwei View-Klassen f&amp;#252;r die Add-In- und die Host-Seite definiert. F&amp;#252;r die Add-In-Seite ist dies die Klasse &lt;b&gt;AddInView&lt;/b&gt;:&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align: none"&gt;&lt;span style="font-family: " courier new"; mso-bidi-font-size: 10.0pt; mso-fareast-language: DE; mso-no-proof: yes"&gt;[&lt;span style="color: #2b91af"&gt;AddInBase&lt;/span&gt;]      &lt;br /&gt;&lt;span style="color: blue"&gt;public&lt;/span&gt; &lt;span style="color: blue"&gt;abstract&lt;/span&gt; &lt;span style="color: blue"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af"&gt;AddInView       &lt;br /&gt;&lt;/span&gt;{      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;public&lt;/span&gt; &lt;span style="color: blue"&gt;abstract&lt;/span&gt; &lt;span style="color: #2b91af"&gt;WindowProxyBase&lt;/span&gt; GetSurface();      &lt;br /&gt;}      &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p&gt;Diese definiert ebenfalls die &lt;b&gt;GetSurface()&lt;/b&gt;-Methode, gibt jedoch eine &lt;b&gt;WindowProxyBase&lt;/b&gt;-Instanz zur&amp;#252;ck. Auf Host-Seite wird die Methode durch die &lt;b&gt;AddInHostView&lt;/b&gt;-Klasse bereit gestellt.&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align: none"&gt;&lt;span style="color: blue; font-family: " courier new"; mso-bidi-font-size: 10.0pt; mso-fareast-language: DE; mso-no-proof: yes"&gt;public&lt;/span&gt;&lt;span style="font-family: " courier new"; mso-bidi-font-size: 10.0pt; mso-fareast-language: DE; mso-no-proof: yes"&gt; &lt;span style="color: blue"&gt;abstract&lt;/span&gt; &lt;span style="color: blue"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af"&gt;AddInHostView       &lt;br /&gt;&lt;/span&gt;{      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;public&lt;/span&gt; &lt;span style="color: blue"&gt;abstract&lt;/span&gt; &lt;span style="color: #2b91af"&gt;WindowProxyBase&lt;/span&gt; GetSurface();      &lt;br /&gt;}      &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p&gt;Fehlen noch die entsprechenden Adapter-Klassen. Zun&amp;#228;chst die &lt;b&gt;AddInViewToContractAdapter&lt;/b&gt;-Klasse der Add-In-Seite:&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align: none"&gt;&lt;span style="font-family: " courier new"; mso-bidi-font-size: 10.0pt; mso-fareast-language: DE; mso-no-proof: yes"&gt;[&lt;span style="color: #2b91af"&gt;AddInAdapter&lt;/span&gt;]      &lt;br /&gt;&lt;span style="color: blue"&gt;public&lt;/span&gt; &lt;span style="color: blue"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af"&gt;AddInViewToContractAdapter&lt;/span&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; : &lt;span style="color: #2b91af"&gt;ContractBase&lt;/span&gt;, &lt;span style="color: #2b91af"&gt;IAddInContract&lt;/span&gt;       &lt;br /&gt;{      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;private&lt;/span&gt; &lt;span style="color: #2b91af"&gt;AddInView&lt;/span&gt; m_view;      &lt;br /&gt;      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;public&lt;/span&gt; AddInViewToContractAdapter(&lt;span style="color: #2b91af"&gt;AddInView&lt;/span&gt; view)      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;{      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;m_view = view;      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;}      &lt;br /&gt;      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;public&lt;/span&gt; &lt;span style="color: #2b91af"&gt;IWindowProxy&lt;/span&gt; GetSurface()      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;{      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;WindowProxyBase&lt;/span&gt; proxy =       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;this&lt;/span&gt;.m_view.GetSurface();      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;return&lt;/span&gt; &lt;span style="color: blue"&gt;new&lt;/span&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #2b91af"&gt;WindowProxyViewToContractAddInAdapter&lt;/span&gt;(proxy);      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;}      &lt;br /&gt;}      &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p&gt;Hier kommt die &lt;b&gt;WindowProxyViewToContractAddInAdapter&lt;/b&gt;-Klasse aus der &lt;b&gt;WindowsFormsAddInProxy.dll&lt;/b&gt; zum Einsatz, um eine &lt;b&gt;IWindowProxy&lt;/b&gt;-Implementierung einer bestimmten Version bereit zu stellen.&lt;/p&gt;  &lt;p&gt;Analog dazu stellt &lt;b&gt;AddInContractToHostViewAdapter&lt;/b&gt; den entsprechenden Adapter f&amp;#252;r die Host-Seite bereit. &lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align: none"&gt;&lt;span style="font-family: " courier new"; mso-bidi-font-size: 10.0pt; mso-fareast-language: DE; mso-no-proof: yes"&gt;[&lt;span style="color: #2b91af"&gt;HostAdapter&lt;/span&gt;]      &lt;br /&gt;&lt;span style="color: blue"&gt;public&lt;/span&gt; &lt;span style="color: blue"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af"&gt;AddInContractToHostViewAdapter&lt;/span&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; : &lt;span style="color: #2b91af"&gt;AddInHostView       &lt;br /&gt;&lt;/span&gt;{      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;private&lt;/span&gt; &lt;span style="color: #2b91af"&gt;IAddInContract&lt;/span&gt; m_contract;      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;private&lt;/span&gt; &lt;span style="color: #2b91af"&gt;ContractHandle&lt;/span&gt; m_handle;      &lt;br /&gt;      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;public&lt;/span&gt; AddInContractToHostViewAdapter      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (&lt;span style="color: #2b91af"&gt;IAddInContract&lt;/span&gt; contract)      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;{      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;m_contract = contract;      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;m_handle = &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;ContractHandle&lt;/span&gt;(contract);      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;}      &lt;br /&gt;      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;public&lt;/span&gt; &lt;span style="color: blue"&gt;override&lt;/span&gt; &lt;span style="color: #2b91af"&gt;WindowProxyBase&lt;/span&gt; GetSurface()      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;{      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IWindowProxy&lt;/span&gt; proxy = m_contract.GetSurface();      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;return&lt;/span&gt; &lt;span style="color: blue"&gt;new&lt;/span&gt;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #2b91af"&gt;WindowProxyViewToContractHostAdapter&lt;/span&gt;(proxy);      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;}      &lt;br /&gt;}      &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p&gt;Hier kommt die &lt;b&gt;WindowProxyViewToContractHostAdapter&lt;/b&gt;-Klasse zum Einsatz, die f&amp;#252;r die Bereitstellung einer entsprechenden &lt;b&gt;WindowProxyBase&lt;/b&gt;-Instanz sorgt.&lt;/p&gt;  &lt;h4&gt;Add-In erstellen&lt;/h4&gt;  &lt;p&gt;Nachdem die Infrastruktur steht, kann es an die Implementierung der Add-Ins gehen. Hierf&amp;#252;r muss zun&amp;#228;chst einmal eine entsprechende Oberfl&amp;#228;che bereit gestellt werden. Die &lt;b&gt;WindowsFormsAddInProxy.dll&lt;/b&gt; stellt hierf&amp;#252;r die Basisklasse &lt;b&gt;AddInSurface&lt;/b&gt; bereit. Sie leitet von &lt;b&gt;UserControl&lt;/b&gt; ab und enth&amp;#228;lt die n&amp;#246;tige Logik zum Transfer der Oberfl&amp;#228;che &amp;#252;ber die AppDomain-Grenze. Durch die Ableitung von &lt;b&gt;UserControl&lt;/b&gt; kann der Entwurf der Oberfl&amp;#228;che bequem &amp;#252;ber den Control Designer erfolgen, ohne das irgendwelche Add-In-spezifischen Details ber&amp;#252;cksichtigt werden m&amp;#252;ssen. Im Demoprojekt habe ich einfach eine Handvoll Controls aus der Toolbox gezogen auf der Oberfl&amp;#228;che platziert:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.google.com/NeumannJN/R4IDnMe4knI/AAAAAAAAADg/Kzcsv8OWChY/Surface%5B5%5D"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="317" alt="Surface" src="http://lh5.google.com/NeumannJN/R4IDnse4koI/AAAAAAAAADo/IhezvHsjCyg/Surface_thumb%5B3%5D" width="467" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Nachdem die Entwurfsphase abgeschlossen ist, kann es an die Implementierung gehen. Da diese im Wesentlichen nur aus der &lt;b&gt;GetSurface()&lt;/b&gt;-Methode besteht, ist das Ganze recht &amp;#252;berschaubar:&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align: none"&gt;&lt;span style="font-family: " courier new"; mso-bidi-font-size: 10.0pt; mso-fareast-language: DE; mso-no-proof: yes"&gt;[System.AddIn.&lt;span style="color: #2b91af"&gt;AddIn&lt;/span&gt;(&lt;span style="color: #a31515"&gt;&amp;quot;Add-In 1&amp;quot;&lt;/span&gt;,       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;Version=&lt;span style="color: #a31515"&gt;&amp;quot;1.0.0.0&amp;quot;&lt;/span&gt;,       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;Description=&lt;span style="color: #a31515"&gt;&amp;quot;Add-In Nr. 1&amp;quot;&lt;/span&gt;,       &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;Publisher=&lt;span style="color: #a31515"&gt;&amp;quot;J&amp;#246;rg Neumann&amp;quot;&lt;/span&gt;)]      &lt;br /&gt;&lt;span style="color: blue"&gt;public&lt;/span&gt; &lt;span style="color: blue"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af"&gt;FirstAddIn&lt;/span&gt; : &lt;span style="color: #2b91af"&gt;AddInView       &lt;br /&gt;&lt;/span&gt;{      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;private&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Surface&lt;/span&gt; m_surface;      &lt;br /&gt;      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;public&lt;/span&gt; &lt;span style="color: blue"&gt;override&lt;/span&gt; &lt;span style="color: #2b91af"&gt;WindowProxyBase&lt;/span&gt; GetSurface()      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;{      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;m_surface = &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Surface&lt;/span&gt;();      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;return&lt;/span&gt; &lt;span style="color: blue"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;WindowProxy&lt;/span&gt;(m_surface);      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;}      &lt;br /&gt;}      &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p&gt;In &lt;b&gt;GetSurface()&lt;/b&gt; wird eine Instanz von &lt;b&gt;Surface&lt;/b&gt; erzeugt. &lt;b&gt;Surface&lt;/b&gt; leitet wiederum von &lt;b&gt;AddInSurface&lt;/b&gt; ab und enth&amp;#228;lt die gerade entworfene Oberfl&amp;#228;che. Hierbei ist zu beachten, dass die entsprechende Variable auf Klassenebene deklariert wird, da sonst der Garbage Collector zuschl&amp;#228;gt und die Oberfl&amp;#228;che nach kurzer Zeit entsorgt. F&amp;#252;r die R&amp;#252;ckgabe muss nun noch eine &lt;b&gt;WindowProxyBase&lt;/b&gt;-Instanz erstellt werden. Dies ist jedoch mit einem Einzeiler erledigt, da &lt;b&gt;WindowProxy&lt;/b&gt; ein &lt;b&gt;AddInSurface&lt;/b&gt;-Objekt im Konstruktor entgegen nimmt.&lt;/p&gt;  &lt;h4&gt;Add-In im Host laden&lt;/h4&gt;  &lt;p&gt;Zum Einbinden der Add-In-Oberfl&amp;#228;che in die Host-Anwendung stellt die &lt;b&gt;WindowsFormsAddInProxy.dll&lt;/b&gt; die Komponente &lt;b&gt;WindowProxyPanel&lt;/b&gt; bereit. Sie leitet von &lt;b&gt;UserControl&lt;/b&gt; ab und kann somit direkt auf die Form der Anwendung gezogen werden. &lt;b&gt;WindowProxyPanel&lt;/b&gt; hostet die &amp;#252;ber &lt;b&gt;AddInSurface&lt;/b&gt; bereitgestellte Oberfl&amp;#228;che und k&amp;#252;mmert sich hinter den Kulissen um die Synchronisation der entsprechenden Windows Messages (n&amp;#228;heres dazu im n&amp;#228;chsten Teil).&lt;/p&gt;  &lt;p&gt;Wie die folgende Abbildung zeigt, ist die Oberfl&amp;#228;che der Demoanwendung relativ &amp;#252;berschaubar. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.google.com/NeumannJN/R4IDoMe4kpI/AAAAAAAAADw/kwNDtBda81Q/HostApp%5B3%5D"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="399" alt="HostApp" src="http://lh5.google.com/NeumannJN/R4IDose4kqI/AAAAAAAAAD4/GX-1Pillxi0/HostApp_thumb%5B1%5D" width="459" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Sie besteht lediglich aus einer &lt;b&gt;WindowProxyPanel&lt;/b&gt;-Instanz, sowie einem Button zur Aktivierung. Der Code zum Laden des Add-Ins liegt der Einfachheit halber direkt im &lt;b&gt;Click&lt;/b&gt;-Event Handler:&lt;/p&gt;  &lt;p class="MsoNormal" style="mso-layout-grid-align: none"&gt;&lt;span style="color: blue; font-family: " courier new"; mso-bidi-font-size: 10.0pt; mso-fareast-language: DE; mso-no-proof: yes"&gt;private&lt;/span&gt;&lt;span style="font-family: " courier new"; mso-bidi-font-size: 10.0pt; mso-fareast-language: DE; mso-no-proof: yes"&gt; &lt;span style="color: blue"&gt;void&lt;/span&gt; bindAddInButton_Click(      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: blue"&gt;object&lt;/span&gt; sender, &lt;span style="color: #2b91af"&gt;EventArgs&lt;/span&gt; e)      &lt;br /&gt;{      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Collection&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;AddInToken&lt;/span&gt;&amp;gt; availableAddIns =      &lt;br /&gt;&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; AddInStore&lt;/span&gt;.FindAddIns(      &lt;br /&gt;&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;typeof&lt;/span&gt;(&lt;span style="color: #2b91af"&gt;AddInHostView&lt;/span&gt;),      &lt;br /&gt;&lt;span style="color: #2b91af"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #2b91af"&gt;Environment&lt;/span&gt;.CurrentDirectory);      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (availableAddIns.Count &amp;gt; 0)      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;{      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;instance =       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; availableAddIns[0].Activate&amp;lt;&lt;span style="color: #2b91af"&gt;AddInHostView&lt;/span&gt;&amp;gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (&lt;span style="color: #2b91af"&gt;AddInSecurityLevel&lt;/span&gt;.Host);      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (instance != &lt;span style="color: blue"&gt;null&lt;/span&gt;)      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;{      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: #2b91af"&gt;WindowProxyBase&lt;/span&gt; window =      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; instance.GetSurface();      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (window != &lt;span style="color: blue"&gt;null&lt;/span&gt;)      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;{      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;this&lt;/span&gt;.windowsProxyPanel1.      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; SetWindow(window);      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;this&lt;/span&gt;.windowsProxyPanel1.Select();      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;}      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;}      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;}      &lt;br /&gt;}      &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p&gt;Hier werden zun&amp;#228;chst &amp;#252;ber die &lt;b&gt;FindAddIns()&lt;/b&gt;-Methode die verf&amp;#252;gbaren Add-Ins ermittelt. Daraufhin wird das erste gefundene Add-In &amp;#252;ber die &lt;b&gt;Activate()&lt;/b&gt;-Methode aktiviert, wobei &amp;#252;ber den Wert &lt;b&gt;AddInSecurityLevel.Host&lt;/b&gt; festgelegt wird, dass das Add-In im Sicherheitskontext der Anwendung laufen soll.&lt;/p&gt;  &lt;p&gt;Nun kommen wir zum spannenden Teil: Auf der erzeugten Instanz wird &amp;#252;ber die &lt;b&gt;GetSurface()&lt;/b&gt;-Methode die Oberfl&amp;#228;che des Add-In ermittelt. Das zur&amp;#252;ckgegebene &lt;b&gt;WindowProxyBase&lt;/b&gt;-Objekt wird daraufhin an das &lt;b&gt;WindowProxyPanel&lt;/b&gt; gebunden. Hierzu nimmt dessen &lt;b&gt;SetWindow()&lt;/b&gt;-Methode die entsprechende &lt;b&gt;WindowProxyBase&lt;/b&gt;-Instanz entgegen.&lt;/p&gt;  &lt;p&gt;Im Vergleich zum getriebenen Aufwand sieht das Ergebnis dann doch relativ unspektakul&amp;#228;r aus:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.google.com/NeumannJN/R4IDpMe4krI/AAAAAAAAAEA/Q6RqoLmLOMI/HostInRuntime%5B5%5D"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="310" alt="HostInRuntime" src="http://lh5.google.com/NeumannJN/R4IDpse4ksI/AAAAAAAAAEI/_YTUDH0VreE/HostInRuntime_thumb%5B3%5D" width="472" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Bei dieser Art der Verwendung gibt es jedoch noch einen kleinen Sch&amp;#246;nheitsfehler. Da die Oberfl&amp;#228;che &amp;#252;ber die Windows API &amp;#8222;umgeh&amp;#228;ngt&amp;#8220; wurde, hat Windows Forms keine Informationen &amp;#252;ber die enthaltenen Controls in der Add-In-Oberfl&amp;#228;che. Dies f&amp;#252;hrt dazu, dass bei einem Tab-Wechsel der Fokus lediglich zwischen Button und &lt;b&gt;WindowProxy&lt;/b&gt; wechselt und dabei die eingebetteten Controls ignoriert. Zwar wurde eine entsprechende Fokussteuerung in &lt;b&gt;AddInSurface&lt;/b&gt; implementiert, diese wird jedoch vom Hostfenster &amp;#252;bersteuert. Als Workaround kann die &lt;b&gt;ProcessTabKey()&lt;/b&gt;-Methode der Form wie folgt &amp;#252;berschrieben werden. &lt;/p&gt;  &lt;p&gt;&lt;span style="color: blue; font-family: " courier new"; mso-bidi-font-size: 10.0pt; mso-fareast-language: DE; mso-no-proof: yes"&gt;protected&lt;/span&gt;&lt;span style="font-family: " courier new"; mso-bidi-font-size: 10.0pt; mso-fareast-language: DE; mso-no-proof: yes"&gt; &lt;span style="color: blue"&gt;override&lt;/span&gt; &lt;span style="color: blue"&gt;bool&lt;/span&gt; ProcessTabKey(&lt;span style="color: blue"&gt;bool&lt;/span&gt; forward)      &lt;br /&gt;{      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;if&lt;/span&gt; (&lt;span style="color: blue"&gt;this&lt;/span&gt;.ActiveControl == &lt;span style="color: blue"&gt;this&lt;/span&gt;.windowsProxyPanel1)      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;{      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;this&lt;/span&gt;.windowsProxyPanel1.TabInto();      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;return&lt;/span&gt; &lt;span style="color: blue"&gt;false&lt;/span&gt;;      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;}      &lt;br /&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;&lt;span style="color: blue"&gt;return&lt;/span&gt; &lt;span style="color: blue"&gt;base&lt;/span&gt;.ProcessTabKey(forward);      &lt;br /&gt;}      &lt;p&gt;&lt;/p&gt;   &lt;/span&gt;&lt;/p&gt;  &lt;p&gt;Hier wird gepr&amp;#252;ft, ob die &lt;b&gt;WindowProxyPanel&lt;/b&gt;-Instanz gerade aktiviert ist. Wenn ja, wird dieser die Tab-Steuerung durch einen Aufruf der &lt;b&gt;TabInto()&lt;/b&gt;-Methode &amp;#252;bergeben.&lt;/p&gt;  &lt;p&gt;In der Praxis erweist sich dieser kleine Sch&amp;#246;nheitsfehler jedoch als eher unbedeutend, da das Hauptfenster einer komplexen Anwendung meist aus Men&amp;#252;s, Toolboxen und List Bars besteht und diese nicht &amp;#252;ber die klassische Tab-Steuerung erreichbar sind.&lt;/p&gt;  &lt;p&gt;Im n&amp;#228;chsten Teil gehe ich n&amp;#228;her auf die Implementierung der &lt;b&gt;WindowsFormsAddInProxy.dll&lt;/b&gt; ein und zeige wie die Win32-Kommunikation zwischen Add-In und Host funktioniert.&lt;/p&gt;  &lt;p&gt;Den Source Code von &lt;b&gt;WindowsFormsAddInProxy&lt;/b&gt; k&amp;#246;nnen Sie inkl. Demoprojekt &lt;a href="http://www.esnips.com/doc/69208092-bb7e-45b9-9539-0d56e1a98948/SystemAddInWinFormsDemo"&gt;hier&lt;/a&gt; herunter laden. F&amp;#252;r Feedback bin ich stets dankbar.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;PS:&lt;/strong&gt; Wenn Sie mehr &amp;#252;ber System.AddIn erfahren m&amp;#246;chten, schauen Sie auf der diesj&amp;#228;hrigen &lt;a href="http://www.basta.net"&gt;BASTA! Spring Edition&lt;/a&gt; vorbei. Dort f&amp;#252;hren &lt;a href="http://www.leastprivilege.com/"&gt;Dominick Baier&lt;/a&gt; und ich in der Session &lt;a href="http://basta.net/tracks.asp?tid=668&amp;amp;language=de#session-5"&gt;&amp;#8222;.NET-Anwendungen sicher und robust durch Add-ins erweitern&lt;/a&gt;&amp;#8220; in das Thema ein.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-1670068809411569284?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/1670068809411569284/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=1670068809411569284' title='4 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/1670068809411569284'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/1670068809411569284'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2008/01/test.html' title='Windows Forms Support für System.AddIn, Teil 1'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-1005034212396858565</id><published>2007-10-22T08:23:00.000+02:00</published><updated>2007-10-22T08:33:39.463+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Veröffentlichungen'/><title type='text'>Artikel in der aktuellen dotnetpro</title><content type='html'>&lt;p&gt;In der aktuellen Ausgabe der &lt;a href="http://www.dotnetpro.de/"&gt;dotnetpro&lt;/a&gt; (11/2007) ist der Artikel "Einfacher synchronisieren &amp;shy;- Die ADO.NET Synchronization Services" erschienen, den ich zusammen mit meinem Kollegen Matthias Hönig geschrieben habe.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Aus dem Abstract:&lt;br /&gt;&lt;/strong&gt;Bei Offlineclients ergeben sich die meisten Probleme während der Synchronisation der Daten. Genau für diesen Fall hat Microsoft die ADO.NET Synchronization Services entwickelt. Sie werden fester Bestandteil des kommenden .NET Framework 3.5 sein. dotnetpro stellt das System vor.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-1005034212396858565?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://headwriteline.blogspot.com/2007/10/artikel-in-der-aktuellen-dotnetpro.html' title='Artikel in der aktuellen dotnetpro'/><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/1005034212396858565/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=1005034212396858565' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/1005034212396858565'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/1005034212396858565'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2007/10/artikel-in-der-aktuellen-dotnetpro.html' title='Artikel in der aktuellen dotnetpro'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-3938006638060745560</id><published>2007-09-24T11:20:00.000+02:00</published><updated>2007-09-24T11:26:20.883+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Konferenzen'/><title type='text'>Slides und Samples von der BASTA!</title><content type='html'>Auch diesmal war die &lt;a href="http://www.basta.net/"&gt;BASTA!&lt;/a&gt; wieder ein echtes Highlight! Die Slides und Samples meiner Sessions finden Sie hier:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.esnips.com/nsdoc/61f19e19-4f35-41a3-8815-ced7e35f5130"&gt;SQL Server 2005 Compact Edition&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.esnips.com/doc/95d881ad-72a4-4de9-a634-3041ec1ae492/VBDay-Transaktionen"&gt;Transaktionen einbinden&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.esnips.com/nsdoc/eae9dee4-3cb5-4f98-8ff7-07c50818583e"&gt;SQL Server Power Show&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.esnips.com/nsdoc/f8969edc-8076-4400-8546-6b7be029854d"&gt;Diagnose und Monitoring von verteilten Anwendungen&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.esnips.com/nsdoc/d81f479b-594b-43e7-b930-68b8dc6ee95e"&gt;WPF/WinForms- Interoperabilität&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.esnips.com/nsdoc/b3112ae0-b176-4a16-9a4a-e936af8b7a25"&gt;System.Transactions 2.0&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-3938006638060745560?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://headwriteline.blogspot.com/2007/09/slides-und-samples-von-der-basta.html' title='Slides und Samples von der BASTA!'/><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/3938006638060745560/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=3938006638060745560' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/3938006638060745560'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/3938006638060745560'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2007/09/slides-und-samples-von-der-basta.html' title='Slides und Samples von der BASTA!'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-2609784451848509488</id><published>2007-09-24T11:00:00.000+02:00</published><updated>2007-09-24T11:03:13.156+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Veröffentlichungen'/><title type='text'>Artikel in der aktuellen dotnetpro</title><content type='html'>In der aktuellen &lt;a href="http://www.dotnetpro.de/"&gt;dotnetpro&lt;/a&gt; (10/2007) ist mein Artikel "&lt;strong&gt;Rich Client im Browser &amp;shy;– Browseranwendungen mit WPF entwickeln&lt;/strong&gt;" erschienen.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Aus dem Abstract:&lt;/strong&gt;&lt;br /&gt;Mit WPF lassen sich nicht nur Desktopanwendungen erstellen. WPF-Applikationen können auch im Browser ablaufen. Dafür stehen gleich fünf verschiedene Technologien zur Verfügung: WPF-Desktop, WPF-ClickeOnce, XAML Browser Application, Loose XAML und Silverlight. dotnetpro stellt die neuen Konzepte vor und zeigt, wie Sie auch ohne HTML beeindruckende Browseranwendungen erstellen.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-2609784451848509488?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://headwriteline.blogspot.com/2007/09/artikel-in-der-aktuellen-dotnetpro.html' title='Artikel in der aktuellen dotnetpro'/><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/2609784451848509488/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=2609784451848509488' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/2609784451848509488'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/2609784451848509488'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2007/09/artikel-in-der-aktuellen-dotnetpro.html' title='Artikel in der aktuellen dotnetpro'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-3628311902021491262</id><published>2007-08-08T14:05:00.000+02:00</published><updated>2007-08-08T14:11:11.122+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Veröffentlichungen'/><title type='text'>Artikel in der aktuellen dotnetpro</title><content type='html'>In der aktuellen Ausgabe der &lt;a href="http://www.dotnetpro.de/"&gt;dotnetpro&lt;/a&gt; (9/2007) ist der Artikel "&lt;strong&gt;Leicht verfügbar - Ressourcen nutzen mit Windows Presentation Foundation&lt;/strong&gt;" erschienen, den ich zusammen mit Björn Grossmann geschrieben habe.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Aus dem Abstract:&lt;/strong&gt;&lt;br /&gt;Mit WPF greifen Entwickler sehr flexibel auf jegliche Arten von Ressourcen zu. Ressourcen können in eine Assembly eingebettet sein oder als lose Dateien im lokalen Dateisystem, in einem Netzwerk-Share oder im Internet vorliegen. Resource Dictionaries ermöglichen die mehrfache Wiederverwendung. dotnetpro stellt die neuen Konzepte vor.&lt;br /&gt;&lt;br /&gt;Interessierte finden den Artikel auch als frei verfügbare PDF-Version unter &lt;a href="http://dotnetpro.de/articles/freearticles/pdf/2007-09-WPF.pdf"&gt;http://dotnetpro.de/articles/freearticles/pdf/2007-09-WPF.pdf&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-3628311902021491262?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://headwriteline.blogspot.com/2007/08/artikel-in-der-aktuellen-dotnetpro.html' title='Artikel in der aktuellen dotnetpro'/><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/3628311902021491262/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=3628311902021491262' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/3628311902021491262'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/3628311902021491262'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2007/08/artikel-in-der-aktuellen-dotnetpro.html' title='Artikel in der aktuellen dotnetpro'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-1494486596636638005</id><published>2007-07-19T16:41:00.000+02:00</published><updated>2007-07-19T16:43:46.736+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Veröffentlichungen'/><title type='text'>Artikel in der aktuellen dotnetpro</title><content type='html'>In der aktuellen &lt;a href="http://www.dotnetpro.de/"&gt;dotnetpro&lt;/a&gt; (8/2007) sind zwei Artikel von mir erschienen:&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Ein zweiter Blick auf Microsoft Silverlight&lt;br /&gt;&lt;/strong&gt;Ende April fand Microsofts alljährliche Webentwicklerkonferenz MIX statt. Einen der Schwerpunkte bildete die Webtechnologie Silverlight (vormals WPF/E). Sie bietet umfangreiche Multimediafähigkeiten sowie Unabhängigkeit von Plattform und Browser. Außerdem arbeitet sie mit mehreren Programmier- und Skriptsprachen zusammen und bringt eine abgespeckte .NET-Version mit. dotnetpro zeigt, was sich bisher getan hat und beleuchtet bereits geplante Erweiterungen.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Interoperabilität zwischen WPF und Windows Forms&lt;br /&gt;&lt;/strong&gt;WPF eröffnet eine schöne neue Welt, bricht jedoch mit herkömmlichen Technologien. Eine Anwendung auf WPF umzustellen erfordert mehr, als nur einen Upgrade-Wizard zu starten. Zudem bietet WPF zurzeit noch nicht alles, was bei Windows Forms zum Standard gehört. Der Ausweg: WPF enthält Funktionen, die es ermöglichen, sowohl Windows Forms und ActiveX-Elemente zu nutzen als auch Teile von WPF in klassischen Anwendungen zu verwenden. dotnetpro stellt diese Fähigkeiten vor.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-1494486596636638005?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://headwriteline.blogspot.com/2007/07/artikel-in-der-aktuellen-dotnetpro_19.html' title='Artikel in der aktuellen dotnetpro'/><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/1494486596636638005/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=1494486596636638005' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/1494486596636638005'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/1494486596636638005'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2007/07/artikel-in-der-aktuellen-dotnetpro_19.html' title='Artikel in der aktuellen dotnetpro'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-6316464399818961566</id><published>2007-07-03T17:39:00.001+02:00</published><updated>2007-07-03T18:04:10.383+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Veröffentlichungen'/><title type='text'>Überarbeitete Auflage des SQL Server 2005 Buchs</title><content type='html'>Seit Ende Juni ist die zweite, überarbeitete Ausgabe von "&lt;a href="2http://4.bp.blogspot.com/_11VTbOPwP_U/RopyZQgii_I/AAAAAAAAAAw/QBkpuqDoVw0/s1600-h/sql.jpg"&gt;Das Programmierhandbuch SQL Server 2005&lt;/a&gt;" verfügbar, dass ich zusammen mit Dirk Mertins und Andreas Kühnel geschrieben habe. Die Seitenzahl ist von 879 auf 1010 Seiten gestiegen und besonders der ADO.NET-Teil ist deutlich erweitert worden.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amazon.de/Das-Programmierhandbuch-SQL-Server-2005/dp/383621069X/ref=sr_1_2/303-0341915-8372270?ie=UTF8&amp;s=books&amp;amp;amp;amp;amp;qid=1183476835&amp;amp;sr=8-"&gt;&lt;img id="BLOGGER_PHOTO_ID_5083000907694771186" style="CURSOR: hand" alt="" src="http://4.bp.blogspot.com/_11VTbOPwP_U/RopyZQgii_I/AAAAAAAAAAw/QBkpuqDoVw0/s400/sql.jpg" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-6316464399818961566?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://headwriteline.blogspot.com/2007/07/berarbeitete-auflage-des-sql-server.html' title='Überarbeitete Auflage des SQL Server 2005 Buchs'/><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/6316464399818961566/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=6316464399818961566' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/6316464399818961566'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/6316464399818961566'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2007/07/berarbeitete-auflage-des-sql-server.html' title='Überarbeitete Auflage des SQL Server 2005 Buchs'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_11VTbOPwP_U/RopyZQgii_I/AAAAAAAAAAw/QBkpuqDoVw0/s72-c/sql.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-8274144855265121619</id><published>2007-07-03T09:48:00.000+02:00</published><updated>2007-07-03T09:52:22.792+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Veröffentlichungen'/><title type='text'>Artikel in der aktuellen dotnetpro</title><content type='html'>In der aktuellen &lt;a href="http://www.dotnetpro.de/"&gt;dotnetpro&lt;/a&gt; (7/2007) ist mein Artikel "Ressourcenschonender Umgang mit sehr großen Dateien" erschienen.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Aus dem Abstract:&lt;/strong&gt;&lt;br /&gt;Der Umgang mit Dateien gehört zum Handwerkszeug eines jeden Entwicklers. Das .NET Framework bietet hierfür eine Vielzahl an Klassen. Schwierig wird es jedoch, wenn die Dateien eine bestimmte Größe überschreiten. Dann dauert der Zugriff nicht nur quälend lange, sondern führt auch nicht selten zu einem Speicherüberlauf. dotnetpro zeigt, wie Sie solche Riesendateien effizient verarbeiten und bringt Komponenten und Tools für den praktischen Einsatz gleich mit.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-8274144855265121619?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://headwriteline.blogspot.com/2007/07/artikel-in-der-aktuellen-dotnetpro.html' title='Artikel in der aktuellen dotnetpro'/><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/8274144855265121619/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=8274144855265121619' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/8274144855265121619'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/8274144855265121619'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2007/07/artikel-in-der-aktuellen-dotnetpro.html' title='Artikel in der aktuellen dotnetpro'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-8915260526811660013</id><published>2007-04-16T14:50:00.000+02:00</published><updated>2007-04-16T14:54:53.461+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Diagnose'/><category scheme='http://www.blogger.com/atom/ns#' term='Veröffentlichungen'/><title type='text'>Artikel in der aktuellen dotnetpro</title><content type='html'>Für die aktuelle &lt;a href="http://www.dotnetpro.de"&gt;dotnetpro&lt;/a&gt; (5/2007) habe ich die folgenden zwei Artikel geschrieben.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Am Puls der Anwendung: Diagnose-Frameworks für .NET 2.0&lt;/strong&gt;&lt;br /&gt;(zusammen mit Daniel Leinius)&lt;br /&gt;Die Instrumentierung einer Anwendung ist keine leichte Aufgabe. Neben dem eigentlichen Trace-Code müssen Sie sich Gedanken über die anzusprechenden Ausgabeziele, wie EventLog, Datenbank oder WMI Gedanken machen. Diagnose-Frameworks abstrahieren diese Details und nehmen Ihnen die Implementierungsarbeit ab. Vor allem bieten Sie aber ein einheitliches Programmiermodell und eine dynamische Konfiguration zur Laufzeit. dotnetpro stellt drei gängige Frameworks vor, hebt Stärken und Schwächen hervor und gibt Empfehlungen für den Einsatz.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;EKG für die Anwendung: Laufzeitanalyse mit .NET 2.0&lt;/strong&gt;&lt;br /&gt;Die Fehlersuche gehört zu den am wenigsten geliebten Tätigkeiten im Software-Entwicklungsprozess. Erst recht, wenn auf dem Entwicklungsrechner alles funktioniert und Probleme nur im Produktionssystem auftreten. Hier sind aussagekräftige Laufzeitinformationen gefragt. Das .NET-Framework bietet jedoch mit Tracing, Performance Countern und WMI eine Reihe von Technologien, die Ihnen bei der Analyse helfen können. dotnetpro beschreibt die grundlegenden Konzepte und bietet Ihnen Komponenten, die Sie bei Instrumentierung und Überwachung Ihrer Anwendung unterstützen.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-8915260526811660013?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://headwriteline.blogspot.com/2007/04/artikel-in-der-aktuellen-dotnetpro.html' title='Artikel in der aktuellen dotnetpro'/><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/8915260526811660013/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=8915260526811660013' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/8915260526811660013'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/8915260526811660013'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2007/04/artikel-in-der-aktuellen-dotnetpro.html' title='Artikel in der aktuellen dotnetpro'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-1819068311592874482</id><published>2007-03-08T07:33:00.000+01:00</published><updated>2007-03-08T07:35:41.858+01:00</updated><title type='text'>Artikel in der aktuellen dotnetpro</title><content type='html'>In der aktuellen &lt;a href="www.dotnetpro.de"&gt;dotnetpro&lt;/a&gt; (4/2007) ist mein Artikel "Wild und wunderbar: Browseroberflächen mit WPF/E entwickeln" erschienen.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Aus dem Abstract:&lt;/strong&gt;&lt;br /&gt;Mit WPF/E (&lt;em&gt;Windows Presentation Foundation Everywhere&lt;/em&gt;) bringt Microsoft eine abgespeckte WPF-Variante, die Web-Sites um Grafik- und Multimedia-Fähigkeiten erweitert und auf verschiedenen Betriebssystemen und Browsern läuft. Da es sich nahtlos in klassische HTML-Seiten integriert, können Sites sehr leicht um interaktiven Videos, Musik oder 2D-Animationen erweitert werden. Die aktuelle CTP (&lt;em&gt;Community Technologie Preview&lt;/em&gt;) lässt bereits erahnen, welche Kraft in dieser Runtime steckt. dotnetpro erklärt die Konzepte hinter WPF/E und zeigt, in welche Szenarien der Einsatz sinnvoll ist.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-1819068311592874482?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://headwriteline.blogspot.com/2007/03/artikel-in-der-aktuellen-dotnetpro.html' title='Artikel in der aktuellen dotnetpro'/><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/1819068311592874482/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=1819068311592874482' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/1819068311592874482'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/1819068311592874482'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2007/03/artikel-in-der-aktuellen-dotnetpro.html' title='Artikel in der aktuellen dotnetpro'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-1623116992888304203</id><published>2007-03-07T09:10:00.000+01:00</published><updated>2007-03-07T09:15:48.569+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Veröffentlichungen'/><title type='text'>Artikel in der Computer World Schweiz</title><content type='html'>In der Ausgabe 50/06 der &lt;a href="http://www.Computerworld.ch"&gt;Computer World Schweiz &lt;/a&gt;ist der Artikel "&lt;strong&gt;Leichtgewichtige Transaktionen&lt;/strong&gt;" erschienen, den ich zusammen mit meinem Kollegen Markus Jahn geschrieben habe.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Aus dem Abstract:&lt;/strong&gt;&lt;br /&gt;Mit .NET 2.0 führt Microsoft ein leichtgewichtiges Transaktionssystem ein, dass nicht nur durch seine gute Performance, sondern vor allem durch seine Einfachheit besticht. Hiervon profitieren insbesondere Datenbankanwendungen, da die entsprechenden ADO.NET-Klassen nahtlos mit dem neuen System zusammen arbeiten. Zudem wird es erstmals möglich, eigene transaktionale Klassen zu erstellen, ohne die Enterprise Services und das dahinter liegende COM+-System verwenden zu müssen.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-1623116992888304203?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://headwriteline.blogspot.com/2007/03/artikel-in-der-computer-world-schweiz.html' title='Artikel in der Computer World Schweiz'/><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/1623116992888304203/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=1623116992888304203' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/1623116992888304203'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/1623116992888304203'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2007/03/artikel-in-der-computer-world-schweiz.html' title='Artikel in der Computer World Schweiz'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-8962689177574836399</id><published>2007-03-02T14:34:00.000+01:00</published><updated>2007-03-02T14:50:16.752+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Konferenzen'/><title type='text'>Slides und Samples von der BASTA!</title><content type='html'>Die Spring Edition der &lt;a href="http://www.basta.net"&gt;BASTA!&lt;/a&gt; war auch diesmal wieder ein echtes Highlight. Die Slides und Samples meiner Vorträge finden Sie hier:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.esnips.com/doc/411272b1-3978-42a8-be36-98b5f72ae40d/Neumann_Transactions"&gt;Transaktionale Programmierung mit System.Transactions&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.esnips.com/doc/89059402-689c-47cc-bc24-75e6cbc9202d/Neumann_WPFInterop"&gt;Glücklich vereint: Interoperabilität zwischen WPF und Windows Forms&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-8962689177574836399?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://headwriteline.blogspot.com/2007/03/slides-und-samples-von-der-basta.html' title='Slides und Samples von der BASTA!'/><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/8962689177574836399/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=8962689177574836399' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/8962689177574836399'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/8962689177574836399'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2007/03/slides-und-samples-von-der-basta.html' title='Slides und Samples von der BASTA!'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-6593163540626246938</id><published>2007-02-01T14:37:00.000+01:00</published><updated>2007-02-01T15:19:35.579+01:00</updated><title type='text'>Pimp my ElementHost!</title><content type='html'>Mit dem &lt;a href="http://msdn2.microsoft.com/en-us/library/system.windows.forms.integration.elementhost.aspx"&gt;ElementHost&lt;/a&gt; kann man ja bekanntlich WPF-Content in Windows Forms hosten. Dies geht im Moment jedoch rein programmatisch - eine Windows Forms Designer-Integration existiert (zumindest auf den ersten Blick) nicht.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://msdn2.microsoft.com/en-us/library/system.windows.forms.integration.elementhost.aspx"&gt;ElementHost&lt;/a&gt; ist von Control abgeleitet und lässt sich somit auf eine Form ziehen (nachdem man die Komponente zuvor in die Toolbox eingefügt hat). Das Erscheinungsbild ist jedoch zunächst äußerst ernüchternd:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_11VTbOPwP_U/RcHtWhOFw-I/AAAAAAAAAAM/7nW-5YBbIn4/s1600-h/ElementHost+in+VS2005.bmp"&gt;&lt;img id="BLOGGER_PHOTO_ID_5026559630252557282" style="CURSOR: hand" alt="" src="http://3.bp.blogspot.com/_11VTbOPwP_U/RcHtWhOFw-I/AAAAAAAAAAM/7nW-5YBbIn4/s400/ElementHost+in+VS2005.bmp" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;p&gt;Das Control erscheint nämlich nur im Component Tray. Für den Entwurf einer komplexen Oberfläche, die neben Windows Forms auch WPF-Controls enthalten soll, ist das jedoch nicht wirklich akzeptabel.&lt;br /&gt;&lt;br /&gt;Ein Blick unter die Haube fördert jedoch zu Tage, dass dies nicht unbedingt eine Limitation des Controls ist, sondern vielmehr auf das Fehlen einer Designer-Assembly zurückzuführen ist. Ein Blick in die &lt;strong&gt;WindowsFormsIntegration.dll&lt;/strong&gt; schafft Klarheit:&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;&lt;strong&gt;[..., Designer("WindowsFormsIntegration.Design.ElementHostDesigner, WindowsFormsIntegration.Design, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;public class ElementHost : Control&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;{&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;...&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;}&lt;/span&gt;&lt;/p&gt;Demnach wird die Klasse &lt;strong&gt;ElementHostDesigner&lt;/strong&gt; für die Entwurfszeitdarstellung verwendet. Das Problem ist nur, dass die zugehörige Assembly &lt;strong&gt;WindowsFormsIntegration.Design.dll&lt;/strong&gt; nicht zum Lieferumfang von .NET 3.0 gehört. Da die hier angegebene Klasse somit nicht erstellt werden kann, verweigert der Windows Forms-Designer die Darstellung und verbannt die Komponente in den Tray.&lt;br /&gt;&lt;br /&gt;Diesen Misstand können Sie jedoch sehr leicht durch eine Ableitung beheben:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;&lt;strong&gt;[Designer("System.Windows.Forms.Design.ControlDesigner, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]&lt;br /&gt;&lt;/strong&gt;public class ElementHostControl : &lt;strong&gt;System.Windows.Forms.Integration.ElementHost&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;...&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Hierbei weisen Sie der Klasse über das &lt;strong&gt;Designer&lt;/strong&gt;-Attribut einfach den im Framework enthaltenen &lt;strong&gt;ControlDesigner&lt;/strong&gt; zu. Zur Integration des WPF-Contents verwenden Sie nun statt &lt;a href="http://msdn2.microsoft.com/en-us/library/system.windows.forms.integration.elementhost.aspx"&gt;ElementHost&lt;/a&gt; das &lt;strong&gt;ElementHostControl&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;Damit nun aber zur Entwurfszeit auch der zu hostende Content angezeigt wird, haben Sie zwei Möglichkeiten. Entweder Sie leiten von &lt;strong&gt;ElementHostControl&lt;/strong&gt; ab und erstellen im Konstruktor den Visual Tree programmatisch oder Sie binden ein WPF-Control dynamisch. Hierzu könnten Sie der Klasse z.B. eine &lt;strong&gt;ControlType&lt;/strong&gt;-Eigenschaft verpassen und in dessen Setter die angegebene Klasse per Reflection instanziieren. Das so erstellte Objekt weisen Sie schließlich der &lt;strong&gt;Child&lt;/strong&gt;-Eigenschaft von &lt;a href="http://msdn2.microsoft.com/en-us/library/system.windows.forms.integration.elementhost.aspx"&gt;ElementHost&lt;/a&gt; zu.&lt;br /&gt;&lt;br /&gt;In der aktuellen Orcas CTP (wohlgemerkt die CTP von VS9 und nicht die WPF-Extensions für VS2005) existiert hingegen die ominöse &lt;strong&gt;WindowsFormsIntegration.Design.dll&lt;/strong&gt; und liefert auch eine sehr nette Integration:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_11VTbOPwP_U/RcHtwROFw_I/AAAAAAAAAAU/hcEr5pKSqLE/s1600-h/ElementHost+in+Orcas.bmp"&gt;&lt;img id="BLOGGER_PHOTO_ID_5026560072634188786" style="CURSOR: hand" alt="" src="http://2.bp.blogspot.com/_11VTbOPwP_U/RcHtwROFw_I/AAAAAAAAAAU/hcEr5pKSqLE/s400/ElementHost+in+Orcas.bmp" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Hierbei ist es auch möglich, das entsprechende WPF-Control innerhalb des WinForms-Projekts zu erstellen, was zurzeit ebenfalls nicht funktioniert.&lt;br /&gt;&lt;br /&gt;Scheinbar möchte sich MS wohl noch ein paar Features für Oracas aufheben. Für alle, die zurzeit mit VS2005 + WPF-Extensions arbeiten, bleibt leider nur der oben genannte Workaround.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-6593163540626246938?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://headwriteline.blogspot.com/2007/02/pimp-my-elementhost.html' title='Pimp my ElementHost!'/><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/6593163540626246938/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=6593163540626246938' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/6593163540626246938'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/6593163540626246938'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2007/02/pimp-my-elementhost.html' title='Pimp my ElementHost!'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_11VTbOPwP_U/RcHtWhOFw-I/AAAAAAAAAAM/7nW-5YBbIn4/s72-c/ElementHost+in+VS2005.bmp' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-116798019720425386</id><published>2007-01-05T07:51:00.000+01:00</published><updated>2007-01-05T07:57:49.703+01:00</updated><title type='text'>Neue Tools für WPF und WPF/E</title><content type='html'>&lt;ul&gt;&lt;li&gt;&lt;a href="http://blogs.msdn.com/llobo/default.aspx"&gt;Lester&lt;/a&gt; hat mit &lt;a href="http://blogs.msdn.com/llobo/archive/2006/12/30/xamlpadx-v2.aspx"&gt;XamlPadX v2&lt;/a&gt; ein erweitertes XAML Pad gebaut, dass einige nette Features bietet.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.leastprivilege.com"&gt;Dominick&lt;/a&gt; hat mich auf &lt;a href="http://wpfwonderland.wordpress.com/2007/01/02/wpf-tools-stylesnooper"&gt;StyleSnooper&lt;/a&gt; aufmerksam gemacht, welches die Styles sämtlicher in WPF enthaltener Controls anzeigt.&lt;/li&gt;&lt;li&gt;Aber wirklich cool ist &lt;strong&gt;WPF/E Pad&lt;/strong&gt; von &lt;a href="http://blogs.msdn.com/mharsh/default.aspx"&gt;Mike Harsh&lt;/a&gt;. Mehr Infos &lt;a href="http://blogs.msdn.com/mharsh/archive/2006/12/22/wpf-e-pad.aspx"&gt;hier&lt;/a&gt; und &lt;a href="http://blogs.msdn.com/mharsh/archive/2006/12/28/updated-version-of-wpf-e-pad.aspx"&gt;hier&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-116798019720425386?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://headwriteline.blogspot.com/2007/01/neue-tools-fr-wpf-und-wpfe.html' title='Neue Tools für WPF und WPF/E'/><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/116798019720425386/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=116798019720425386' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/116798019720425386'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/116798019720425386'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2007/01/neue-tools-fr-wpf-und-wpfe.html' title='Neue Tools für WPF und WPF/E'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-116654057493422964</id><published>2006-12-19T15:55:00.000+01:00</published><updated>2006-12-19T16:03:13.596+01:00</updated><title type='text'>Kaxaml rockt!</title><content type='html'>&lt;a href="http://www.notstatic.com"&gt;Robby Ingebretsen&lt;/a&gt; hat mit &lt;strong&gt;Kaxaml&lt;/strong&gt; einen wirklich guten XAML-Editor gebaut. Die aktuelle Version 0.2 enthält Features wie &lt;strong&gt;Auto tag completion&lt;/strong&gt;, &lt;strong&gt;XAML Snippets&lt;/strong&gt;, einen &lt;strong&gt;Color Picker&lt;/strong&gt;, &lt;strong&gt;Find &amp;amp; Replace&lt;/strong&gt;, sowie eine &lt;strong&gt;Undo&lt;/strong&gt;-Funktion. Ein Muß für jeden XAML Pad-Benutzer!&lt;br /&gt;&lt;br /&gt;Nähere Infos &lt;a href="http://notstatic.com/archives/64"&gt;hier&lt;/a&gt;, Download &lt;a href="http://www.notstatic.com/kaxaml/Kaxaml_0.2.msi"&gt;hier&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-116654057493422964?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://headwriteline.blogspot.com/2006/12/kaxaml-rockt.html' title='Kaxaml rockt!'/><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/116654057493422964/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=116654057493422964' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/116654057493422964'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/116654057493422964'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2006/12/kaxaml-rockt.html' title='Kaxaml rockt!'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-116645310601748853</id><published>2006-12-18T15:43:00.000+01:00</published><updated>2006-12-18T15:45:46.680+01:00</updated><title type='text'>Artikel in der aktuellen dotnetpro</title><content type='html'>In der aktuellen Ausgabe der &lt;a href="http://www.dotnetpro.de"&gt;dotnetpro&lt;/a&gt; (01/2007) ist mein Artikel „&lt;strong&gt;Neue Klassen, optimierte Verfahren: .NET 2.0: Neuerungen für Komponentenentwickler&lt;/strong&gt;“ erschienen.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Auszug aus dem Abstract:&lt;br /&gt;&lt;/strong&gt;Bei der Fülle neuer Features im .NET Framework 2.0 sind einige Neuerungen fast unbemerkt geblieben. Doch gerade im Windows.Forms-Namespace haben sich teilweise tiefgreifende Änderungen vollzogen, von denen insbesondere Komponentenentwickler profitieren können. Jörg Neumann stellt die wichtigsten Änderungen vor und zeigt welche Vorteile die neuen Konzepte haben.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-116645310601748853?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://headwriteline.blogspot.com/2006/12/artikel-in-der-aktuellen-dotnetpro.html' title='Artikel in der aktuellen dotnetpro'/><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/116645310601748853/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=116645310601748853' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/116645310601748853'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/116645310601748853'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2006/12/artikel-in-der-aktuellen-dotnetpro.html' title='Artikel in der aktuellen dotnetpro'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25127186.post-116636006817144994</id><published>2006-12-17T13:38:00.000+01:00</published><updated>2006-12-17T13:55:42.210+01:00</updated><title type='text'>WPF/E: Limitationen bei Event Triggern</title><content type='html'>In WPF/E werden zum Animieren von Elementen - ebenso wie in WPF - &lt;strong&gt;Event Trigger&lt;/strong&gt; verwendet. Diese reagieren bei bestimmten Ereignissen und führen daraufhin entsprechende Animationslogik aus.&lt;br /&gt;&lt;br /&gt;Die aktuelle CTP unterstützt jedoch nur das &lt;strong&gt;Loaded&lt;/strong&gt;-Event, was die Möglichkeiten deutlich einschränkt. Wenn Sie beispielsweise eine Animation starten wollen, wenn der Benutzer auf ein Element klickt, so können Sie diese zwar per Java Script starten, sie wird jedoch beim initialen Laden der Seite bereits ausgeführt.&lt;br /&gt;&lt;br /&gt;Ein Workaround besteht darin, die Animation dynamisch hinzuzfügen. Hierbei deklarieren Sie den Event Trigger nicht in Ihrer XAML-Datei, sondern erzeugen ihn zur Laufzeit per Java Script.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;var xaml = "&amp;lt;EventTrigger&amp;gt;";&lt;br /&gt;xaml = xaml + " &amp;lt;EventTrigger.Actions&amp;gt;";&lt;br /&gt;xaml = xaml + " &amp;lt;BeginStoryboard&amp;gt;";&lt;br /&gt;xaml = xaml + " &amp;lt;Storyboard x:Name='imageAnimation'&amp;gt;";&lt;br /&gt;xaml = xaml + " &amp;lt;DoubleAnimation ...";&lt;br /&gt;xaml = xaml + " ...";&lt;br /&gt;xaml = xaml + " &amp;lt;/Storyboard&amp;gt;";&lt;br /&gt;xaml = xaml + " &amp;lt;/BeginStoryboard&amp;gt;";&lt;br /&gt;xaml = xaml + " &amp;lt;/EventTrigger.Actions&amp;gt;";&lt;br /&gt;xaml = xaml + "&amp;lt;/EventTrigger&amp;gt;";&lt;br /&gt;&lt;br /&gt;var wpfeControl = document.getElementById("wpfeControl1");&lt;br /&gt;var canvas = wpfeControl.findName("rootCanvas");&lt;br /&gt;var trigger = wpfeControl.&lt;strong&gt;createFromXaml&lt;/strong&gt;(xaml);&lt;br /&gt;canvas.&lt;strong&gt;Children.Add&lt;/strong&gt;(trigger);&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Bleibt zu hoffen, dass dieser Workaround zur finalen Version überflüssig wird.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25127186-116636006817144994?l=headwriteline.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://headwriteline.blogspot.com/2006/12/wpfe-limitationen-bei-event-triggern.html' title='WPF/E: Limitationen bei Event Triggern'/><link rel='replies' type='application/atom+xml' href='http://headwriteline.blogspot.com/feeds/116636006817144994/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25127186&amp;postID=116636006817144994' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/116636006817144994'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25127186/posts/default/116636006817144994'/><link rel='alternate' type='text/html' href='http://headwriteline.blogspot.com/2006/12/wpfe-limitationen-bei-event-triggern.html' title='WPF/E: Limitationen bei Event Triggern'/><author><name>Jörg Neumann</name><uri>http://www.blogger.com/profile/03421917575329764772</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://2.bp.blogspot.com/_11VTbOPwP_U/SoUkMYC12dI/AAAAAAAAAME/fLSIETtTkVI/S220/jone_130x160.jpg'/></author><thr:total>0</thr:total></entry></feed>
