<?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:blogger='http://schemas.google.com/blogger/2008' 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-2559668977390861004</id><updated>2026-09-25T08:46:52.096+01:00</updated><category term="Development"/><category term="C#"/><category term="WPF"/><category term=".Net"/><category term="WP7"/><category term="MVVM"/><category term="Rx"/><category term="WP7Contrib"/><category term="CodePlex"/><category term="WP7 WP7Contrib CodePlex"/><category term="testing"/><category term="Performance"/><category term="UI"/><category term="Developement"/><category term="Diagnostics"/><category term="F#"/><category term="TDD"/><category term="javascript"/><category term="Async"/><category term="Azure"/><category term="Caching"/><category term="Reactive Extensions"/><category term="WP7Dev"/><category term=".Net 5.0"/><category term=".Net 6.0"/><category term="AOP"/><category term="ASP.NET 5.0"/><category term="Advertising"/><category term="Bing Maps"/><category term="Coding"/><category term="Coding Building CI Testing"/><category term="Coding C#"/><category term="CultureInfo"/><category term="DDD"/><category term="Disposable"/><category term="FINDaPAD"/><category term="ORM"/><category term="RESTful"/><category term="SignalR"/><category term="Silverlight"/><category term="TPL"/><category term="WP7 Bing Maps Development UK Crime"/><category term="WP7 Bing Maps Development UK Polygons Clustering Performance"/><category term="WP7 WP7Contrib Phone Maps"/><category term="WP7 WP7Contrib SilverlightSerializer C#"/><category term="WebAPI"/><category term="XAML"/><category term="continuous testing"/><category term="jasmine"/><category term=".Net 4.5"/><category term=".Net 7.0"/><category term="Abstractions"/><category term="Agile"/><category term="Agile Courage"/><category term="AuthorizationHandler"/><category term="AutoFac"/><category term="Azure IIS RESTful development"/><category term="BDD"/><category term="Benchmark"/><category term="Bounded Context"/><category term="C# 5.0"/><category term="C# 6.0"/><category term="CLoud"/><category term="Chocolatey"/><category term="Coding Functional-Programming"/><category term="Coding REST Knowledge"/><category term="Coding Services"/><category term="Coding TDD Refactoring Agile"/><category term="Command"/><category term="DAL"/><category term="DDD Coaching"/><category term="DDD Domain Events Auditing nHibernate"/><category term="DDD Entities Value Objects"/><category term="Debugging"/><category term="Design Patterns"/><category term="Design Patterns Databases Auditing"/><category term="Development Coding"/><category term="Development Process"/><category term="Development VS 2011"/><category term="Development unit testing"/><category term="EventAggregator"/><category term="Exceptions"/><category term="FindaPad Property Rental Windows Phone 7 Mobile Devices"/><category term="Fun Coding Duct-Tape"/><category term="Goto"/><category term="Hotfixes"/><category term="Interop"/><category term="IoC"/><category term="Jobs Development"/><category term="LINQ"/><category term="MSDN Coding"/><category term="MSpec"/><category term="MVC"/><category term="Mobile Devices"/><category term="Mocking"/><category term="ModuleLoader"/><category term="Multilingual"/><category term="NoSQL RavenDB Azure Development"/><category term="Nokia"/><category term="OO"/><category term="Observations"/><category term="Office"/><category term="Outlook"/><category term="Permissions"/><category term="Portable Class Library"/><category term="Portable Library"/><category term="PostSharp"/><category term="Process"/><category term="REST Distributed-Systems"/><category term="REST HTTP"/><category term="Rants"/><category term="RavenDB IIS 7.5 Development"/><category term="Reactive"/><category term="Reactive Extension"/><category term="ReadOnlyCollections"/><category term="Resharper"/><category term="SQL-Server"/><category term="Serialization"/><category term="Silverlight Installation"/><category term="Simplicity"/><category term="SqlDependency"/><category term="TDD IoC DI"/><category term="TDD Mocking"/><category term="TDD Team Observation"/><category term="Task"/><category term="Telerik"/><category term="Themes"/><category term="Undo-Redo"/><category term="VS 2012"/><category term="ViewModels"/><category term="WP7 Bing Maps Development Network HTTP"/><category term="WP7 Bing Maps Development UK Crime Clustering"/><category term="WP7 Cultures C#"/><category term="WP7 Javascript web browser"/><category term="WP7 MSBuild"/><category term="WP7 ORM Databases performance"/><category term="WP7 Serialisation"/><category term="WP7 SilverlightSerializer C#"/><category term="WP7 WP7Contrib Bing Maps Development"/><category term="WP7 WP7Contrib Bing Maps Polygon Development"/><category term="WP7 WP7Contrib CodePlex Bing Maps Development"/><category term="WP7 WP7Contrib CodePlex ObservableCollection"/><category term="WP7 WP7Contrib ILMerge .Net"/><category term="WP7 cryptography bouncy castle"/><category term="WP7 feedback development app store"/><category term="WP7 sqlite performance development"/><category term="WP7Contrib  Bing Maps WP7"/><category term="WP7Contrib WP7 Geo-Location development C#"/><category term="WP7Contrib WP7 HTTP Compression"/><category term="WP7Contrib WP7 Url Development Rx"/><category term="WPF Cultures"/><category term="Web Services"/><category term="Windows"/><category term="Windows 8"/><category term="Windows Phone 7"/><category term="WuApi"/><category term="automated testing"/><category term="coding C# IoC StructureMap"/><category term="coupling"/><category term="databases"/><category term="html"/><category term="integration testing"/><category term="marketplace"/><category term="nCrunch"/><category term="nHbiernate Repository Pattern Criteria"/><category term="nHibernate Auditing Design Fluent"/><category term="nHibnerate Entities Events Listeners"/><category term="node.js"/><category term="nodes.js"/><category term="rest web"/><category term="slickGrid"/><category term="threading"/><category term="unit testing"/><category term="wcf"/><category term="web api"/><category term="web services mobile devices data"/><category term="windows phone"/><title type='text'>Awkward Coder</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://awkwardcoder.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://awkwardcoder.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default?start-index=26&amp;max-results=25&amp;redirect=false'/><author><name>awkwardcoder</name><uri>http://www.blogger.com/profile/09746266491429238639</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNCVrxgZI0ysSe04Lq2lyQfaYkLNVLBhLda8ryfijkXIytzt_8m2LpnVZqeEjyv3K_DkRQY6nUCjqVapwc3GZCzWZMa7snTHxSYXfBqPkTLMsdoMowuwzBMQbdlaYpwQ/s220/PXL_20210316_143926215.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>166</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-2559668977390861004.post-5730061835917809475</id><published>2023-11-08T17:43:00.002+00:00</published><updated>2023-11-08T17:44:43.091+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term=".Net 7.0"/><category scheme="http://www.blogger.com/atom/ns#" term="Interop"/><category scheme="http://www.blogger.com/atom/ns#" term="Office"/><category scheme="http://www.blogger.com/atom/ns#" term="Outlook"/><title type='text'>Outlook AdvanceSearch API not returning latest emails in the results</title><content type='html'>&lt;p&gt;Using Office Interop AdvanceSearch API method to query a Outlook folder isn&#39;t returning all the results, it&#39;s only returning results from 2 days ago!&lt;/p&gt;&lt;p&gt;&lt;i&gt;This code been running fine for over 2 years why is it failing now, and only failing on one machine?&lt;/i&gt;&lt;/p&gt;&lt;p&gt;Turnsout the it&#39;s a new machine after the last one died a couple of days ago, and this lead me to the answer - Indexes...&lt;/p&gt;&lt;p&gt;The indexes hadn&#39;t finished re-building from the last retore point, and if you use API before the Indexes are built you might not get all the results.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;If you dig into the Indexing Options it even tells you this, shame the API can&#39;t surface this warning.&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6xddJw5OxgoHDVVSH5mlt7zHSfl50CTr-smbV5jmrZ4Nj6FX0lkob-D47woThLvHWDHeNQ2AlqUZsnJIrm5OL4GTn1IcfCy00j2WtiQP3QtFc1EKeN-OiuTMOk3uq7cehcS9nzLTt98BFhtM_T7EkvziSmmGo2yZVsOVhWW_hRs6bzizAjgoxvRtWNbhG/s541/10.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;541&quot; data-original-width=&quot;491&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6xddJw5OxgoHDVVSH5mlt7zHSfl50CTr-smbV5jmrZ4Nj6FX0lkob-D47woThLvHWDHeNQ2AlqUZsnJIrm5OL4GTn1IcfCy00j2WtiQP3QtFc1EKeN-OiuTMOk3uq7cehcS9nzLTt98BFhtM_T7EkvziSmmGo2yZVsOVhWW_hRs6bzizAjgoxvRtWNbhG/s16000/10.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/p&gt;&lt;p&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/p&gt;&lt;p&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://awkwardcoder.blogspot.com/feeds/5730061835917809475/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://awkwardcoder.blogspot.com/2023/11/outlook-advancesearch-api-not-returning.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/5730061835917809475'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/5730061835917809475'/><link rel='alternate' type='text/html' href='http://awkwardcoder.blogspot.com/2023/11/outlook-advancesearch-api-not-returning.html' title='Outlook AdvanceSearch API not returning latest emails in the results'/><author><name>awkwardcoder</name><uri>http://www.blogger.com/profile/09746266491429238639</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNCVrxgZI0ysSe04Lq2lyQfaYkLNVLBhLda8ryfijkXIytzt_8m2LpnVZqeEjyv3K_DkRQY6nUCjqVapwc3GZCzWZMa7snTHxSYXfBqPkTLMsdoMowuwzBMQbdlaYpwQ/s220/PXL_20210316_143926215.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6xddJw5OxgoHDVVSH5mlt7zHSfl50CTr-smbV5jmrZ4Nj6FX0lkob-D47woThLvHWDHeNQ2AlqUZsnJIrm5OL4GTn1IcfCy00j2WtiQP3QtFc1EKeN-OiuTMOk3uq7cehcS9nzLTt98BFhtM_T7EkvziSmmGo2yZVsOVhWW_hRs6bzizAjgoxvRtWNbhG/s72-c/10.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2559668977390861004.post-3755157108998824412</id><published>2023-10-12T12:11:00.005+01:00</published><updated>2023-10-12T12:20:53.022+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term=".Net"/><category scheme="http://www.blogger.com/atom/ns#" term="Permissions"/><category scheme="http://www.blogger.com/atom/ns#" term="SQL-Server"/><category scheme="http://www.blogger.com/atom/ns#" term="SqlDependency"/><title type='text'>SqlDependency - getting the permissions working...</title><content type='html'>&lt;div style=&quot;text-align: left;&quot;&gt;&amp;nbsp;After much banging my head against the internet here is a&amp;nbsp;canonical example of how to configure SQL Server permissions, roles to get &lt;a href=&quot;https://learn.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqldependency?view=dotnet-plat-ext-7.0&amp;amp;viewFallbackFrom=net-7.0&quot;&gt;SqlDependency&lt;/a&gt; working in a .Net app.&lt;/div&gt;&lt;p style=&quot;text-align: left;&quot;&gt;This is for sceneario where the identity running the .Net code is running as a configured user account with the db_datareader &amp;amp; db_datawriter.&lt;/p&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: verdana;&quot;&gt;&lt;span style=&quot;color: #6aa84f;&quot;&gt;-- Create Schema User&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #2b00fe;&quot;&gt;CREATE USER sql_dependency_schema_owner WITHOUT LOGIN;&lt;br /&gt;GO&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: verdana;&quot;&gt;&lt;br /&gt;&lt;span style=&quot;color: #6aa84f;&quot;&gt;-- Create Schema for SqlDependency objects&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #2b00fe;&quot;&gt;CREATE SCHEMA sql_dependency AUTHORIZATION &lt;span&gt;sql_dependency_schema_owner;&lt;br /&gt;GO&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: verdana;&quot;&gt;&lt;br /&gt;&lt;span style=&quot;color: #6aa84f;&quot;&gt;-- Create Role for users of [sql_dependency]&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #2b00fe;&quot;&gt;CREATE ROLE sql_dependency_user;&lt;br /&gt;GO&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: verdana;&quot;&gt;&lt;br /&gt;&lt;span style=&quot;color: #6aa84f;&quot;&gt;-- Grant role permissions&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #2b00fe;&quot;&gt;GRANT CONTROL ON SCHEMA::sql_dependency TO sql_dependency_user;&lt;br /&gt;GRANT IMPERSONATE ON USER::sql_dependency_schema_owner TO sql_dependency_user;&lt;br /&gt;GRANT CREATE PROCEDURE TO sql_dependency_user;&lt;br /&gt;GRANT CREATE QUEUE TO sql_dependency_user;&lt;br /&gt;GRANT CREATE SERVICE TO sql_dependency_user;&lt;br /&gt;GRANT REFERENCES ON CONTRACT::[http://schemas.microsoft.com/SQL/Notifications/PostQueryNotification] TO sql_dependency_user;&lt;br /&gt;GRANT VIEW DEFINITION TO sql_dependency_user;&lt;br /&gt;GRANT SELECT to sql_dependency_user;&lt;br /&gt;GRANT SUBSCRIBE QUERY NOTIFICATIONS TO sql_dependency_user;&lt;br /&gt;GRANT RECEIVE ON QueryNotificationErrorsQueue TO sql_dependency_user;&lt;br /&gt;GO&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: verdana;&quot;&gt;&lt;br /&gt;&lt;span style=&quot;color: #6aa84f;&quot;&gt;-- Set [sql_dependency] as user default schema add to role, example user &#39;ollie&#39;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #2b00fe;&quot;&gt;ALTER USER&amp;nbsp;ollie&amp;nbsp;WITH DEFAULT_SCHEMA = sql_dependency;&lt;br /&gt;ALTER ROLE sql_dependency_user ADD MEMBER&amp;nbsp;ollie;&lt;br /&gt;GO&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://awkwardcoder.blogspot.com/feeds/3755157108998824412/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://awkwardcoder.blogspot.com/2023/10/sqldependency-getting-permissions.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/3755157108998824412'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/3755157108998824412'/><link rel='alternate' type='text/html' href='http://awkwardcoder.blogspot.com/2023/10/sqldependency-getting-permissions.html' title='SqlDependency - getting the permissions working...'/><author><name>awkwardcoder</name><uri>http://www.blogger.com/profile/09746266491429238639</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNCVrxgZI0ysSe04Lq2lyQfaYkLNVLBhLda8ryfijkXIytzt_8m2LpnVZqeEjyv3K_DkRQY6nUCjqVapwc3GZCzWZMa7snTHxSYXfBqPkTLMsdoMowuwzBMQbdlaYpwQ/s220/PXL_20210316_143926215.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2559668977390861004.post-5804484799106475244</id><published>2022-06-29T17:59:00.007+01:00</published><updated>2022-06-29T18:02:14.341+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term=".Net 6.0"/><category scheme="http://www.blogger.com/atom/ns#" term="ModuleLoader"/><category scheme="http://www.blogger.com/atom/ns#" term="Simplicity"/><category scheme="http://www.blogger.com/atom/ns#" term="WPF"/><title type='text'>Clean app startup (WPF)</title><content type='html'>&lt;p&gt;Simple easy to read code is the building blocks for complex applications, and to this end, the is how I now start all desktop apps (written in XAML / WPF). This is nothing new (and not original) but it&#39;s been refined &amp;amp; destilled down to a point of simpliclity :)&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjihJdpBvJyPdkiJUIoq_ZnXdr1Gv5XuFCv0kJ_C0cVslYVLzoN2lfyUqXtBmw0uSKfTwcwq0BbBDuprapknW2FQOZjyeO3Q1FgM5R6SahekcMwwTNplAb0YpixUIvU788-H3qHHqmWdtkJc0d8Ps-SSw9K73TqNGE28-IpSrgjhmxxh9D8VDe9MMhFPQ/s1095/app.cs.png&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;375&quot; data-original-width=&quot;1095&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjihJdpBvJyPdkiJUIoq_ZnXdr1Gv5XuFCv0kJ_C0cVslYVLzoN2lfyUqXtBmw0uSKfTwcwq0BbBDuprapknW2FQOZjyeO3Q1FgM5R6SahekcMwwTNplAb0YpixUIvU788-H3qHHqmWdtkJc0d8Ps-SSw9K73TqNGE28-IpSrgjhmxxh9D8VDe9MMhFPQ/s16000/app.cs.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Single line written once and forgotten about...&lt;/p&gt;&lt;p&gt;&lt;i&gt;Need to add Exception handling - write it in a Module...&lt;/i&gt;&lt;/p&gt;&lt;p&gt;&lt;i&gt;Need to add Heartbeat monitoring - write it in a Module...&lt;/i&gt;&lt;/p&gt;&lt;p&gt;&lt;i&gt;Using DI - do it in a Module...&lt;/i&gt;&lt;/p&gt;&lt;p&gt;&lt;i&gt;Startup XAML - guess what, done in a Module...&lt;/i&gt;&lt;/p&gt;&lt;p&gt;&lt;i&gt;Want only one instance of the app - do it in a Module...&lt;/i&gt;&lt;/p&gt;&lt;p&gt;So lifting from my updated Simple.Wpf.Template on &lt;a href=&quot;https://github.com/oriches/Simple.Wpf.Template&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;gitHub&lt;/a&gt;, I have the following set of Modules defined - this forms the basis for all apps I&#39;m asked to develop for clients:&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDOvIozyIAS9O7psWO2jA21ONvGvr3FMoO_Za_d3wnHVCoH0NARuZ6mO2q-OkHcPmqT0LgsE31YJQR4Hk_WQ2sbYkd7rrB9yc0he6zCmrVL73MOLlSqLxwsXca0DKRCZX1QAW8m6evo5LH5JYkzJoFRpeZJshi1KkJhnzMu1tsEnSv-jHlrOd_-EQjdw/s874/examples.modules.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;874&quot; data-original-width=&quot;675&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDOvIozyIAS9O7psWO2jA21ONvGvr3FMoO_Za_d3wnHVCoH0NARuZ6mO2q-OkHcPmqT0LgsE31YJQR4Hk_WQ2sbYkd7rrB9yc0he6zCmrVL73MOLlSqLxwsXca0DKRCZX1QAW8m6evo5LH5JYkzJoFRpeZJshi1KkJhnzMu1tsEnSv-jHlrOd_-EQjdw/s16000/examples.modules.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;The complexity is hidden away in the ModuleLoader class, simple put this scans &amp;amp; loads any type with the ModuleConfigurationAttribute, orders the Modules according to the properties of the Attribute and dynamically invokes the Modules.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Check out the code &lt;a href=&quot;https://github.com/oriches/Simple.Wpf.Template&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;...&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://awkwardcoder.blogspot.com/feeds/5804484799106475244/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://awkwardcoder.blogspot.com/2022/06/clean-app-startup-wpf.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/5804484799106475244'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/5804484799106475244'/><link rel='alternate' type='text/html' href='http://awkwardcoder.blogspot.com/2022/06/clean-app-startup-wpf.html' title='Clean app startup (WPF)'/><author><name>awkwardcoder</name><uri>http://www.blogger.com/profile/09746266491429238639</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNCVrxgZI0ysSe04Lq2lyQfaYkLNVLBhLda8ryfijkXIytzt_8m2LpnVZqeEjyv3K_DkRQY6nUCjqVapwc3GZCzWZMa7snTHxSYXfBqPkTLMsdoMowuwzBMQbdlaYpwQ/s220/PXL_20210316_143926215.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjihJdpBvJyPdkiJUIoq_ZnXdr1Gv5XuFCv0kJ_C0cVslYVLzoN2lfyUqXtBmw0uSKfTwcwq0BbBDuprapknW2FQOZjyeO3Q1FgM5R6SahekcMwwTNplAb0YpixUIvU788-H3qHHqmWdtkJc0d8Ps-SSw9K73TqNGE28-IpSrgjhmxxh9D8VDe9MMhFPQ/s72-c/app.cs.png" height="72" width="72"/><thr:total>0</thr:total><georss:featurename>Albion Rd, London N16 9PD, UK</georss:featurename><georss:point>51.5555305 -0.0838738</georss:point><georss:box>23.245296663821158 -35.2401238 79.865764336178842 35.0723762</georss:box></entry><entry><id>tag:blogger.com,1999:blog-2559668977390861004.post-2789572418680460701</id><published>2022-06-17T16:15:00.010+01:00</published><updated>2022-06-17T16:20:17.247+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term=".Net 6.0"/><category scheme="http://www.blogger.com/atom/ns#" term="Benchmark"/><category scheme="http://www.blogger.com/atom/ns#" term="C#"/><category scheme="http://www.blogger.com/atom/ns#" term="Performance"/><title type='text'>Benchmarking DateTime.ToString(&quot;...&quot;)</title><content type='html'>&lt;p&gt;
  Looking to eek-out as much perf as I can from some code (C#) at work, and looking at all the .ToString() manipulations in the code and I came across the following:&lt;/p&gt;
&lt;p&gt;
  &lt;span style=&quot;font-family: Roboto Mono;&quot;&gt;&lt;script src=&quot;https://gist.github.com/oriches/25c738d683bf0d07ddf53dd4a7c194f8.js&quot;&gt;&lt;/script&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;&lt;i&gt;How can I quickly workout if I want to do something around this?&lt;/i&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://benchmarkdotnet.org/articles/overview.html&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;BenchmarkDotNet&lt;/a&gt; to the rescue, and this library really does make benchmarking easy (and fun!). I created an overload of the extension method which internally uses a cache to avoid the repeative ToString() calls:&lt;/p&gt;
&lt;p&gt;
  &lt;span style=&quot;font-family: Roboto Mono;&quot;&gt;&lt;script src=&quot;https://gist.github.com/oriches/9ab1d9b2bd98f3e00cfe65f38b1a60c6.js&quot;&gt;&lt;/script&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
  Only small issue was wanting to test a Static methods, and this only involved creating a wrapper class with annotated methods(calling the static implementations), also preloaded the internal cache:
&lt;/p&gt;
&lt;p&gt;
  &lt;span style=&quot;font-family: Roboto Mono;&quot;&gt;&lt;script src=&quot;https://gist.github.com/oriches/f484f40f6aebb5cf3c720323464a4c2f.js&quot;&gt;&lt;/script&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;Results below, make-of-it what you will...&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9tkTwx9RUVGk_Hxrgg5F9-psCKPkv_IIt9KsuCPmCm1b7Nijm-93Hh1gmOHtgyNLTQ8vvPOe8ZltHedGi9RMZL6UlWNlBYLjAZzJB3Me-JOzrxIehnMH2Pp06P0K4xs38AwzMQIdQi2erHD8KThimdoW3bOAaobg8WiW4hqHuJg_xabOUhiOsNGT73g/s1832/datetime_benchmarknet.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1145&quot; data-original-width=&quot;1832&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9tkTwx9RUVGk_Hxrgg5F9-psCKPkv_IIt9KsuCPmCm1b7Nijm-93Hh1gmOHtgyNLTQ8vvPOe8ZltHedGi9RMZL6UlWNlBYLjAZzJB3Me-JOzrxIehnMH2Pp06P0K4xs38AwzMQIdQi2erHD8KThimdoW3bOAaobg8WiW4hqHuJg_xabOUhiOsNGT73g/s16000/datetime_benchmarknet.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://awkwardcoder.blogspot.com/feeds/2789572418680460701/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://awkwardcoder.blogspot.com/2022/06/benchmarking-datetimetostring.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/2789572418680460701'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/2789572418680460701'/><link rel='alternate' type='text/html' href='http://awkwardcoder.blogspot.com/2022/06/benchmarking-datetimetostring.html' title='Benchmarking DateTime.ToString(&quot;...&quot;)'/><author><name>awkwardcoder</name><uri>http://www.blogger.com/profile/09746266491429238639</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNCVrxgZI0ysSe04Lq2lyQfaYkLNVLBhLda8ryfijkXIytzt_8m2LpnVZqeEjyv3K_DkRQY6nUCjqVapwc3GZCzWZMa7snTHxSYXfBqPkTLMsdoMowuwzBMQbdlaYpwQ/s220/PXL_20210316_143926215.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9tkTwx9RUVGk_Hxrgg5F9-psCKPkv_IIt9KsuCPmCm1b7Nijm-93Hh1gmOHtgyNLTQ8vvPOe8ZltHedGi9RMZL6UlWNlBYLjAZzJB3Me-JOzrxIehnMH2Pp06P0K4xs38AwzMQIdQi2erHD8KThimdoW3bOAaobg8WiW4hqHuJg_xabOUhiOsNGT73g/s72-c/datetime_benchmarknet.png" height="72" width="72"/><thr:total>0</thr:total><georss:featurename>Albion Rd, London N16 9PD, UK</georss:featurename><georss:point>51.5555305 -0.0838738</georss:point><georss:box>23.245296663821158 -35.2401238 79.865764336178842 35.0723762</georss:box></entry><entry><id>tag:blogger.com,1999:blog-2559668977390861004.post-5376612655516784067</id><published>2022-06-13T15:40:00.006+01:00</published><updated>2022-06-13T15:53:30.735+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="C# 6.0"/><category scheme="http://www.blogger.com/atom/ns#" term="EventAggregator"/><category scheme="http://www.blogger.com/atom/ns#" term="Goto"/><category scheme="http://www.blogger.com/atom/ns#" term="UI"/><title type='text'>Rx EventAggregator&amp;#60;T&amp;#62; for desktop apps</title><content type='html'>&lt;p&gt;In my continuing (point-less) mission to avoid using anything related to MS Prism - a quick implementation of an EventAggregator&amp;nbsp;using Rx - took about 5 minutes to write for a problem I currently have, normally try and avoid using such a pattern as it can lead the scattering of business logic which can hard to &#39;follow&#39; when refactoring / re-visting code.&lt;/p&gt;
&lt;p&gt;
  Trying to kepp the interace as simple and obvious as possible (symetric design) - this will be injected by the container:&lt;/p&gt;
&lt;p&gt;
  &lt;span style=&quot;font-family: Roboto Mono;&quot;&gt;&lt;script src=&quot;https://gist.github.com/oriches/c7f9d835d6862d779f3b5b7680ede445.js&quot;&gt;&lt;/script&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
  Simple base event class, not thing special at the moment, might add a timestamp in the future, but more likely to do that with Rx on the event stream using the apply named Timestamp method:
&lt;/p&gt;
&lt;p&gt;
  &lt;span style=&quot;font-family: Roboto Mono;&quot;&gt;&lt;script src=&quot;https://gist.github.com/oriches/4969a018394baa4bb534d07a4a2f4dbb.js&quot;&gt;&lt;/script&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
  Included a simplifed Schedulers wrapper - idea being you can get any of the Rx Schedulers in one place, and importantly makes unit testing easier:
&lt;/p&gt;
&lt;p&gt;
&lt;span style=&quot;font-family: Roboto Mono;&quot;&gt;&lt;script src=&quot;https://gist.github.com/oriches/faef730bbf7b8321aaa10452578cbd93.js&quot;&gt;&lt;/script&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
  Show me the money...
&lt;/p&gt;
&lt;p&gt;
  &lt;span style=&quot;font-family: Roboto Mono;&quot;&gt;&lt;script src=&quot;https://gist.github.com/oriches/c29ec60b3ddd36b2b0d0169552b8ecd8.js&quot;&gt;&lt;/script&gt;&lt;/span&gt;
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://awkwardcoder.blogspot.com/feeds/5376612655516784067/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://awkwardcoder.blogspot.com/2022/06/reactive-eventaggregator-for-desktop.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/5376612655516784067'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/5376612655516784067'/><link rel='alternate' type='text/html' href='http://awkwardcoder.blogspot.com/2022/06/reactive-eventaggregator-for-desktop.html' title='Rx EventAggregator&amp;#60;T&amp;#62; for desktop apps'/><author><name>awkwardcoder</name><uri>http://www.blogger.com/profile/09746266491429238639</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNCVrxgZI0ysSe04Lq2lyQfaYkLNVLBhLda8ryfijkXIytzt_8m2LpnVZqeEjyv3K_DkRQY6nUCjqVapwc3GZCzWZMa7snTHxSYXfBqPkTLMsdoMowuwzBMQbdlaYpwQ/s220/PXL_20210316_143926215.jpg'/></author><thr:total>0</thr:total><georss:featurename>Albion Rd, London N16 9PD, UK</georss:featurename><georss:point>51.5555305 -0.0838738</georss:point><georss:box>23.245296663821158 -35.2401238 79.865764336178842 35.0723762</georss:box></entry><entry><id>tag:blogger.com,1999:blog-2559668977390861004.post-5702848432286642086</id><published>2021-09-20T10:34:00.000+01:00</published><updated>2021-09-20T10:34:06.314+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Diagnostics"/><category scheme="http://www.blogger.com/atom/ns#" term="html"/><category scheme="http://www.blogger.com/atom/ns#" term="javascript"/><category scheme="http://www.blogger.com/atom/ns#" term="slickGrid"/><title type='text'>Getting the last column to fit to available space in slickGrid</title><content type='html'>&lt;div&gt;I wanted a quick diagnostics page in html / js and this included grid to show server logs, decided to use &lt;a href=&quot;https://slickgrid.net/Index.html&quot; target=&quot;_blank&quot;&gt;slickGrid&lt;/a&gt;. All pretty easy to use apart from one thing - last column to fill remaining space...&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Nothing in their examples, so here&#39;s one for posterity...&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Not sure if it&#39;s the preferred way, but it works - the most obivous issue for is doing a DOM search to get the Viewport element - this is tightly coupled to the current latest release.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Stuck the implmentation in a Class and not provided any logic for creating Data, Columns or other grid optnios / plugins - tried to keep it simple...&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;script src=&quot;https://gist.github.com/oriches/5c6b83889c52d5df18e4e7451ff6976e.js&quot;&gt;&lt;/script&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://awkwardcoder.blogspot.com/feeds/5702848432286642086/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://awkwardcoder.blogspot.com/2021/09/getting-last-column-to-fit-to-available.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/5702848432286642086'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/5702848432286642086'/><link rel='alternate' type='text/html' href='http://awkwardcoder.blogspot.com/2021/09/getting-last-column-to-fit-to-available.html' title='Getting the last column to fit to available space in slickGrid'/><author><name>awkwardcoder</name><uri>http://www.blogger.com/profile/09746266491429238639</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNCVrxgZI0ysSe04Lq2lyQfaYkLNVLBhLda8ryfijkXIytzt_8m2LpnVZqeEjyv3K_DkRQY6nUCjqVapwc3GZCzWZMa7snTHxSYXfBqPkTLMsdoMowuwzBMQbdlaYpwQ/s220/PXL_20210316_143926215.jpg'/></author><thr:total>0</thr:total><georss:featurename>Hackney, London, UK</georss:featurename><georss:point>51.5436387 -0.0553621</georss:point><georss:box>23.233402815197582 -35.211614782209018 79.853874584802426 35.100890582209011</georss:box></entry><entry><id>tag:blogger.com,1999:blog-2559668977390861004.post-8205213838197301437</id><published>2021-08-06T14:01:00.004+01:00</published><updated>2021-08-06T14:15:30.928+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term=".Net 5.0"/><category scheme="http://www.blogger.com/atom/ns#" term="ASP.NET 5.0"/><category scheme="http://www.blogger.com/atom/ns#" term="AuthorizationHandler"/><category scheme="http://www.blogger.com/atom/ns#" term="SignalR"/><title type='text'>Custom AuthorizationHandler for SignalR Hubs</title><content type='html'>&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Roboto Mono;&quot;&gt;How to implement IAuthorizationRequirement for SignalR in Asp.Net Core v5.0&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;&lt;span style=&quot;font-family: Roboto Mono;&quot;&gt;Been battling this for a couple of days, and eventually ended up raising an issue on &lt;a href=&quot;https://github.com/dotnet/aspnetcore/issues/35099&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;Asp.Net Core gitHub&lt;/a&gt;&amp;nbsp;to find the answer.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: Roboto Mono;&quot;&gt;Wanting to do some custom authorization on a SignalR Hub when the client makes a connection (Hub is created) and when an endpoint (Hub method) is called:&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;font-family: Roboto Mono;&quot;&gt;&lt;script src=&quot;https://gist.github.com/oriches/5d5aba92491278da713d8faed770b5b6.js&quot;&gt;&lt;/script&gt;
&lt;/span&gt;&lt;p&gt;&lt;span style=&quot;font-family: Roboto Mono;&quot;&gt;I was assuming I could use the same Policy for both class &amp;amp; method attributes, but it ain&#39;t so - not because you can&#39;t, because you need the signatures to be different.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: Roboto Mono;&quot;&gt;Method implementation has a resource type of HubInnovationContext:&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;font-family: Roboto Mono;&quot;&gt;&lt;script src=&quot;https://gist.github.com/oriches/b684eccc9485e3367e47b2eae01c2f22.js&quot;&gt;&lt;/script&gt;&lt;/span&gt;&lt;p&gt;&lt;span style=&quot;font-family: Roboto Mono;&quot;&gt;I assumed class implementation would have a resource type of HubConnectionContext - client connects etc... This isn&#39;t the case, it&#39;s infact of type &lt;a href=&quot;https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.http.defaulthttpcontext?view=aspnetcore-5.0&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;DefaultHttpContext&lt;/a&gt;. For me I don&#39;t even need that, it can be removed completely&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Roboto Mono&amp;quot;;&quot;&gt;from the inheritence signature and override implementation.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: &amp;quot;Roboto Mono&amp;quot;;&quot;&gt;&lt;script src=&quot;https://gist.github.com/oriches/6a300a2927d361bdb87cf204b2c9b956.js&quot;&gt;&lt;/script&gt;Only other thing to note, and this could be a biggy, is the ordering of the statements in the Startup class:&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: &amp;quot;Roboto Mono&amp;quot;;&quot;&gt;&lt;script src=&quot;https://gist.github.com/oriches/cefc8bef4fe442e304d4767632f62cf7.js&quot;&gt;&lt;/script&gt;&lt;/span&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://awkwardcoder.blogspot.com/feeds/8205213838197301437/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://awkwardcoder.blogspot.com/2021/08/custom-authorizationhandler-for-signalr.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/8205213838197301437'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/8205213838197301437'/><link rel='alternate' type='text/html' href='http://awkwardcoder.blogspot.com/2021/08/custom-authorizationhandler-for-signalr.html' title='Custom AuthorizationHandler for SignalR Hubs'/><author><name>awkwardcoder</name><uri>http://www.blogger.com/profile/09746266491429238639</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNCVrxgZI0ysSe04Lq2lyQfaYkLNVLBhLda8ryfijkXIytzt_8m2LpnVZqeEjyv3K_DkRQY6nUCjqVapwc3GZCzWZMa7snTHxSYXfBqPkTLMsdoMowuwzBMQbdlaYpwQ/s220/PXL_20210316_143926215.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2559668977390861004.post-1815244903831239561</id><published>2021-07-09T13:16:00.006+01:00</published><updated>2021-08-06T14:15:53.956+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term=".Net 5.0"/><category scheme="http://www.blogger.com/atom/ns#" term="ASP.NET 5.0"/><category scheme="http://www.blogger.com/atom/ns#" term="AutoFac"/><category scheme="http://www.blogger.com/atom/ns#" term="SignalR"/><title type='text'>AutoFac for SignalR using ASP.NET Core version 5.0</title><content type='html'>&lt;p style=&quot;text-align: left;&quot;&gt;Putting this here, so it might help someone else in the future!&lt;/p&gt;&lt;p style=&quot;text-align: left;&quot;&gt;Couldn&#39;t find an example for version 5 of ASP.NET Core - the number of breaking changes in ASP.NET Core is incredible, and a big negative for the framework when looking to integrate 3rd party services such as logging &amp;amp; IOC.&lt;/p&gt;&lt;p style=&quot;text-align: left;&quot;&gt;Steps:&lt;/p&gt;&lt;p style=&quot;text-align: left;&quot;&gt;&lt;b&gt;1. Add nuGet packages:&lt;/b&gt;&lt;/p&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Autofac&lt;br /&gt;Autofac.Extensions.DependencyInjection&lt;/div&gt;&lt;p style=&quot;text-align: left;&quot;&gt;&lt;b&gt;2. Update Program.cs file to add AutoFac Factory:&lt;/b&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left;&quot;&gt;Highlighted the import part in &lt;span style=&quot;color: red;&quot;&gt;Red&lt;/span&gt;:&lt;/p&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlICEMNSUXIS4DJs40QAXoUrZt4Yfy6k8cpfmS92svyNhWyoQeKwKKGaDru7XXkorkszXggfXJLphWIHAw5e7WDwiOF89yUMFIMAvYiqeLbNMst7j0hDJCtjT6z-MJRI0wY9GlrEuY0x7h/s1291/Program2.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;617&quot; data-original-width=&quot;1291&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlICEMNSUXIS4DJs40QAXoUrZt4Yfy6k8cpfmS92svyNhWyoQeKwKKGaDru7XXkorkszXggfXJLphWIHAw5e7WDwiOF89yUMFIMAvYiqeLbNMst7j0hDJCtjT6z-MJRI0wY9GlrEuY0x7h/s16000/Program2.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;p style=&quot;text-align: left;&quot;&gt;&lt;b&gt;3. Update Startup.cs file to add AutoFac container configuration:&lt;/b&gt;&lt;/p&gt;&lt;p style=&quot;text-align: left;&quot;&gt;Highlighted the import part in&amp;nbsp;&lt;span style=&quot;color: red;&quot;&gt;Red&lt;/span&gt;:&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDKZVwsf67DkFTnEfyD5U7l6iVymahfcNeEw6TcFwlTP-SbiTFrdf9hvLw4B2IK7QZlkKB7UW0QIK0piKi-NakZL2vir4YSclm7mD1PckEpyrRTg0YJslOmn3LjiixefZaVBjaIkWbCqXY/s1315/Program2.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1315&quot; data-original-width=&quot;1312&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDKZVwsf67DkFTnEfyD5U7l6iVymahfcNeEw6TcFwlTP-SbiTFrdf9hvLw4B2IK7QZlkKB7UW0QIK0piKi-NakZL2vir4YSclm7mD1PckEpyrRTg0YJslOmn3LjiixefZaVBjaIkWbCqXY/s16000/Program2.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;p style=&quot;text-align: left;&quot;&gt;IRegisterService &amp;amp; IRegisterHub are interfaces I created for easy registration with AutoFac.&lt;/p&gt;&lt;p style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://awkwardcoder.blogspot.com/feeds/1815244903831239561/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://awkwardcoder.blogspot.com/2021/07/autofac-for-signalr-using-aspnet-core.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/1815244903831239561'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/1815244903831239561'/><link rel='alternate' type='text/html' href='http://awkwardcoder.blogspot.com/2021/07/autofac-for-signalr-using-aspnet-core.html' title='AutoFac for SignalR using ASP.NET Core version 5.0'/><author><name>awkwardcoder</name><uri>http://www.blogger.com/profile/09746266491429238639</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNCVrxgZI0ysSe04Lq2lyQfaYkLNVLBhLda8ryfijkXIytzt_8m2LpnVZqeEjyv3K_DkRQY6nUCjqVapwc3GZCzWZMa7snTHxSYXfBqPkTLMsdoMowuwzBMQbdlaYpwQ/s220/PXL_20210316_143926215.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlICEMNSUXIS4DJs40QAXoUrZt4Yfy6k8cpfmS92svyNhWyoQeKwKKGaDru7XXkorkszXggfXJLphWIHAw5e7WDwiOF89yUMFIMAvYiqeLbNMst7j0hDJCtjT6z-MJRI0wY9GlrEuY0x7h/s72-c/Program2.png" height="72" width="72"/><thr:total>0</thr:total><georss:featurename>London, UK</georss:featurename><georss:point>51.5073509 -0.1277583</georss:point><georss:box>23.197115015197578 -35.284010982209011 79.817586784802415 35.028494382209018</georss:box></entry><entry><id>tag:blogger.com,1999:blog-2559668977390861004.post-6642588092833040426</id><published>2016-06-21T21:28:00.000+01:00</published><updated>2016-06-21T23:30:42.962+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term=".Net"/><category scheme="http://www.blogger.com/atom/ns#" term="C#"/><category scheme="http://www.blogger.com/atom/ns#" term="Development"/><category scheme="http://www.blogger.com/atom/ns#" term="Performance"/><category scheme="http://www.blogger.com/atom/ns#" term="WPF"/><title type='text'>WPF tips &amp; tricks: Dispatcher thread performance</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
Not blogged for an age, and I received an email last week which provoked me back to life. It was a job spec for a WPF contract where they want help sorting out the performance of their app especially around grids and tabular data.&lt;br /&gt;
&lt;br /&gt;
I thought I&#39;d shared some tips &amp;amp; tricks I&#39;ve picked up along the way, these aren&#39;t probably going to solve any issues you might be having directly, but they might point you in the right direction when trying to find and resolve performance issues with a WPF app.&lt;br /&gt;
&lt;br /&gt;
First off, performance is something you shouldn&#39;t try and improve without evidence, and this means having evidence proving you&#39;ve improved the performance - before &amp;amp; after metrics for example. Without this you&#39;re basically pissing into the wind, which can be fun from a developer point of view but bad for a project :)&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;So, what do I mean by &#39;&lt;i&gt;Dispatcher thread performance&lt;/i&gt;&#39;?&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
The &#39;dispatcher thread&#39; or the &#39;UI thread&#39; is &lt;strike&gt;probably&lt;/strike&gt; the most important thread in any WPF app, and making sure this is working efficiently should be one of the primary concerns of any WPF developer, if not you&#39;ll end up in a situation which has prompted me back to life.&lt;br /&gt;
&lt;br /&gt;
The code below doesn&#39;t improve efficiency, it allows you to observe when the dispatcher thread is overloaded with work, it has to much work to do in the time available, this manifests it&#39;s self as an application freezing &amp;amp; stalling for an end user - also known as &#39;&lt;i&gt;white screen of death&lt;/i&gt;&#39;.&lt;br /&gt;
&lt;!-- HTML generated using hilite.me --&gt;&lt;br /&gt;
&lt;div style=&quot;background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;&quot;&gt;
&lt;table&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;pre style=&quot;line-height: 125%; margin: 0;&quot;&gt; 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23&lt;/pre&gt;
&lt;/td&gt;&lt;td&gt;&lt;pre style=&quot;line-height: 125%; margin: 0;&quot;&gt;&lt;span style=&quot;color: #008800; font-weight: bold;&quot;&gt;private&lt;/span&gt; &lt;span style=&quot;color: #008800; font-weight: bold;&quot;&gt;static&lt;/span&gt; IDisposable &lt;span style=&quot;color: #0066bb; font-weight: bold;&quot;&gt;ObserveUiFreeze&lt;/span&gt;()
{
    &lt;span style=&quot;color: #333399; font-weight: bold;&quot;&gt;var&lt;/span&gt; timer = &lt;span style=&quot;color: #008800; font-weight: bold;&quot;&gt;new&lt;/span&gt; DispatcherTimer(DispatcherPriority.Normal)
    {
        Interval = TimeSpan.FromMilliseconds(&lt;span style=&quot;color: #6600ee; font-weight: bold;&quot;&gt;333&lt;/span&gt;)
    };

    &lt;span style=&quot;color: #333399; font-weight: bold;&quot;&gt;var&lt;/span&gt; previous = DateTime.Now;
    timer.Tick += (sender, args) =&amp;gt;
    {
        &lt;span style=&quot;color: #333399; font-weight: bold;&quot;&gt;var&lt;/span&gt; current = DateTime.Now;
        &lt;span style=&quot;color: #333399; font-weight: bold;&quot;&gt;var&lt;/span&gt; delta = current - previous;
        previous = current;

        &lt;span style=&quot;color: #008800; font-weight: bold;&quot;&gt;if&lt;/span&gt; (delta &amp;gt; TimeSpan.FromMilliseconds(&lt;span style=&quot;color: #6600ee; font-weight: bold;&quot;&gt;500&lt;/span&gt;))
        {
            Debug.WriteLine(&lt;span style=&quot;background-color: #fff0f0;&quot;&gt;&quot;UI Freeze = {0} ms&quot;&lt;/span&gt;, delta.TotalMilliseconds);
        }
    };

    timer.Start();
    &lt;span style=&quot;color: #008800; font-weight: bold;&quot;&gt;return&lt;/span&gt; Disposable.Create(timer.Stop);
}
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;b&gt;So, how does this code work?&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Very simply really, by using a dispatcher timer to tick every 333 ms, it will always fire every 333ms irrespective of anything else, but this doesn&#39;t mean the Tick handler will receive the event in a timely manner and this is the key point. If it doesn&#39;t receive the event in a timely manner it means the dispatcher thread is overloaded with work and can&#39;t refresh the UI quick enough. The Tick handler evaluates the delta between the current &amp;amp; previous times, and if this is greater than 500ms it will write out to console window (in VS or DebugView). &lt;br /&gt;
&lt;br /&gt;
Example output from VS is shown below, this is using the publicly available &lt;a href=&quot;https://github.com/oriches/Simple.MahApps.Template&quot; target=&quot;_blank&quot;&gt;WPF template&lt;/a&gt; project I use as a starting point for most apps. I&#39;ve highlighted the line of interest:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIJ5ILmGLdO9Pmj8S9G6D3-WukdtfBMIpfTVn_Z7PULcjwlMXrfHI60axOPYclN0nWM5ND_RacPvuIFtVu7SBAelQ-nQfk80G6qrcTosRAD2G3Nbwvz-Ne5CuEDJX_XYfJOJWlVkrnxZHh/s1600/wpf+t%2526t+01.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIJ5ILmGLdO9Pmj8S9G6D3-WukdtfBMIpfTVn_Z7PULcjwlMXrfHI60axOPYclN0nWM5ND_RacPvuIFtVu7SBAelQ-nQfk80G6qrcTosRAD2G3Nbwvz-Ne5CuEDJX_XYfJOJWlVkrnxZHh/s1600/wpf+t%2526t+01.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&amp;nbsp;The output was forced by placing a Thread.Sleep call in the Refresh button handler in the ViewModel:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjaW6HDhFpMSBBKQzOl7tOssGp1-DODEYjUlt1orSuZLhLN0bnOw_06vEAvRlwg7LvlpkGD6YiWHz54OUYfqrRKW0sGmTCRDuazha83aAdX22OBO-uJhnPS7OaVd_LMr3zHTVOvwNTC2NdN/s1600/wpf+t%2526t+02.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjaW6HDhFpMSBBKQzOl7tOssGp1-DODEYjUlt1orSuZLhLN0bnOw_06vEAvRlwg7LvlpkGD6YiWHz54OUYfqrRKW0sGmTCRDuazha83aAdX22OBO-uJhnPS7OaVd_LMr3zHTVOvwNTC2NdN/s1600/wpf+t%2526t+02.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Hopefully you now see this gives an easy way to diagnose problems with overloading the dispatcher thread.&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://awkwardcoder.blogspot.com/feeds/6642588092833040426/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://awkwardcoder.blogspot.com/2016/06/wpf-tips-tricks-dispatcher-thread.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/6642588092833040426'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/6642588092833040426'/><link rel='alternate' type='text/html' href='http://awkwardcoder.blogspot.com/2016/06/wpf-tips-tricks-dispatcher-thread.html' title='WPF tips &amp; tricks: Dispatcher thread performance'/><author><name>awkwardcoder</name><uri>http://www.blogger.com/profile/09746266491429238639</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNCVrxgZI0ysSe04Lq2lyQfaYkLNVLBhLda8ryfijkXIytzt_8m2LpnVZqeEjyv3K_DkRQY6nUCjqVapwc3GZCzWZMa7snTHxSYXfBqPkTLMsdoMowuwzBMQbdlaYpwQ/s220/PXL_20210316_143926215.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIJ5ILmGLdO9Pmj8S9G6D3-WukdtfBMIpfTVn_Z7PULcjwlMXrfHI60axOPYclN0nWM5ND_RacPvuIFtVu7SBAelQ-nQfk80G6qrcTosRAD2G3Nbwvz-Ne5CuEDJX_XYfJOJWlVkrnxZHh/s72-c/wpf+t%2526t+01.png" height="72" width="72"/><thr:total>0</thr:total><georss:featurename>London N16, UK</georss:featurename><georss:point>51.5623078 -0.076435299999957351</georss:point><georss:box>51.5228228 -0.15711629999995735 51.6017928 0.0042457000000426515</georss:box></entry><entry><id>tag:blogger.com,1999:blog-2559668977390861004.post-8689960741242723380</id><published>2015-04-28T21:24:00.002+01:00</published><updated>2015-04-28T21:24:44.275+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term=".Net"/><category scheme="http://www.blogger.com/atom/ns#" term="Development"/><category scheme="http://www.blogger.com/atom/ns#" term="WPF"/><title type='text'>WPF anti-pattern: Docking panels</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
Developers love docking panels (especially Windows developers), they love the ability to &#39;dock&#39; a panel to the left, top, right bottom of the window, and repeat this with windows inside windows inside windows ad infinitum...&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Shown below is the docking ability in Visual Studio - it works great because the target user has the required level of understanding of a complex app.&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQm_dZ43I47UnLCqAaq4StT3UK-TKupWMF6voD64L31ngxrDhfHUSzMXWD3VBEWfpfPKRy0HkUZ-q0feQlQ9nTkc_7KuITiKfXAUsQbhoRnPmFnIcU8XSCA9Z-oMjN9IkzG5iLZp3mJex9/s1600/dock+01.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQm_dZ43I47UnLCqAaq4StT3UK-TKupWMF6voD64L31ngxrDhfHUSzMXWD3VBEWfpfPKRy0HkUZ-q0feQlQ9nTkc_7KuITiKfXAUsQbhoRnPmFnIcU8XSCA9Z-oMjN9IkzG5iLZp3mJex9/s1600/dock+01.png&quot; height=&quot;360&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
The problem is the majority of users haven&#39;t got a clue about them...&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
When they accidentally drag a tab or window and the UI suddenly show docking points like the above screen shot they haven&#39;t got a clue what to do to get back to where they were. This coupled with the look on their faces makes me think the use of docking panels should be avoid in all but the most complicated apps - the average business line app developed using WPF doesn&#39;t really need a docking panel.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
I call the use of docking panels in general an anti-pattern :)&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://awkwardcoder.blogspot.com/feeds/8689960741242723380/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://awkwardcoder.blogspot.com/2015/04/wpf-anti-pattern-docking-panels.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/8689960741242723380'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/8689960741242723380'/><link rel='alternate' type='text/html' href='http://awkwardcoder.blogspot.com/2015/04/wpf-anti-pattern-docking-panels.html' title='WPF anti-pattern: Docking panels'/><author><name>awkwardcoder</name><uri>http://www.blogger.com/profile/09746266491429238639</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNCVrxgZI0ysSe04Lq2lyQfaYkLNVLBhLda8ryfijkXIytzt_8m2LpnVZqeEjyv3K_DkRQY6nUCjqVapwc3GZCzWZMa7snTHxSYXfBqPkTLMsdoMowuwzBMQbdlaYpwQ/s220/PXL_20210316_143926215.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQm_dZ43I47UnLCqAaq4StT3UK-TKupWMF6voD64L31ngxrDhfHUSzMXWD3VBEWfpfPKRy0HkUZ-q0feQlQ9nTkc_7KuITiKfXAUsQbhoRnPmFnIcU8XSCA9Z-oMjN9IkzG5iLZp3mJex9/s72-c/dock+01.png" height="72" width="72"/><thr:total>0</thr:total><georss:featurename>Stoke Newington, London N16 8EB, UK</georss:featurename><georss:point>51.556352399999987 -0.076537400000006528</georss:point><georss:box>51.555118399999991 -0.079058900000006524 51.557586399999984 -0.074015900000006532</georss:box></entry><entry><id>tag:blogger.com,1999:blog-2559668977390861004.post-7792095063871033394</id><published>2015-01-08T13:24:00.000+00:00</published><updated>2015-01-08T13:24:45.569+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term=".Net"/><category scheme="http://www.blogger.com/atom/ns#" term="C#"/><category scheme="http://www.blogger.com/atom/ns#" term="Development"/><category scheme="http://www.blogger.com/atom/ns#" term="WPF"/><title type='text'>Styling WPF buttons for Image Viewer</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
A quick post on styling the next &amp;amp; previous buttons for an Image Viewer written in WPF, I&#39;m using the &lt;a href=&quot;http://mahapps.com/&quot; target=&quot;_blank&quot;&gt;MahApps&lt;/a&gt; libraries to give the UI a modern look &amp;amp; feel - they are available as &lt;a href=&quot;https://www.nuget.org/packages?q=MahApps&quot; target=&quot;_blank&quot;&gt;nuget&lt;/a&gt; packages, I&#39;m using the core and resources packages.&lt;br /&gt;
&lt;br /&gt;
The initial version is very simple and hopefully the behaviour is obvious - the image flanked by a couple of buttons for moving to the next\previous image:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&amp;nbsp;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQqZ4_TQh95sgZnRSYQPsoniQjXHAphK-6Hd-0owUtHQEc8-A7eEarnbE3OVPxeoSBl5kNAwrYrmj_LKZEK8CXEWuyW-caGUCBSKBZ3FFmfNcQUeJDqIJMMtZw26id-hpnPak8ak6SG77x/s1600/image+viewer+01.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em; text-align: center;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQqZ4_TQh95sgZnRSYQPsoniQjXHAphK-6Hd-0owUtHQEc8-A7eEarnbE3OVPxeoSBl5kNAwrYrmj_LKZEK8CXEWuyW-caGUCBSKBZ3FFmfNcQUeJDqIJMMtZw26id-hpnPak8ak6SG77x/s1600/image+viewer+01.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
The XAML for this is very simple, using grid layout to achieve the alignment required, one thing to note is the Stretch characteristics of the Image control - the image ratio will be maintained as the app is resized. Also I&#39;m using the default (implicit) styling for the button controls, these come from the MahApps libraries:&lt;/div&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAwkPYC04E9JulWCwy8IHdYrI_m-Cc5s70YauAOBll3IxadJ3-yE8WPh1iNp6HQvosFp2bcXbyzL_HVOYTE0bAA0RwVgZwyY7NlWqXAwH8VmReEiVbJlsbzJVh1WtVRGpkvHj-u_j09FHU/s1600/image+viewer+02.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAwkPYC04E9JulWCwy8IHdYrI_m-Cc5s70YauAOBll3IxadJ3-yE8WPh1iNp6HQvosFp2bcXbyzL_HVOYTE0bAA0RwVgZwyY7NlWqXAwH8VmReEiVbJlsbzJVh1WtVRGpkvHj-u_j09FHU/s1600/image+viewer+02.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
The next iteration sees the &#39;&lt;i&gt;cleaning up&lt;/i&gt;&#39; of the actual UI elements - the removal of border from around all the controls and the applying of the flat button style to the next &amp;amp; previous buttons.&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
The other majors changes are the replacement of the &#39;next&#39; &amp;amp; &#39;previous&#39; text with a couple of icons implemented as Path embedded on a Canvas, and the moving of the buttons to on top of the image - this obviously is now not ideal because it&#39;s obscuring parts of the image:&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGnLd0IeNLDQ0rz0603PpkQLqZF5dyfG0CA2EtZ_Ss2HcfDHaKob7efKCTDl6U3kQBO8lxShaLkWoFoZMZwc_3bG-Yu0tEtrj2uCSYdQQhvWBe500_JY0x0b-p3ke4UonkdN8Vs8UUVmDf/s1600/image+viewer+03.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGnLd0IeNLDQ0rz0603PpkQLqZF5dyfG0CA2EtZ_Ss2HcfDHaKob7efKCTDl6U3kQBO8lxShaLkWoFoZMZwc_3bG-Yu0tEtrj2uCSYdQQhvWBe500_JY0x0b-p3ke4UonkdN8Vs8UUVmDf/s1600/image+viewer+03.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&amp;nbsp;The XAML has changed subtly, the Image now spans all the columns in the Grid and each Button content has been replaced with a styled VisualBrush:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDVKirICKi66ON71ovT9t6kK263qnCj7mRhEJwYHUgg_N53I_6m3sFQF8_ZK13e1g3bEM8uBnlAhejW4lVldssCMSVwDHCfe530rKP23cmgR2Cdk1ttG0gumlGJNjomaEO0n0l9fKpWqIb/s1600/image+viewer+04.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDVKirICKi66ON71ovT9t6kK263qnCj7mRhEJwYHUgg_N53I_6m3sFQF8_ZK13e1g3bEM8uBnlAhejW4lVldssCMSVwDHCfe530rKP23cmgR2Cdk1ttG0gumlGJNjomaEO0n0l9fKpWqIb/s1600/image+viewer+04.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
The Visual for the next button is defined as follows:&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUElIQxS8L2-ADwJrGf5o1q9Xd91Qk7HCaXxQMNDJpMMXHgcbbW1bWBJ21HKHFTdz6DzNmaLqghESKJ7PyjcTx1XaDg2iXi-kt87dDk1fUyvdvrEiwweZUj4GBW5NeVrPonfovShQozSme/s1600/image+viewer+08.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUElIQxS8L2-ADwJrGf5o1q9Xd91Qk7HCaXxQMNDJpMMXHgcbbW1bWBJ21HKHFTdz6DzNmaLqghESKJ7PyjcTx1XaDg2iXi-kt87dDk1fUyvdvrEiwweZUj4GBW5NeVrPonfovShQozSme/s1600/image+viewer+08.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
The final version isn&#39;t that different to the previous, the most obvious change is the use of Property Triggers to control the Opacity of the buttons - the buttons only become visible when the mouse is moved over there location, this means for the majority of the time the whole image will be visible and not obscured by the buttons.&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiS3qP0sNOMJRHpW-5xG0FpLzewl-n4DDJdwH8thP0fRFJpBRgLuxkMR9tEXQNRd9bNXIJ1anBjYmUitPNNX6N7YQf6c6MaVpHprUs-gDG_XQbk5EQ5lcKQzPj7FHtsNg5u-X27LSsT14f1/s1600/image+viewer+05.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiS3qP0sNOMJRHpW-5xG0FpLzewl-n4DDJdwH8thP0fRFJpBRgLuxkMR9tEXQNRd9bNXIJ1anBjYmUitPNNX6N7YQf6c6MaVpHprUs-gDG_XQbk5EQ5lcKQzPj7FHtsNg5u-X27LSsT14f1/s1600/image+viewer+05.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&amp;nbsp;The XAML is now simpler - mainly because the styling has been abstracted away into a separate style resource dictionary:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8QFrRlqYZlWxUFy-18TRt0UzhGw6iUdJfM08f2ukuHQv6faIgyTuqSxYrIDNddgLzhl5nTT-S39MDaRYU2kEBwiFhMu9-eINX9gnJhwrjDiOmHsu6BxkL6GKmDXiIgpJtB7PZti9Rine4/s1600/image+viewer+06.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8QFrRlqYZlWxUFy-18TRt0UzhGw6iUdJfM08f2ukuHQv6faIgyTuqSxYrIDNddgLzhl5nTT-S39MDaRYU2kEBwiFhMu9-eINX9gnJhwrjDiOmHsu6BxkL6GKmDXiIgpJtB7PZti9Rine4/s1600/image+viewer+06.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&amp;nbsp;The complexity (which isn&#39;t very complex really) is moved into the styling for the buttons:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsJCTafmT9RtYZx-B4EgfUdx25nda7C4fJWkaJPNKn0Vjdd5IdlFLoEtdPBqbPy-obkar_xr62KiNmQKtfVSm9ewi0BkG5X6mVOkKamPUxyInLxRtK_xJhuxUsAXKoERopTawwGc2xWggi/s1600/image+viewer+07.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsJCTafmT9RtYZx-B4EgfUdx25nda7C4fJWkaJPNKn0Vjdd5IdlFLoEtdPBqbPy-obkar_xr62KiNmQKtfVSm9ewi0BkG5X6mVOkKamPUxyInLxRtK_xJhuxUsAXKoERopTawwGc2xWggi/s1600/image+viewer+07.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://awkwardcoder.blogspot.com/feeds/7792095063871033394/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://awkwardcoder.blogspot.com/2015/01/styling-wpf-buttons-for-image-viewer.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/7792095063871033394'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/7792095063871033394'/><link rel='alternate' type='text/html' href='http://awkwardcoder.blogspot.com/2015/01/styling-wpf-buttons-for-image-viewer.html' title='Styling WPF buttons for Image Viewer'/><author><name>awkwardcoder</name><uri>http://www.blogger.com/profile/09746266491429238639</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNCVrxgZI0ysSe04Lq2lyQfaYkLNVLBhLda8ryfijkXIytzt_8m2LpnVZqeEjyv3K_DkRQY6nUCjqVapwc3GZCzWZMa7snTHxSYXfBqPkTLMsdoMowuwzBMQbdlaYpwQ/s220/PXL_20210316_143926215.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQqZ4_TQh95sgZnRSYQPsoniQjXHAphK-6Hd-0owUtHQEc8-A7eEarnbE3OVPxeoSBl5kNAwrYrmj_LKZEK8CXEWuyW-caGUCBSKBZ3FFmfNcQUeJDqIJMMtZw26id-hpnPak8ak6SG77x/s72-c/image+viewer+01.png" height="72" width="72"/><thr:total>0</thr:total><georss:featurename>London N16, UK</georss:featurename><georss:point>51.5623078 -0.076435299999957351</georss:point><georss:box>51.5228228 -0.15711629999995735 51.6017928 0.0042457000000426515</georss:box></entry><entry><id>tag:blogger.com,1999:blog-2559668977390861004.post-6999744109520721186</id><published>2014-12-17T19:53:00.002+00:00</published><updated>2015-01-08T13:25:34.409+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term=".Net"/><category scheme="http://www.blogger.com/atom/ns#" term="C#"/><category scheme="http://www.blogger.com/atom/ns#" term="Development"/><category scheme="http://www.blogger.com/atom/ns#" term="WPF"/><title type='text'>UI freezing when CPU hits 100% constantly - follow up, part deux</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
My last &lt;a href=&quot;http://awkwardcoder.blogspot.co.uk/2014/12/ui-freezing-when-cpu-hits-100.html&quot; target=&quot;_blank&quot;&gt;post&lt;/a&gt; had a comment from &lt;a href=&quot;https://twitter.com/LordHanson&quot; target=&quot;_blank&quot;&gt;@LordHanson&lt;/a&gt; about changing the thread priority via the ThreadStart parameter to see if this improved the performance.&lt;br /&gt;
&lt;br /&gt;
I made the following small change to include setting the thread priority:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgp3dpaWIpaK4LZxAxITz3pj4wpNjQ1oSguTUbCv9LOym-uXplTjW9piVtEwRCCLSjcWaEqnYKdo5PYDGNpTIqlmtWWPEuMqtz_VM6qGJb5X7JGo9oEP9D_FvXIXko941kS4b1f6YMAH1AW/s1600/cpu+3+01.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgp3dpaWIpaK4LZxAxITz3pj4wpNjQ1oSguTUbCv9LOym-uXplTjW9piVtEwRCCLSjcWaEqnYKdo5PYDGNpTIqlmtWWPEuMqtz_VM6qGJb5X7JGo9oEP9D_FvXIXko941kS4b1f6YMAH1AW/s1600/cpu+3+01.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
This improved the responsiveness of the UI when the number of thread is equal to or greater than the number of logical processors (tested with 2 * System.Environment.ProcessorCount), I still see the UI stuttering &amp;amp; stalling occasionally but it&#39;s greatly reduced - happens less than 10% of the time.&lt;br /&gt;
&lt;br /&gt;
I then start to wonder is it better from the point of view of total time taken to reduce the concurrency to less than the number of logical processors or to reduce the thread priority. I suppose the answer depends on which technique you want to use, for me there isn&#39;t a justifiable reason not to use the Parallel.For from the TPL - it&#39;s not a piece of time critical code.&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://awkwardcoder.blogspot.com/feeds/6999744109520721186/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://awkwardcoder.blogspot.com/2014/12/ui-freezing-when-cpu-hits-100_17.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/6999744109520721186'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/6999744109520721186'/><link rel='alternate' type='text/html' href='http://awkwardcoder.blogspot.com/2014/12/ui-freezing-when-cpu-hits-100_17.html' title='UI freezing when CPU hits 100% constantly - follow up, part deux'/><author><name>awkwardcoder</name><uri>http://www.blogger.com/profile/09746266491429238639</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNCVrxgZI0ysSe04Lq2lyQfaYkLNVLBhLda8ryfijkXIytzt_8m2LpnVZqeEjyv3K_DkRQY6nUCjqVapwc3GZCzWZMa7snTHxSYXfBqPkTLMsdoMowuwzBMQbdlaYpwQ/s220/PXL_20210316_143926215.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgp3dpaWIpaK4LZxAxITz3pj4wpNjQ1oSguTUbCv9LOym-uXplTjW9piVtEwRCCLSjcWaEqnYKdo5PYDGNpTIqlmtWWPEuMqtz_VM6qGJb5X7JGo9oEP9D_FvXIXko941kS4b1f6YMAH1AW/s72-c/cpu+3+01.png" height="72" width="72"/><thr:total>0</thr:total><georss:featurename>Stoke Newington, London N16 8EB, UK</georss:featurename><georss:point>51.556352399999987 -0.076537400000006528</georss:point><georss:box>51.555118399999991 -0.079058900000006524 51.557586399999984 -0.074015900000006532</georss:box></entry><entry><id>tag:blogger.com,1999:blog-2559668977390861004.post-7374890543018437718</id><published>2014-12-15T18:16:00.001+00:00</published><updated>2015-01-08T13:27:24.558+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term=".Net"/><category scheme="http://www.blogger.com/atom/ns#" term="C#"/><category scheme="http://www.blogger.com/atom/ns#" term="Development"/><category scheme="http://www.blogger.com/atom/ns#" term="WPF"/><title type='text'>UI freezing when CPU hits 100% constantly - follow up</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
I was wondering on the affects if my previous &lt;a href=&quot;http://awkwardcoder.blogspot.co.uk/2014/11/ui-freezing-when-cpu-hits-100-constantly.html&quot; target=&quot;_blank&quot;&gt;post&lt;/a&gt; was re-written to remove the use of TPL and just use the standard threading classes in the framework instead, would the performance be different.&lt;br /&gt;
&lt;br /&gt;
So the previous post was using the following code: &lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgujGzvs3Fydhyphenhyphenbxn2aKXmuhh4LyEgGWUAC_sfS53jdXjrl_6NT06Kr7WllCgqs7KHQyJ5paGRpS1CT-oJ87v8MZlH2H9x3kyehYxv9qjF7spMVxNJjtIv8YXQbQo-K4jWCadadBkp9lS5r/s1600/cpu+04.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgujGzvs3Fydhyphenhyphenbxn2aKXmuhh4LyEgGWUAC_sfS53jdXjrl_6NT06Kr7WllCgqs7KHQyJ5paGRpS1CT-oJ87v8MZlH2H9x3kyehYxv9qjF7spMVxNJjtIv8YXQbQo-K4jWCadadBkp9lS5r/s1600/cpu+04.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
When the limited concurrency scheduler is initialised with a number greater than or equal to the number of logical processors then the CPU hits 100% and the app stalls and stutters.&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;If this is re-written without the use of TPL would I get the same results?&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Re-writing this produced the following code, using a Semaphore to control the number of concurrent threads:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMLi-aGr1zLQerMPs-MrQebOWwTz5SdXHy8hQoh54uPAWCLlfXreN590ysXyiqwt06q4KQnpu4lFr9ZvvfbKknb08lvBLnJ3wMsgQ2qIKeEi_iua2Fjo-IxxWxZKmpMJvKJuX0T2n0nbtD/s1600/cpu+2+01.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMLi-aGr1zLQerMPs-MrQebOWwTz5SdXHy8hQoh54uPAWCLlfXreN590ysXyiqwt06q4KQnpu4lFr9ZvvfbKknb08lvBLnJ3wMsgQ2qIKeEi_iua2Fjo-IxxWxZKmpMJvKJuX0T2n0nbtD/s1600/cpu+2+01.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
In answer to the question, you get exactly the same behaviour, there is no benefit in not using TPL to handle the concurrency - good :)&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://awkwardcoder.blogspot.com/feeds/7374890543018437718/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://awkwardcoder.blogspot.com/2014/12/ui-freezing-when-cpu-hits-100.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/7374890543018437718'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/7374890543018437718'/><link rel='alternate' type='text/html' href='http://awkwardcoder.blogspot.com/2014/12/ui-freezing-when-cpu-hits-100.html' title='UI freezing when CPU hits 100% constantly - follow up'/><author><name>awkwardcoder</name><uri>http://www.blogger.com/profile/09746266491429238639</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNCVrxgZI0ysSe04Lq2lyQfaYkLNVLBhLda8ryfijkXIytzt_8m2LpnVZqeEjyv3K_DkRQY6nUCjqVapwc3GZCzWZMa7snTHxSYXfBqPkTLMsdoMowuwzBMQbdlaYpwQ/s220/PXL_20210316_143926215.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgujGzvs3Fydhyphenhyphenbxn2aKXmuhh4LyEgGWUAC_sfS53jdXjrl_6NT06Kr7WllCgqs7KHQyJ5paGRpS1CT-oJ87v8MZlH2H9x3kyehYxv9qjF7spMVxNJjtIv8YXQbQo-K4jWCadadBkp9lS5r/s72-c/cpu+04.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2559668977390861004.post-8756093536861522155</id><published>2014-11-16T16:34:00.000+00:00</published><updated>2015-01-08T13:26:48.201+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term=".Net"/><category scheme="http://www.blogger.com/atom/ns#" term="C#"/><category scheme="http://www.blogger.com/atom/ns#" term="Development"/><category scheme="http://www.blogger.com/atom/ns#" term="WPF"/><title type='text'>UI freezing when CPU hits 100% constantly</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
I&#39;ve been working with a team where I&#39;ve been putting a WPF UI over a set of implementations of a custom interface. Each implementation is a long running process which is handled in standard manner by creating an asynchronous Task&amp;lt;T&amp;gt; and displaying the results from the continuation.&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
The standard CPU utilisation for the majority of the interface implementations is shown below - this represent the ideal, not hogging the CPU&#39;s and behaving like a good citizen...&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbJDMJM8AhXTJfYoAvT1LaxdY6dlqBtZADscAXtWq2gLkCjsb4eAyG5uz6w4F9o8JgPat799jhyphenhyphenB2W9L3k4rGq7kqgNoKOaJ1brImZfdF1wB5ga_Quzioe1px7KgaQ7O0B_TBLrt3T4Wmw/s1600/cpu+02.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbJDMJM8AhXTJfYoAvT1LaxdY6dlqBtZADscAXtWq2gLkCjsb4eAyG5uz6w4F9o8JgPat799jhyphenhyphenB2W9L3k4rGq7kqgNoKOaJ1brImZfdF1wB5ga_Quzioe1px7KgaQ7O0B_TBLrt3T4Wmw/s1600/cpu+02.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Where as one implementation has the following CPU utilisation - all logical processors max&#39;ed out. The app becomes unresponsive, the UI starts to stutter and freeze all because the dispatcher (UI) thread is not being scheduled frequently enough - white screen of death (WSoD). It&#39;s not only this app it starts to affect but all other apps running.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4bnG9tR0v7fUSpLqYoU6xq8rPG9taLU20sOhrvJ0-aSUSV1UoQot2OI7zfXqPC55W26iJ4BPVrl286nJ8OgHWtevl-BxGheY6zo8P5mf0peBrFX7jEviDY-wzjpwUv9vbh01WlI0-IY2v/s1600/cpu+01.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4bnG9tR0v7fUSpLqYoU6xq8rPG9taLU20sOhrvJ0-aSUSV1UoQot2OI7zfXqPC55W26iJ4BPVrl286nJ8OgHWtevl-BxGheY6zo8P5mf0peBrFX7jEviDY-wzjpwUv9vbh01WlI0-IY2v/s1600/cpu+01.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
Hopefully the difference between the majority and this particular instance is obvious - the majority are single-threaded long running processes and the other is a multi-threaded long running process. It is not multi-threaded by a factor 2, 3 or 4, but by a factor of n, where n is considerably larger than the number of available logical processors, a value greater than 100.&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
The code causing this issue is generating simulation data for a set of stochastic models, the generation is CPU bound for around 5 minutes, after that the long running process returns to be being a single-threaded and behaves like all the other implementations, I can&#39;t show the actual code, but shown below is something similar:&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjx7BJ09XnOwKGY1zI2Kja2ryxyU_pJ4_oAP1srHOpyiKaKq5n72fMcs5Wy3pUG1jkvg6MCG6wP9paW-C0GR2n4dFxUU0IVcMDZSKgNQRjYG4MWU_-xXNpg44QSP0g79M33evmNuxnby0-v/s1600/cpu+03.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjx7BJ09XnOwKGY1zI2Kja2ryxyU_pJ4_oAP1srHOpyiKaKq5n72fMcs5Wy3pUG1jkvg6MCG6wP9paW-C0GR2n4dFxUU0IVcMDZSKgNQRjYG4MWU_-xXNpg44QSP0g79M33evmNuxnby0-v/s1600/cpu+03.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
As you can see the for-loop creates a lot of tasks - 1000 in the example. The method then waits for all of them to complete before returning.&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
The scheduling of tasks (onto the logical processors) can be configured, but in this case it isn&#39;t and this is the problem, the default method overload has been usēd.&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
Because we aren&#39;t attempting to control the number of concurrent tasks running the TPL is maximizing the number of tasks, in this case it&#39;s running 8 in parallel across the logical processors until all the scheduled tasks have completed.&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;i&gt;How do I control the level of concurrency for so many tasks?&lt;/i&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
The overloads for StartNew on the TaskFactory class doesn&#39;t expose an obvious solution such as an integer value for the maximum concurrency. The answer is to pass a custom scheduler to the method which it controls the level of concurrency. &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ee789351(v=vs.110).aspx&quot; target=&quot;_blank&quot;&gt;MSDN&lt;/a&gt; has an article on the subject, and it&#39;s perfectly suited to this problem. The modified method now looks like this:&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDi8Hjcpqu5uYFxMEjbJ0iHNlTnh7IfZ3tZgl5A3B9OtN5ZxVY5xoMdMlDx6BM3COCuGvejwrWBKMi8iHE471nt1YLev_OCdM4ISplZljc3ppgGOquMs7ZfdIyvjjv7G6cxbEiYCCCi1zw/s1600/cpu+04.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDi8Hjcpqu5uYFxMEjbJ0iHNlTnh7IfZ3tZgl5A3B9OtN5ZxVY5xoMdMlDx6BM3COCuGvejwrWBKMi8iHE471nt1YLev_OCdM4ISplZljc3ppgGOquMs7ZfdIyvjjv7G6cxbEiYCCCi1zw/s1600/cpu+04.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
I&#39;ve hardcoded the maximum number of concurrency to 6 in the above example, but you could do something more dynamic by using the System.Environment.ProcessorCount property. The CPU utilisation now looks something like this:&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHwLlHVq2YsgiM3A_fHR_WVPh-UxquZWnkIvQcOeFv_JYPnG7RbYpNzyNthNEB-u8gFv1vs7MvLafs8eMTjojcSkjVH2rM9Ya36rU_NtMsa8tzoyHDpNAU7iaoWjZGNkdI9qDCOWO33D9u/s1600/cpu+05.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHwLlHVq2YsgiM3A_fHR_WVPh-UxquZWnkIvQcOeFv_JYPnG7RbYpNzyNthNEB-u8gFv1vs7MvLafs8eMTjojcSkjVH2rM9Ya36rU_NtMsa8tzoyHDpNAU7iaoWjZGNkdI9qDCOWO33D9u/s1600/cpu+05.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
The CPU utilisation is now around 75% which represent the level of concurrency I&#39;ve specified with the scheduler - it was created &amp;nbsp;with a concurrency of 6 (out of possible 8 logical processors). This still seems rather large, but there is enough spare capacity for the dispatcher thread to be scheduled and therefore the UI remains responsive.&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
Note: The code above could be re-written to be more elegant using Parallel.For method, this would remove the need for the custom scheduler - it&#39;s not my code to change apparently :)&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
If I was to re-write it, something like this following would be better IMO:&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDETdoFwwYAsVZ5U5VjIxkv0idHUDtschQ9OcfBO-V_y1BjgeM152GIUKVnF6-KleO4vswQ36aOibNJ8U42owb6W4uvXBjnc_-cykvtmVgsxTr16GLZIr9Cpk-eB5CGcmUUKobvwZP1PN9/s1600/cpu+06.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDETdoFwwYAsVZ5U5VjIxkv0idHUDtschQ9OcfBO-V_y1BjgeM152GIUKVnF6-KleO4vswQ36aOibNJ8U42owb6W4uvXBjnc_-cykvtmVgsxTr16GLZIr9Cpk-eB5CGcmUUKobvwZP1PN9/s1600/cpu+06.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
More info about the differences can be found in the following pdf, &lt;a href=&quot;http://www.microsoft.com/en-us/download/details.aspx?id=19222&quot; target=&quot;_blank&quot;&gt;Pattern of Parallel Programming in C#&lt;/a&gt;&amp;nbsp;for info on Parallel.ForEach vs Task.Factory.StartNew.&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://awkwardcoder.blogspot.com/feeds/8756093536861522155/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://awkwardcoder.blogspot.com/2014/11/ui-freezing-when-cpu-hits-100-constantly.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/8756093536861522155'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/8756093536861522155'/><link rel='alternate' type='text/html' href='http://awkwardcoder.blogspot.com/2014/11/ui-freezing-when-cpu-hits-100-constantly.html' title='UI freezing when CPU hits 100% constantly'/><author><name>awkwardcoder</name><uri>http://www.blogger.com/profile/09746266491429238639</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNCVrxgZI0ysSe04Lq2lyQfaYkLNVLBhLda8ryfijkXIytzt_8m2LpnVZqeEjyv3K_DkRQY6nUCjqVapwc3GZCzWZMa7snTHxSYXfBqPkTLMsdoMowuwzBMQbdlaYpwQ/s220/PXL_20210316_143926215.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbJDMJM8AhXTJfYoAvT1LaxdY6dlqBtZADscAXtWq2gLkCjsb4eAyG5uz6w4F9o8JgPat799jhyphenhyphenB2W9L3k4rGq7kqgNoKOaJ1brImZfdF1wB5ga_Quzioe1px7KgaQ7O0B_TBLrt3T4Wmw/s72-c/cpu+02.png" height="72" width="72"/><thr:total>0</thr:total><georss:featurename>London N16, UK</georss:featurename><georss:point>51.5623078 -0.076435299999957351</georss:point><georss:box>51.5228228 -0.15711629999995735 51.6017928 0.0042457000000426515</georss:box></entry><entry><id>tag:blogger.com,1999:blog-2559668977390861004.post-1167616036442472730</id><published>2014-11-06T18:46:00.002+00:00</published><updated>2014-11-06T21:26:18.011+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term=".Net"/><category scheme="http://www.blogger.com/atom/ns#" term="C#"/><category scheme="http://www.blogger.com/atom/ns#" term="Development"/><title type='text'>Modelling units of measure</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
I&#39;ve been looking at writing an exercise app, and this would require some kind of units of measure for distance (as well as time).&lt;br /&gt;
&lt;br /&gt;
I could use an enum to represent the different types of units - metres, kilometres, yards, miles etc. But this seems to be lacking from the point of view of converting between the different types - I would need a class to represent the conversions. What I want is a more integrated approach - the use of static read-only properties.&lt;br /&gt;
&lt;br /&gt;
What I want to be able to do is best described by the following test:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLNupZ5JkvAiYeOFbGGhiK-T3OZRwNl2eCLn4ti3RjKQClydMt9A1QXPc_rt-b8s7fhfktBqJ7NWzFmhKS-bL8Ra3sCfDtyked9EALZCjiofvQfdanGXT5qTvLRuXnCiBorcFatWU8aL8W/s1600/units+01.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLNupZ5JkvAiYeOFbGGhiK-T3OZRwNl2eCLn4ti3RjKQClydMt9A1QXPc_rt-b8s7fhfktBqJ7NWzFmhKS-bL8Ra3sCfDtyked9EALZCjiofvQfdanGXT5qTvLRuXnCiBorcFatWU8aL8W/s1600/units+01.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
The Measurement struct is very simple, a couple of properties - Amount &amp;amp; Unit and a ConvertTo method:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxho8-hVNEKPryfDE4QYe9Uf2V-544wMPTaFsllToAJyE4VUHJHSgEgN4aHbeomfbM2YNZqHc3GlQIFhzYAsoLhKoecPRrSuODX2RQpDe1Q9RELp5rAPEfyEabVOEI_imThoS2t9HxKFDe/s1600/units+02.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxho8-hVNEKPryfDE4QYe9Uf2V-544wMPTaFsllToAJyE4VUHJHSgEgN4aHbeomfbM2YNZqHc3GlQIFhzYAsoLhKoecPRrSuODX2RQpDe1Q9RELp5rAPEfyEabVOEI_imThoS2t9HxKFDe/s1600/units+02.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
As you can see in the ConvertTo method the Unit class owns the conversions - it is more than just a simple Enum - it has behaviour, how to convert between the different units of measure.&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;So how are the units defined?&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
A Unit instance is exposed as a read-only static property on a static Units class:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvL3knxjcL4tVv2Ltt1_cvJUvThQAw6x9g27aIaGhkp5OgVeohGt_X6rSEeFMhhHWwPFWlDMkrVcUz8-7ymGBb9SfGbSTJqobT-uX8cF2tV0cHvZJQfD-b3_i9Du5CzZgojB9YSH014LGB/s1600/units+03.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvL3knxjcL4tVv2Ltt1_cvJUvThQAw6x9g27aIaGhkp5OgVeohGt_X6rSEeFMhhHWwPFWlDMkrVcUz8-7ymGBb9SfGbSTJqobT-uX8cF2tV0cHvZJQfD-b3_i9Du5CzZgojB9YSH014LGB/s1600/units+03.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
What makes this approach interesting is the use of the Lazy&amp;lt;T&amp;gt; to get around the circular reference problem when the static properties are initialized - for example the Centimetre properties uses the Metre &amp;amp; Kilometre properties which in turn use the Centimetre property, which in turn use the Metre &amp;amp; Kilometre properties.&lt;br /&gt;
&lt;br /&gt;
As you can see this could go on for ever if I didn&#39;t use the Lazy&amp;lt;T&amp;gt; inside the Unit class. It allows me to disconnect the creation of the conversions from the Converters property because by the time the Converters properties is accessed the constructor on the Unit class will have completed.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzMpQlW30PXSsoPzUhiZBEjtcAwv2ldbjRo8W4f2T2G3eNkCz46y2-OJTEekoHiqNJ2A0nDxxNb7xOBrI6UmG2Mhq5mrMHRIoy4nJSuHcsTi3dHlO7EwfwbeNUNMV5mMw5J58nVX5k48d0/s1600/units+04.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzMpQlW30PXSsoPzUhiZBEjtcAwv2ldbjRo8W4f2T2G3eNkCz46y2-OJTEekoHiqNJ2A0nDxxNb7xOBrI6UmG2Mhq5mrMHRIoy4nJSuHcsTi3dHlO7EwfwbeNUNMV5mMw5J58nVX5k48d0/s1600/units+04.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
The smart bit of code is inside the Converters property, a pretty standard piece of lazy initialization to create the actual Converter instances.&lt;br /&gt;
&lt;br /&gt;
The code above is from the Simple.Units repo available on&amp;nbsp;&lt;a href=&quot;https://github.com/oriches/Simple.Units&quot; target=&quot;_blank&quot;&gt;GitHub&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://awkwardcoder.blogspot.com/feeds/1167616036442472730/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://awkwardcoder.blogspot.com/2014/11/modelling-units-of-measure.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/1167616036442472730'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/1167616036442472730'/><link rel='alternate' type='text/html' href='http://awkwardcoder.blogspot.com/2014/11/modelling-units-of-measure.html' title='Modelling units of measure'/><author><name>awkwardcoder</name><uri>http://www.blogger.com/profile/09746266491429238639</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNCVrxgZI0ysSe04Lq2lyQfaYkLNVLBhLda8ryfijkXIytzt_8m2LpnVZqeEjyv3K_DkRQY6nUCjqVapwc3GZCzWZMa7snTHxSYXfBqPkTLMsdoMowuwzBMQbdlaYpwQ/s220/PXL_20210316_143926215.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLNupZ5JkvAiYeOFbGGhiK-T3OZRwNl2eCLn4ti3RjKQClydMt9A1QXPc_rt-b8s7fhfktBqJ7NWzFmhKS-bL8Ra3sCfDtyked9EALZCjiofvQfdanGXT5qTvLRuXnCiBorcFatWU8aL8W/s72-c/units+01.png" height="72" width="72"/><thr:total>0</thr:total><georss:featurename>London N16, UK</georss:featurename><georss:point>51.5623078 -0.076435299999957351</georss:point><georss:box>51.5228228 -0.15711629999995735 51.6017928 0.0042457000000426515</georss:box></entry><entry><id>tag:blogger.com,1999:blog-2559668977390861004.post-2311586108494272205</id><published>2014-01-18T23:37:00.000+00:00</published><updated>2014-01-19T15:09:39.422+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="C#"/><category scheme="http://www.blogger.com/atom/ns#" term="Development"/><category scheme="http://www.blogger.com/atom/ns#" term="F#"/><category scheme="http://www.blogger.com/atom/ns#" term="MVVM"/><category scheme="http://www.blogger.com/atom/ns#" term="WPF"/><title type='text'>Simple F# REPL in WPF - part 4</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
This is the final post in this mini series, I&#39;m going to show the finished UI user control and how simple it is to host inside a WPF app. The code is available on &lt;a href=&quot;https://github.com/oriches/Simple.Wpf.FSharp.Repl&quot;&gt;gitHub&lt;/a&gt;&amp;nbsp;and the published binaries are available via &lt;a href=&quot;https://www.nuget.org/packages/Simple.Wpf.FSharp.Repl/&quot;&gt;nuGet&lt;/a&gt;&amp;nbsp;(supports&amp;nbsp;.Net version 4.0+).&lt;br /&gt;
&lt;br /&gt;
Before I show the finished UI, lets look at the F# Interactive in Visual Studio, this loads, queries &amp;amp; displays the results from an external assembly:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHzBVdKzYN5pbO2ylEzdFCKUBuyfx_9Lowff0kJdwOcI4owdO3sZb3o9Dg7jOFmuzDDdoB33W_J97kkA2fGC4g6HsOAgIBeefWS0nO0D9dk6Ys657bEikgQJS_D3EWZSvaYeoTYZE2tVuR/s1600/wpf+fsharp+repl+22.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHzBVdKzYN5pbO2ylEzdFCKUBuyfx_9Lowff0kJdwOcI4owdO3sZb3o9Dg7jOFmuzDDdoB33W_J97kkA2fGC4g6HsOAgIBeefWS0nO0D9dk6Ys657bEikgQJS_D3EWZSvaYeoTYZE2tVuR/s1600/wpf+fsharp+repl+22.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;i&gt;What does this look like in my implementation?&lt;/i&gt;&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnil5wsb6d7H_RJOgVbLqoEA72wk5CQsEnhATSmS6_uNDZd6CbpHP-zSYQG6-qpcaOwTBh0W8BJvuGuFhquqz0HE4Wl3W_qPrglnONuLaS-SLmcDkw1d5cPVdll4IOrK3RM-vYBADQzo_v/s1600/wpf+fsharp+repl+21.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnil5wsb6d7H_RJOgVbLqoEA72wk5CQsEnhATSmS6_uNDZd6CbpHP-zSYQG6-qpcaOwTBh0W8BJvuGuFhquqz0HE4Wl3W_qPrglnONuLaS-SLmcDkw1d5cPVdll4IOrK3RM-vYBADQzo_v/s1600/wpf+fsharp+repl+21.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
It&#39;s looks pretty familiar right? :)&lt;br /&gt;
&lt;br /&gt;
The major difference is I&#39;ve output the working folder for the F# interactive process when the process starts:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNBXhQXrAI1L0xKRpbhlyfOolNK8HmEh707rQfNX8HFa4HXCz8wSgcPx0DSow7SBUhFQV6dZZxAHhm_xI8ayrRJ_qx6Zu0OzIRZ6wAnp84qgub3CHKMSKkq6qLeDlcFwAENDbVSJfh3sRv/s1600/wpf+fsharp+repl+23.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNBXhQXrAI1L0xKRpbhlyfOolNK8HmEh707rQfNX8HFa4HXCz8wSgcPx0DSow7SBUhFQV6dZZxAHhm_xI8ayrRJ_qx6Zu0OzIRZ6wAnp84qgub3CHKMSKkq6qLeDlcFwAENDbVSJfh3sRv/s1600/wpf+fsharp+repl+23.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
I&#39;ve made this configurable in code, so I thought it would be a good idea to tell the end user where they could put any assemblies they want to reference.&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;How can the user access the working folder?&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
Simply, a right click menu:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCjCoxpcRvtVDH50Ppb9CEvCddJheE22O5lifHCk0MHZimJPstC2LYcFTU5U_3OMbQsT5ukC8RP6yR9a3735piEHCs20qJYLDN446iQ1VVyXMkZ0bwxcyLnt2nkb9EIlohmu6hTB4s5nb-/s1600/wpf+fsharp+repl+25.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCjCoxpcRvtVDH50Ppb9CEvCddJheE22O5lifHCk0MHZimJPstC2LYcFTU5U_3OMbQsT5ukC8RP6yR9a3735piEHCs20qJYLDN446iQ1VVyXMkZ0bwxcyLnt2nkb9EIlohmu6hTB4s5nb-/s1600/wpf+fsharp+repl+25.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
All the menu options should be obvious, the working folder for the above example is shown below, you can see it has the assembly referenced above:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7zsWKs10w-Nw29wx9D-v6VPKWE9zS2BkoWoeNLvus-jOzvRnOuSXoPLS0sXuyrwjxPB6Gt_k3XaASs7427rqJO3peh-OuCCdM4CQWE0YFF66KJeEmPHDA0hLu4E2EcMxFq_QYfzdPVoHY/s1600/wpf+fsharp+repl+26.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7zsWKs10w-Nw29wx9D-v6VPKWE9zS2BkoWoeNLvus-jOzvRnOuSXoPLS0sXuyrwjxPB6Gt_k3XaASs7427rqJO3peh-OuCCdM4CQWE0YFF66KJeEmPHDA0hLu4E2EcMxFq_QYfzdPVoHY/s1600/wpf+fsharp+repl+26.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
For completeness the types used in the above query are shown below:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsKDe4dje0RRk4K_8d0vSox19kn4g6szQIN4zt_8grRSLGpIQ1Dc5jkdzgsjmgyuPzkiMwI5TVF3k5n52mnDweaY6iPhvi-MZPpcl2IXbKBxN7qJ6bkvpv-nHmNIJtWJMSAI_psbXb1v-g/s1600/wpf+fsharp+repl+27.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsKDe4dje0RRk4K_8d0vSox19kn4g6szQIN4zt_8grRSLGpIQ1Dc5jkdzgsjmgyuPzkiMwI5TVF3k5n52mnDweaY6iPhvi-MZPpcl2IXbKBxN7qJ6bkvpv-nHmNIJtWJMSAI_psbXb1v-g/s1600/wpf+fsharp+repl+27.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;i&gt;How is the user control being used in code?&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
The user control obviously has an XAML representation - &lt;a href=&quot;https://github.com/oriches/Simple.Wpf.FSharp.Repl/blob/master/Simple.Wpf.FSharp.Repl/UI/ReplEngine.xaml&quot;&gt;ReplEngine&lt;/a&gt;. I&#39;ve tried to keep the using of this as simple as possible, the following screen shot shows the control being used in an MVVM implementation with a specific theme being applied:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHNDIGhdmkvdEB_3qYG6C6ZxCGZIE3jzBl-wNHtk6dhRGsMJ2oQLy_fPqVxu-HurHRc5-Xa6lNDOaKPKQzaA90CvFiLDbC8M7qVi60Dx2g8efc6GQmbYcYnWN7RuFsZbACrEM5kIYmje3c/s1600/wpf+fsharp+repl+28.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHNDIGhdmkvdEB_3qYG6C6ZxCGZIE3jzBl-wNHtk6dhRGsMJ2oQLy_fPqVxu-HurHRc5-Xa6lNDOaKPKQzaA90CvFiLDbC8M7qVi60Dx2g8efc6GQmbYcYnWN7RuFsZbACrEM5kIYmje3c/s1600/wpf+fsharp+repl+28.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
The control&#39;s DataContext is bound to specific view model supplied as part of the assembly. In fact if your going use the control in an MVVM application there are 3 classes you&#39;ll need to know about and use:&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;ReplEngine&lt;/b&gt; - &lt;i&gt;as described above the UI representation of the REPL engine to be included in XAML,&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;ReplEngineController&lt;/b&gt; - &lt;i&gt;coordinates communication between the UI and the actual REPL engine implementation, backed by an interface - IReplEngineController,&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;ReplEngineViewModel &lt;/b&gt;- &lt;i&gt;contains all the UI concerns, bindable properties &amp;amp; commands, backed by an interface IReplEngineViewModel and accessed from the controller.&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
The view model (FSharpReplViewModel) used is shown below and as you can see it&#39;s using both the controller &amp;amp; view model, nothing complicated just simple dependency injection and exposure of the view model as the Content property:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh91gHUEIh5FfCfmucVflT0wQKwVK2u5K0rP9_UJHfpw2SVtJUyxiaXsxv-hyjYgkdxLheyICop_uMywgbUyBMvhbqmpL4q4PbB2h9JGr878g7CLP4aTXCAKTj4_7-8SjTi2TmkE4UqPn5I/s1600/wpf+fsharp+repl+29.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh91gHUEIh5FfCfmucVflT0wQKwVK2u5K0rP9_UJHfpw2SVtJUyxiaXsxv-hyjYgkdxLheyICop_uMywgbUyBMvhbqmpL4q4PbB2h9JGr878g7CLP4aTXCAKTj4_7-8SjTi2TmkE4UqPn5I/s1600/wpf+fsharp+repl+29.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
The IoC registrations for the controller &amp;amp; view model are easy, as you can see there are couple of parameters, these are optional, this is where you&#39;d configure the working folder and the script to run automatically when the UI is first rendered:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5DWnwf1N7gCIfoEZsdZx2vLIuZUSg0_y2wtvQJ1xfELbk-d6w6eigAFYcxxCpbtkYS-gsfPiS8Y9sts38ikjvdmWP40-64DitomgDvfgXAftseELbSepNcLVtkJe4nZKb_dBNXf_D-zBt/s1600/wpf+fsharp+repl+30.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5DWnwf1N7gCIfoEZsdZx2vLIuZUSg0_y2wtvQJ1xfELbk-d6w6eigAFYcxxCpbtkYS-gsfPiS8Y9sts38ikjvdmWP40-64DitomgDvfgXAftseELbSepNcLVtkJe4nZKb_dBNXf_D-zBt/s1600/wpf+fsharp+repl+30.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
As you can see, it&#39;s really quick &amp;amp; simple to use in an MVVM scenario, but;&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;What if you&#39;re not using MVVM, what if you&#39;re using a code-behind approach?&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
This is catered for as well in the form of a user control called &lt;a href=&quot;https://github.com/oriches/Simple.Wpf.FSharp.Repl/blob/master/Simple.Wpf.FSharp.Repl/UI/ReplWindow.xaml&quot;&gt;ReplWindow&lt;/a&gt;. This wraps the ReplEngine user control, the controller &amp;amp; the view model, meaning you don&#39;t have to bind any properties. The StartupScript &amp;amp; WorkingDirectory are exposed as dependency properties:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQrU83DXp7DiOTJnHxqbrFjztUM4vGY2epOrA5pNzehdnhiaWS6c7oT5QtIPBIhXzAqBVU0HuQIBwuz4hkgDPi1wyKexQ5n6zAXiLRZuD9edz5IUJNgSYhIlUuzzAzJCdsMKbf1qGtjERF/s1600/wpf+fsharp+repl+31.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQrU83DXp7DiOTJnHxqbrFjztUM4vGY2epOrA5pNzehdnhiaWS6c7oT5QtIPBIhXzAqBVU0HuQIBwuz4hkgDPi1wyKexQ5n6zAXiLRZuD9edz5IUJNgSYhIlUuzzAzJCdsMKbf1qGtjERF/s1600/wpf+fsharp+repl+31.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
That&#39;s it from a hosting point of view, the only thing left to describe is the theme support, not so much describe but show a hideous green example and the supporting XAML:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZkEE2BKk2ztUCtLveaJBhSvutlFiuefoLot80TMsLty7NAkAOSx2CijbZUHQuyixelcPSAuKhuE8PkISdjLvj3Gh9arEBFkQM3e1a5rRcL-wY1rXeq3wAXclTy6MEuzbxeoi5kDdiz5YS/s1600/wpf+fsharp+repl+32.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZkEE2BKk2ztUCtLveaJBhSvutlFiuefoLot80TMsLty7NAkAOSx2CijbZUHQuyixelcPSAuKhuE8PkISdjLvj3Gh9arEBFkQM3e1a5rRcL-wY1rXeq3wAXclTy6MEuzbxeoi5kDdiz5YS/s1600/wpf+fsharp+repl+32.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
The theme styles the buttons, border, text &amp;amp; terminal controls, if a theme is not defined it will default to the current windows theme:&lt;br /&gt;
&lt;div class=&quot;gistLoad&quot; data-id=&quot;8497297&quot; id=&quot;gist8497297&quot;&gt;
&lt;br /&gt;
Loading gist ....&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
The example app used above is from the Simple.Wpf.Composition repo available on &lt;a href=&quot;https://github.com/oriches/Simple.Wpf.Composition&quot;&gt;gitHub&lt;/a&gt;.&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://awkwardcoder.blogspot.com/feeds/2311586108494272205/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://awkwardcoder.blogspot.com/2014/01/simple-f-repl-in-wpf-part-4.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/2311586108494272205'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/2311586108494272205'/><link rel='alternate' type='text/html' href='http://awkwardcoder.blogspot.com/2014/01/simple-f-repl-in-wpf-part-4.html' title='Simple F# REPL in WPF - part 4'/><author><name>awkwardcoder</name><uri>http://www.blogger.com/profile/09746266491429238639</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNCVrxgZI0ysSe04Lq2lyQfaYkLNVLBhLda8ryfijkXIytzt_8m2LpnVZqeEjyv3K_DkRQY6nUCjqVapwc3GZCzWZMa7snTHxSYXfBqPkTLMsdoMowuwzBMQbdlaYpwQ/s220/PXL_20210316_143926215.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHzBVdKzYN5pbO2ylEzdFCKUBuyfx_9Lowff0kJdwOcI4owdO3sZb3o9Dg7jOFmuzDDdoB33W_J97kkA2fGC4g6HsOAgIBeefWS0nO0D9dk6Ys657bEikgQJS_D3EWZSvaYeoTYZE2tVuR/s72-c/wpf+fsharp+repl+22.png" height="72" width="72"/><thr:total>0</thr:total><georss:featurename>London N16, UK</georss:featurename><georss:point>51.5623078 -0.076435299999957351</georss:point><georss:box>51.5228228 -0.15711629999995735 51.6017928 0.0042457000000426515</georss:box></entry><entry><id>tag:blogger.com,1999:blog-2559668977390861004.post-1265736830931200648</id><published>2014-01-02T19:00:00.000+00:00</published><updated>2014-01-02T19:00:08.602+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="C#"/><category scheme="http://www.blogger.com/atom/ns#" term="Development"/><category scheme="http://www.blogger.com/atom/ns#" term="Themes"/><category scheme="http://www.blogger.com/atom/ns#" term="WPF"/><category scheme="http://www.blogger.com/atom/ns#" term="XAML"/><title type='text'>Managing themes in WPF</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
Having just published &lt;a href=&quot;https://www.nuget.org/packages/Simple.Wpf.Terminal/&quot;&gt;Simple.Wpf.Terminal&lt;/a&gt; as a nuget package I wanted the ability to skin the user control - the more flexibility in the way it looks the more likely it will be used by other devs :)&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Before getting into the detail, lets look at the solution working in the test harness for my &lt;a href=&quot;https://github.com/oriches/Simple.Wpf.FSharp.Repl&quot;&gt;WPF F# REPL Engine&lt;/a&gt;, shown below are four different themes applied dynamically at run-time - no recompilation required to change the theme:&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoGUuGoc3Z8tCGEIXdD-p3bw5dOlSX4mlTdZr6nQq7i-SURnAGy0Zbql41GYP8gTR9BkcAOB9r1cAXXXrrWn1quaM0IMI737nxiL-wCCAfeeVWGINqVvVXfgeHEYYLAogzSRA8QBwI_VXN/s1600/themes+01.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoGUuGoc3Z8tCGEIXdD-p3bw5dOlSX4mlTdZr6nQq7i-SURnAGy0Zbql41GYP8gTR9BkcAOB9r1cAXXXrrWn1quaM0IMI737nxiL-wCCAfeeVWGINqVvVXfgeHEYYLAogzSRA8QBwI_VXN/s1600/themes+01.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
Previously in larger WPF apps I&#39;ve relied upon third-party control vendors like Telerik to provide theming support. Typically they provide good solutions to the problem with multiple themes supported as standard, and when you&#39;re already using their third party controls the use of their themes makes sense. But when you&#39;re developing a small UI component you don&#39;t want to add (&amp;amp; support) such a large footprint just to add themes to your niche control.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
A theme is a collection of &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/system.windows.style(v=vs.100).aspx&quot;&gt;Styles&lt;/a&gt; grouped into a &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/system.windows.resourcedictionary(v=vs.100).aspx&quot;&gt;ResourceDictionary&lt;/a&gt; in WPF. A Style can be applied to a control type, this is done either via the target type of via name (Key). Shown below is a very simple there with two styles defined, hopefully they are obvious but if not these two styles are targeting the Button &amp;amp; TextBlock controls:&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRBh-QMuF3tIltNyKfgLT_rveYNYWTaDpOiIFg5gauuAlYUgxOSrdEzN6EeJ9hoHkU2iBjDd-rGC-BKznsW2wgwXpYbKtkfr8rUFBR5uHnwXPN26lzwuEWSgZs-dmRATKCi_FG8gsluO3M/s1600/themes+02.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRBh-QMuF3tIltNyKfgLT_rveYNYWTaDpOiIFg5gauuAlYUgxOSrdEzN6EeJ9hoHkU2iBjDd-rGC-BKznsW2wgwXpYbKtkfr8rUFBR5uHnwXPN26lzwuEWSgZs-dmRATKCi_FG8gsluO3M/s1600/themes+02.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
A theme (resource dictionary) is then applied either at the application level to all controls in the visual tree or at the control level to all controls lower in the visual tree - scoping the theme to only a part of the visual tree.&lt;br /&gt;
&lt;br /&gt;
How you apply the theme is what makes managing themes interesting, typically in an app which doesn&#39;t support changing the theme at run-time this would be done statically at compile time using XAML:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgp7KPNtLY5CqskXNWAPctkqicCsQKLLJCnsDFdNa8Kr6XsEFRyxWyObNobFlvgHOZ5B3miIkK-nYR9rCgF3muGNNNnNZaIdw-bBC1kqKwrJUpVTyhXkiMFeQ83equmHZHUzHOpH276yvco/s1600/themes+03.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgp7KPNtLY5CqskXNWAPctkqicCsQKLLJCnsDFdNa8Kr6XsEFRyxWyObNobFlvgHOZ5B3miIkK-nYR9rCgF3muGNNNnNZaIdw-bBC1kqKwrJUpVTyhXkiMFeQ83equmHZHUzHOpH276yvco/s1600/themes+03.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
But this approach won&#39;t work when you want to be able to change the theme dynamically at run-time, you need to do this in code behind, and this is where a theme manager comes into play.&lt;br /&gt;
&lt;br /&gt;
The solution I wanted was to provide a simple UI (combo box) allowing the user to select a theme which is then dynamically applied to the UI. The UI control manipulates a globally defined theme manager - defined globally as a static class:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYwyZ_zh8JsrsQ18CguyE4kPdoHl-TaIRpVKqqifKvbOpayF69lVUUPC7mFmVfEs1gEV_4ZuudlqAPZXOw2JqvyZC8IOdqEIhWo_FE9iuOUNwoIQfFyWWe10_cSme2wsh3yfvBW3UITEXH/s1600/themes+04.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYwyZ_zh8JsrsQ18CguyE4kPdoHl-TaIRpVKqqifKvbOpayF69lVUUPC7mFmVfEs1gEV_4ZuudlqAPZXOw2JqvyZC8IOdqEIhWo_FE9iuOUNwoIQfFyWWe10_cSme2wsh3yfvBW3UITEXH/s1600/themes+04.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlLSmBmjD0twO9XXfwzfTarhNgLHX2w6TEuvBh71KByCc8OZo4gs08QKG7yJBrf38As5NsULVEr7FypcQQIqthMgpVEModOPRmvVBtQHulCwC9JWXsGQxYlAvLULSo24SaZq7OXmJwGTJF/s1600/themes+05.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlLSmBmjD0twO9XXfwzfTarhNgLHX2w6TEuvBh71KByCc8OZo4gs08QKG7yJBrf38As5NsULVEr7FypcQQIqthMgpVEModOPRmvVBtQHulCwC9JWXsGQxYlAvLULSo24SaZq7OXmJwGTJF/s1600/themes+05.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
The control exposes three dependency properties - &lt;i&gt;ItemsSource, SelectedItem &amp;amp; Scope&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
These allow the setting, selecting and scoping of the theme you want to apply to the app. As stated earlier the actual manipulating was done using a theme manager class, this means you aren&#39;t required to use UI (combo box) to manage themes. The theme manager implementation is shown below, as you can see it&#39;s pretty straight forward manipulation of resource dictionaries:&lt;br /&gt;
&lt;div class=&quot;gistLoad&quot; data-id=&quot;8223820&quot; id=&quot;gist8223820&quot;&gt;
&lt;br /&gt;
Loading gist ....&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
The following example shows how I use the control in a code-behind approach - there&#39;s an MVVM approach included in the code base on &lt;a href=&quot;https://github.com/oriches/Simple.Wpf.Themes&quot;&gt;github&lt;/a&gt;:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUwT9D38KhnkSKCw4mJeXuglue6F8lPgP8rk39ZrIaksSPIEm0qUlXp_WsYYlXpPuvT4t5bcbDP2AHP-BeN0WCJlaPdwpY5JCaGxQbgpc-8nxxYy-bO2nlMsAqlUDr2wb7wosjpcAI3vVR/s1600/themes+06.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUwT9D38KhnkSKCw4mJeXuglue6F8lPgP8rk39ZrIaksSPIEm0qUlXp_WsYYlXpPuvT4t5bcbDP2AHP-BeN0WCJlaPdwpY5JCaGxQbgpc-8nxxYy-bO2nlMsAqlUDr2wb7wosjpcAI3vVR/s1600/themes+06.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&amp;nbsp;with the following code behind, note the use of the Theme class to bring to together the user friendly name and the actual URI of the resource dictionary:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_LQZh9iBzAeDDL_n0SUfwpMZ_hKu0ffcO144hEzyRuEZG8jWTDsYWlfUI8wT9HV6n3NJISyyEgutu6IL6nhbxAiB6TLwIS0eRG0PSWBH1HWz7IND6rsjMfF1HsQ7xxCQzDGHUCCvpJKfe/s1600/themes+07.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_LQZh9iBzAeDDL_n0SUfwpMZ_hKu0ffcO144hEzyRuEZG8jWTDsYWlfUI8wT9HV6n3NJISyyEgutu6IL6nhbxAiB6TLwIS0eRG0PSWBH1HWz7IND6rsjMfF1HsQ7xxCQzDGHUCCvpJKfe/s1600/themes+07.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&amp;nbsp;and finally the following XAML definition:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwg7rjVQthihhHvL4c8ApzlTCGGiRCkELB6XzFXkGCL8nBaLPgi18evZLBfBxJfD-rvQgMqxrs4aVj8MnmpSb1LEvwbOg6N3tDm1XbrRScNYPohH6m3l2LQm5HgisQS81aSZl2m7q0oHP2/s1600/themes+08.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwg7rjVQthihhHvL4c8ApzlTCGGiRCkELB6XzFXkGCL8nBaLPgi18evZLBfBxJfD-rvQgMqxrs4aVj8MnmpSb1LEvwbOg6N3tDm1XbrRScNYPohH6m3l2LQm5HgisQS81aSZl2m7q0oHP2/s1600/themes+08.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Hopefully you can see you don&#39;t need to actually use the ThemeManager class directly, this is done for you by the Theme user control.&lt;br /&gt;
&lt;br /&gt;
I&#39;ve pushed the code up onto &lt;a href=&quot;https://github.com/oriches/Simple.Wpf.Themes&quot;&gt;github&lt;/a&gt; and as a nuget &lt;a href=&quot;https://www.nuget.org/packages/Simple.Wpf.Themes/&quot;&gt;package&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://awkwardcoder.blogspot.com/feeds/1265736830931200648/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://awkwardcoder.blogspot.com/2014/01/managing-themes-in-wpf.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/1265736830931200648'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/1265736830931200648'/><link rel='alternate' type='text/html' href='http://awkwardcoder.blogspot.com/2014/01/managing-themes-in-wpf.html' title='Managing themes in WPF'/><author><name>awkwardcoder</name><uri>http://www.blogger.com/profile/09746266491429238639</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNCVrxgZI0ysSe04Lq2lyQfaYkLNVLBhLda8ryfijkXIytzt_8m2LpnVZqeEjyv3K_DkRQY6nUCjqVapwc3GZCzWZMa7snTHxSYXfBqPkTLMsdoMowuwzBMQbdlaYpwQ/s220/PXL_20210316_143926215.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoGUuGoc3Z8tCGEIXdD-p3bw5dOlSX4mlTdZr6nQq7i-SURnAGy0Zbql41GYP8gTR9BkcAOB9r1cAXXXrrWn1quaM0IMI737nxiL-wCCAfeeVWGINqVvVXfgeHEYYLAogzSRA8QBwI_VXN/s72-c/themes+01.png" height="72" width="72"/><thr:total>0</thr:total><georss:featurename>London N16, UK</georss:featurename><georss:point>51.5623078 -0.076435299999957351</georss:point><georss:box>51.5228228 -0.15711629999995735 51.6017928 0.0042457000000426515</georss:box></entry><entry><id>tag:blogger.com,1999:blog-2559668977390861004.post-1277839118367813975</id><published>2013-12-27T21:13:00.000+00:00</published><updated>2013-12-29T17:01:58.510+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="C#"/><category scheme="http://www.blogger.com/atom/ns#" term="Development"/><category scheme="http://www.blogger.com/atom/ns#" term="F#"/><category scheme="http://www.blogger.com/atom/ns#" term="MVVM"/><category scheme="http://www.blogger.com/atom/ns#" term="UI"/><category scheme="http://www.blogger.com/atom/ns#" term="WPF"/><title type='text'>Simple F# REPL in WPF - part 3</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
In this post I&#39;m going to talk about the WPF user control I&#39;m going to use to display the output from the F# Interactive executable, the previous posts (&lt;a href=&quot;http://awkwardcoder.blogspot.co.uk/2013/12/simple-f-repl-in-wpf-part-1.html&quot;&gt;here&lt;/a&gt; &amp;amp; &lt;a href=&quot;http://awkwardcoder.blogspot.co.uk/2013/12/simple-f-repl-in-wpf-part-2.html&quot;&gt;here&lt;/a&gt;) talked about manipulating the standard input &amp;amp; output streams of the executable to provide the following interface:&lt;br /&gt;
&lt;div class=&quot;gistLoad&quot; data-id=&quot;8147812&quot; id=&quot;gist8147812&quot;&gt;
&lt;br /&gt;
Loading gist ....&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
The control will render any values generated by the Output property on the interface, the property is an Rx stream which generates a new value when ever the F# Interactive executable outputs a line.&lt;br /&gt;
&lt;br /&gt;
The control has basic &lt;a href=&quot;http://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop&quot;&gt;REPL&lt;/a&gt; semantics - user enters a line of text, the line is executed and the output is printed to the screen. The F# Interactive window in Visual Studio is the implementation I&#39;ll be copying.&lt;br /&gt;
&lt;br /&gt;
I had a look around and found &#39;WPF Terminal&#39; on &lt;a href=&quot;http://wpfterminal.codeplex.com/&quot;&gt;CodePlex&lt;/a&gt;&amp;nbsp;it looked promising - fulfills the REPL requirements, until I realised it&#39;s using a &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/system.windows.controls.textbox(v=vs.110).aspx&quot;&gt;TextBox&lt;/a&gt;&amp;nbsp;for the rendeing. With a TextBox the&amp;nbsp;text can only be one colour and I need the ability to show errors in a different colour. Also I wanted the ability to define the terminal prompt used.&lt;br /&gt;
&lt;br /&gt;
I realised I needed to use a &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/system.windows.controls.richtextbox(v=vs.100).aspx&quot;&gt;RichTextBox&lt;/a&gt; to get the UI behaviour I wanted, this meant writing my own control.&lt;br /&gt;
&lt;br /&gt;
Before showing the key parts of the implementation, lets look at the finished control used in a couple of test apps:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkahJgqkCGYuAm_neqV_jB9a9BoVZUco31BGbJ_9DgsaBwqZ1UgvhfWTXAUQIwI1OTaeAdDAVB8NYSTjQOeFidhZ-JJ_HS-7-0Ai8JrCmF8KPESc-eCBbBz5C11HlTMWYB_FgB0AvI-f22/s1600/wpf+fsharp+repl+12.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkahJgqkCGYuAm_neqV_jB9a9BoVZUco31BGbJ_9DgsaBwqZ1UgvhfWTXAUQIwI1OTaeAdDAVB8NYSTjQOeFidhZ-JJ_HS-7-0Ai8JrCmF8KPESc-eCBbBz5C11HlTMWYB_FgB0AvI-f22/s1600/wpf+fsharp+repl+12.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
This has the following XAML definition, as you can see it&#39;s using several custom dependency properties, these are explained later:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0AWUAAQrxGr2P4aWgmI6ZPWutam6pr4JKf9g4_wWsBg-wbXjkky0wrh7OH050kTXb9EMNRM70croiqvox1HnqaJluJKNrZOJvQMhzWcQT4xgU6s3VBY7UYhCWwn-cQN-JSdJrsoXwsa-q/s1600/wpf+fsharp+repl+13.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0AWUAAQrxGr2P4aWgmI6ZPWutam6pr4JKf9g4_wWsBg-wbXjkky0wrh7OH050kTXb9EMNRM70croiqvox1HnqaJluJKNrZOJvQMhzWcQT4xgU6s3VBY7UYhCWwn-cQN-JSdJrsoXwsa-q/s1600/wpf+fsharp+repl+13.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Another example used as a log window (inside a WPF app):&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-5AWKyXlioKkD5ZnSzkTtkCApaWcxNi_NN8NsrtbmrlwTN2QzfjM8OwWcnpcZCH4JRITmhXDKYIpJMR0J0WueENAKz5kj3ot8iHGEiQ8Yl_B6FGnW5HdNg74WiqLrOJIytQW2Wr5HVm6b/s1600/wpf+fsharp+repl+14.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-5AWKyXlioKkD5ZnSzkTtkCApaWcxNi_NN8NsrtbmrlwTN2QzfjM8OwWcnpcZCH4JRITmhXDKYIpJMR0J0WueENAKz5kj3ot8iHGEiQ8Yl_B6FGnW5HdNg74WiqLrOJIytQW2Wr5HVm6b/s1600/wpf+fsharp+repl+14.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
And this has the following XAML definition:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3gOq7BRLEJjnyd1myxQezeMWEauLYujsgUSpvtgr8B2VeVIX6tcm9sHUh9jGZyVSqDulDrp-riEtE_0dyyvAkqk0kj2EoSHjC2BAKBK7XeI0FS5fhvV90dr6zwPcZMcF1NpnDWSAqb3yc/s1600/wpf+fsharp+repl+15.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3gOq7BRLEJjnyd1myxQezeMWEauLYujsgUSpvtgr8B2VeVIX6tcm9sHUh9jGZyVSqDulDrp-riEtE_0dyyvAkqk0kj2EoSHjC2BAKBK7XeI0FS5fhvV90dr6zwPcZMcF1NpnDWSAqb3yc/s1600/wpf+fsharp+repl+15.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Hopefully it&#39;s obvious looking at these two different uses that there isn&#39;t any implementation inside the control apart from how to show the bound data (ItemsSource property) - the control only deals with UI concerns, as any View in an MVC implementation should only do.&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;What does the implementation look like?&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
As I said earlier, this control derives from RichTextBox, the derived class &#39;Terminal&#39; defines the following event &amp;amp; dependancy properties - you can see some of these used in the above XAML screenshots:&lt;br /&gt;
&lt;div class=&quot;gistLoad&quot; data-id=&quot;8151554&quot; id=&quot;gist8151554&quot;&gt;
&lt;br /&gt;
Loading gist ....&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
Hopefully the use and behaviour of these is obvious, but if not the most important three are:&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;LineEntered&lt;/b&gt; - &lt;i&gt;event is fired when ever the user press the Enter key&lt;/i&gt;,&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Line&lt;/b&gt; - &lt;i&gt;currently entered line by the user,&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;ItemsSource &lt;/b&gt;- &lt;i&gt;data displayed above the Line, this would be a collection implementing the IEnumerable interface, you can define the ItemDisplayPath if you&#39;re binding a complex type not a simple type (string).&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
I&#39;m not going to show the complete implementation because it&#39;s over 600 lines, but the most important method is the intercepting of every key press using the override&amp;nbsp;OnPreviewKeyDown. This allows the control to prevent or allow certain key presses:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxLHfUDA4I39Z2wCNxuUaiqQIE4ZWwZuhGxBtOFM3vXuF_OShev0fsVOXshubVT9SSw4aRz-9mjOcLLRADnxL8uRdjXBa7kB-qFMgDHV_soUCHFt0ldSNr8YJ-A7MbqSz0up_Nf6dNaZkz/s1600/wpf+fsharp+repl+16.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxLHfUDA4I39Z2wCNxuUaiqQIE4ZWwZuhGxBtOFM3vXuF_OShev0fsVOXshubVT9SSw4aRz-9mjOcLLRADnxL8uRdjXBa7kB-qFMgDHV_soUCHFt0ldSNr8YJ-A7MbqSz0up_Nf6dNaZkz/s1600/wpf+fsharp+repl+16.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
When dealing with a RichTextBox you have to understand the&amp;nbsp;content&amp;nbsp;you see on the screen isn&#39;t what you&#39;re going&amp;nbsp;to manipulate when you&#39;re trying to add, remove or edit content. &amp;nbsp;You do this using instances of a&amp;nbsp;&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/system.windows.documents.textpointer(v=vs.100).aspx&quot;&gt;TextPointer&lt;/a&gt;&amp;nbsp;- they represent a position within in the &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/system.windows.documents.flowdocument(v=vs.100).aspx&quot;&gt;FlowDocument&lt;/a&gt; of the RichTextBox.&lt;br /&gt;
&lt;br /&gt;
The constructor is shown below, as you can see I&#39;m creating the FlowDocument with a &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/system.windows.documents.paragraph(v=vs.100).aspx&quot;&gt;Paragraph&lt;/a&gt;, it then adds a &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/system.windows.documents.run(v=vs.100).aspx&quot;&gt;Run&lt;/a&gt; which represents the Prompt in the UI, doing this allows the manipulation of the content later. This is because from a terminal window point of view the text entered after prompt is the important part:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgA_TqrTEzfufvdkCo3OjbYUpcmV2RNfLxV0sty7PsL2PuQXHK7K4RYbttwEKafarVXLSBnXeNKKwCz5_tjz54jTVPptH-X-0T6EeemRTaKBf_O-gMcU0z00cwqsyoXK6PxYF4PPL1IRTzo/s1600/wpf+fsharp+repl+17.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgA_TqrTEzfufvdkCo3OjbYUpcmV2RNfLxV0sty7PsL2PuQXHK7K4RYbttwEKafarVXLSBnXeNKKwCz5_tjz54jTVPptH-X-0T6EeemRTaKBf_O-gMcU0z00cwqsyoXK6PxYF4PPL1IRTzo/s1600/wpf+fsharp+repl+17.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
The following screenshot shows the delete key handler, it&#39;s probably the simplest key handler in the control, all it does is compare the current caret position to the end of the prompt and if it is greater than the caret then the delete key can be processed:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfn-S6GrJCdBhnnzqK1lJwoI2OBtbHajn26Zy46_AxymXWrh01xfj0I7lS3PBPLBekllE9x20QGs58j8Wq-7o14CiYP5awV53QcSOzxSkCX09pQRoTUHeA7z3EA000XZ8YdcS_1dlHaIfh/s1600/wpf+fsharp+repl+18.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfn-S6GrJCdBhnnzqK1lJwoI2OBtbHajn26Zy46_AxymXWrh01xfj0I7lS3PBPLBekllE9x20QGs58j8Wq-7o14CiYP5awV53QcSOzxSkCX09pQRoTUHeA7z3EA000XZ8YdcS_1dlHaIfh/s1600/wpf+fsharp+repl+18.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
I&#39;ve pushed the code into the wild as both a GitHub &lt;a href=&quot;https://github.com/oriches/Simple.Wpf.Terminal&quot;&gt;repo&lt;/a&gt; and as a nuget &lt;a href=&quot;https://www.nuget.org/packages/Simple.Wpf.Terminal/&quot;&gt;package&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
In the next part of this series I&#39;ll bring it all together in an MVVM based solution.&lt;br /&gt;
&lt;br /&gt;
Note: The F# Interactive screen shot was taken from the &lt;a href=&quot;https://github.com/oriches/Simple.Wpf.FSharp.Repl&quot;&gt;Simple.Wpf.FSharp.Repl&lt;/a&gt; GitHub repo.&lt;br /&gt;
&lt;br /&gt;
Note: The log window screen shot was taken from the &lt;a href=&quot;https://github.com/oriches/Simple.Wpf.Composition&quot;&gt;Simple.Wpf.Composition&lt;/a&gt; GitHub repo, select &#39;Logging Workspace&#39; from the drop down and click Add.&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;script src=&quot;https://raw.github.com/moski/gist-Blogger/master/public/gistLoader.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://awkwardcoder.blogspot.com/feeds/1277839118367813975/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://awkwardcoder.blogspot.com/2013/12/simple-f-repl-in-wpf-part-3.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/1277839118367813975'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/1277839118367813975'/><link rel='alternate' type='text/html' href='http://awkwardcoder.blogspot.com/2013/12/simple-f-repl-in-wpf-part-3.html' title='Simple F# REPL in WPF - part 3'/><author><name>awkwardcoder</name><uri>http://www.blogger.com/profile/09746266491429238639</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNCVrxgZI0ysSe04Lq2lyQfaYkLNVLBhLda8ryfijkXIytzt_8m2LpnVZqeEjyv3K_DkRQY6nUCjqVapwc3GZCzWZMa7snTHxSYXfBqPkTLMsdoMowuwzBMQbdlaYpwQ/s220/PXL_20210316_143926215.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkahJgqkCGYuAm_neqV_jB9a9BoVZUco31BGbJ_9DgsaBwqZ1UgvhfWTXAUQIwI1OTaeAdDAVB8NYSTjQOeFidhZ-JJ_HS-7-0Ai8JrCmF8KPESc-eCBbBz5C11HlTMWYB_FgB0AvI-f22/s72-c/wpf+fsharp+repl+12.png" height="72" width="72"/><thr:total>0</thr:total><georss:featurename>London N16, UK</georss:featurename><georss:point>51.5623078 -0.076435299999957351</georss:point><georss:box>51.5228228 -0.15711629999995735 51.6017928 0.0042457000000426515</georss:box></entry><entry><id>tag:blogger.com,1999:blog-2559668977390861004.post-177483014663136387</id><published>2013-12-19T22:39:00.000+00:00</published><updated>2013-12-20T00:03:44.776+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="C#"/><category scheme="http://www.blogger.com/atom/ns#" term="Development"/><category scheme="http://www.blogger.com/atom/ns#" term="F#"/><category scheme="http://www.blogger.com/atom/ns#" term="MVVM"/><category scheme="http://www.blogger.com/atom/ns#" term="UI"/><category scheme="http://www.blogger.com/atom/ns#" term="WPF"/><title type='text'>Simple F# REPL in WPF - part 2</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
In the first &lt;a href=&quot;http://awkwardcoder.blogspot.co.uk/2013/12/simple-f-repl-in-wpf-part-1.html&quot;&gt;post &lt;/a&gt;I&#39;ve managed to abstract the use of the F# interactive process behind an interface - it can now be used from an .net application:&lt;br /&gt;
&lt;div class=&quot;gistLoad&quot; data-id=&quot;8046336&quot; id=&quot;gist8046336&quot;&gt;
&lt;br /&gt;
Loading gist ....&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
The goal of the abstraction was to make it easy to use and I believe it has, but after reviewing the interface and implementation there will be responsiveness problems when I try and use it in an actual WPF UI.&lt;br /&gt;
&lt;br /&gt;
I reckon this because the F# interactive process is running &#39;&lt;i&gt;out of process&lt;/i&gt;&#39; and the fact that any script I want to execute has to be written to the input stream and then interpreted &amp;amp; executed. This means there&#39;s going to be an appreciable delay in the responsiveness of the UI - a delay long enough to be observed by the user or at worst allow the user to enter another script before the previous has been executed and therefore screw up the output.&lt;br /&gt;
&lt;br /&gt;
This can be observed in the console test harness as well, if I enter text before the initial setup has been completed it screws up an error - I&#39;ve highlighted the text and the error it generated:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuRFW-tYm1bDIxESj78T_kedcuVQgBlZ3LxQxxtCX9q2GtyxfHDQYiewOdBmUChU48ZuondgnksA5vI2Uj2Gt7sK_B3C0-Du0Crhod-NIHj2RNpiYY6TukDTNj9FQpqKqNQZ6ddSCkfBf6/s1600/wpf+fsharp+repl+09.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuRFW-tYm1bDIxESj78T_kedcuVQgBlZ3LxQxxtCX9q2GtyxfHDQYiewOdBmUChU48ZuondgnksA5vI2Uj2Gt7sK_B3C0-Du0Crhod-NIHj2RNpiYY6TukDTNj9FQpqKqNQZ6ddSCkfBf6/s1600/wpf+fsharp+repl+09.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
In a UI based application you typically disable controls when you want to prevent the user from entering text (data) when it&#39;s not applicable - using XAML framework properties like IsEnabled or IsReadOnly.&lt;br /&gt;
&lt;br /&gt;
Exposing information to manipulate the XAML properties will be key to preventing user input at the wrong times during the engine execution cycle. Currently the interface doesn&#39;t expose any information about the current state of the F# interactive process - the name of the interface should have given me a clue, it contains the word &#39;engine&#39;. Engines usually have a set of predefined states - stopped, starting, stated, idling etc.&lt;br /&gt;
&lt;br /&gt;
I need to expose state of the REPL engine through the interface - this will allow me to enable\disable controls in any WPF UI. I&#39;ve decided on the following states and these are exposed via an IObservable&amp;lt;state&amp;gt; property on the interface called &#39;State&#39;:&lt;br /&gt;
&lt;div class=&quot;gistLoad&quot; data-id=&quot;8047059&quot; id=&quot;gist8047059&quot;&gt;
&lt;br /&gt;
Loading gist ....&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
The observable property will pump when ever there is a state change in the engine and this will allow any UI to do what ever it wants when a state transition occurs. Implementing this in the engine is easy, in fact it improves the implementation because the control flow is easier to understand, shown below is the implementation of the Stop method:&lt;br /&gt;
&lt;div class=&quot;gistLoad&quot; data-id=&quot;8047217&quot; id=&quot;gist8047217&quot;&gt;
&lt;br /&gt;
Loading gist ....&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
Hooking this new property up in the console test harness is easy:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCb4VcYBSs2qI4AEg7sK6XG6yGv7u-CpuupNxPlP3jowybPVJRLWu6fKM19zHDHAsIdf7CEaQFQiaEv2wC56xDBF19turSn9VIAtw3OVNK7RFX2oJI5eqAEPwqewaxSC0DVlSSUwiHG_R-/s1600/wpf+fsharp+repl+10.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCb4VcYBSs2qI4AEg7sK6XG6yGv7u-CpuupNxPlP3jowybPVJRLWu6fKM19zHDHAsIdf7CEaQFQiaEv2wC56xDBF19turSn9VIAtw3OVNK7RFX2oJI5eqAEPwqewaxSC0DVlSSUwiHG_R-/s1600/wpf+fsharp+repl+10.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
When running this produces the following results in the output window of visual studio:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIJyJU5Z36gXHrAoBxCli-nB58TTmOAYOYYcxt19Oe-NAMKRquLduwW6KbToaR077OhFXk-rwojDPrMuXoRaT7gvkfVQbumHJH8zlLKs0v8jAlt53_Gq7TxcVrmDk2JK10Z59-k1U9UV1Y/s1600/wpf+fsharp+repl+11.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIJyJU5Z36gXHrAoBxCli-nB58TTmOAYOYYcxt19Oe-NAMKRquLduwW6KbToaR077OhFXk-rwojDPrMuXoRaT7gvkfVQbumHJH8zlLKs0v8jAlt53_Gq7TxcVrmDk2JK10Z59-k1U9UV1Y/s1600/wpf+fsharp+repl+11.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
The future WPF UI will disable the ability to execute a script while the state is not equal to &#39;Running&#39;.&lt;br /&gt;
&lt;br /&gt;
In the next post I&#39;ll actually get around to using the implementation in WPF :)&lt;/div&gt;
&lt;script src=&quot;https://raw.github.com/moski/gist-Blogger/master/public/gistLoader.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;&lt;br /&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://awkwardcoder.blogspot.com/feeds/177483014663136387/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://awkwardcoder.blogspot.com/2013/12/simple-f-repl-in-wpf-part-2.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/177483014663136387'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/177483014663136387'/><link rel='alternate' type='text/html' href='http://awkwardcoder.blogspot.com/2013/12/simple-f-repl-in-wpf-part-2.html' title='Simple F# REPL in WPF - part 2'/><author><name>awkwardcoder</name><uri>http://www.blogger.com/profile/09746266491429238639</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNCVrxgZI0ysSe04Lq2lyQfaYkLNVLBhLda8ryfijkXIytzt_8m2LpnVZqeEjyv3K_DkRQY6nUCjqVapwc3GZCzWZMa7snTHxSYXfBqPkTLMsdoMowuwzBMQbdlaYpwQ/s220/PXL_20210316_143926215.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuRFW-tYm1bDIxESj78T_kedcuVQgBlZ3LxQxxtCX9q2GtyxfHDQYiewOdBmUChU48ZuondgnksA5vI2Uj2Gt7sK_B3C0-Du0Crhod-NIHj2RNpiYY6TukDTNj9FQpqKqNQZ6ddSCkfBf6/s72-c/wpf+fsharp+repl+09.png" height="72" width="72"/><thr:total>0</thr:total><georss:featurename>London N16, UK</georss:featurename><georss:point>51.5623078 -0.076435299999957351</georss:point><georss:box>51.5228228 -0.15711629999995735 51.6017928 0.0042457000000426515</georss:box></entry><entry><id>tag:blogger.com,1999:blog-2559668977390861004.post-2820623663738414542</id><published>2013-12-15T21:22:00.002+00:00</published><updated>2013-12-19T23:56:46.067+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="C#"/><category scheme="http://www.blogger.com/atom/ns#" term="Development"/><category scheme="http://www.blogger.com/atom/ns#" term="F#"/><category scheme="http://www.blogger.com/atom/ns#" term="WPF"/><title type='text'>Simple F# REPL in WPF - part 1</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;I&#39;m currently working on a C# WPF app which makes use of F# as a modelling language to dynamically create data points from static data in the system. The user enters the F# in the UI via a code editor window, it is then validated &amp;amp; compiled by back-end services for use in reporting &amp;amp; charting views. This all works well but the feedback loop is rather long - instead of being seconds it can take a couple of minutes! What would be nice is a &lt;a href=&quot;http://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop&quot;&gt;REPL&lt;/a&gt; window in the UI, which would allow the user to test the F# code snippet they&#39;ve just created without having to communicate with the back-end services.&lt;br /&gt;
&lt;br /&gt;
What follows is the first in a set of posts (not sure how many there will be) in the creating of a simple &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/dd233175.aspx&quot;&gt;F# REPL&lt;/a&gt; UI for use in an WPF app - the end goal is to be able to include a WPF user control in a XAML data template.&lt;br /&gt;
&lt;br /&gt;
The F# interactive window in Visual Studio is done using the &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/dd233175.aspx&quot;&gt;fsi.exe&lt;/a&gt; executable, this functionality is what I want to achieve in any WPF app - t&lt;i&gt;he ability for the user to enter some F# code and execute and get the results displayed immediately&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
The F# interactive (fsi.exe) executable provide in visual studio is own &amp;amp; copyrighted by Mircosoft so using this is out of the question. Fortunately F# has been open sourced and is available &lt;a href=&quot;http://fsharp.github.io/fsharp/&quot;&gt;here&lt;/a&gt; - I&#39;ll be using the latest version of the F# code base (v3.0).&lt;br /&gt;
&lt;br /&gt;
Shown below is the F# interactive window from visual studio, and as you can I see I&#39;ve enter a simple F# expression which has been executed&amp;nbsp; - &lt;i&gt;let answer = 42.00;;&lt;/i&gt;&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgimrqRbg52npFBtHjQXgJv6LDbJyyIhaQScLScEgW3n78o3lbhxMw9-2KJHh7MIXHIjMi9uv4m3pHgy4qpdgoPpbF-X2lB6zpHmealiYdeg23WVHMjGjmc7a3gRSaY1-wSKArz5gj2V6C0/s1600/wpf+fsharp+repl+01.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgimrqRbg52npFBtHjQXgJv6LDbJyyIhaQScLScEgW3n78o3lbhxMw9-2KJHh7MIXHIjMi9uv4m3pHgy4qpdgoPpbF-X2lB6zpHmealiYdeg23WVHMjGjmc7a3gRSaY1-wSKArz5gj2V6C0/s1600/wpf+fsharp+repl+01.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;Menu: &lt;i&gt;View -&amp;gt; Other Windows -&amp;gt; F# Interactive&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
My goal for this post is to use the F# interactive executable behind the following interface - this will then allow me to easily host and use the F# interactive executable in any .net app in the future - for this post the host will be a console application:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4BiCvVOTm7xnuUpZDMR7iLBM6-KheuQuQQXitU0ddUZPDkPRDMFswiH4osI2VU82vmAA2kx3fg8Py-smGdT6uskOVqGC3V2WIL7fCkcG2XbmU0xVZaKngJzeQ_k4Z8AqtVK2GC8HkLhC8/s1600/wpf+fsharp+repl+06.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4BiCvVOTm7xnuUpZDMR7iLBM6-KheuQuQQXitU0ddUZPDkPRDMFswiH4osI2VU82vmAA2kx3fg8Py-smGdT6uskOVqGC3V2WIL7fCkcG2XbmU0xVZaKngJzeQ_k4Z8AqtVK2GC8HkLhC8/s1600/wpf+fsharp+repl+06.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;I&#39;m using &lt;a href=&quot;http://rx.codeplex.com/&quot;&gt;Reactive Extensions&lt;/a&gt; to expose the output from the F# interactive executable to the host app. Hopefully the interface is self explanatory - but if not, the idea is you will start the F# REPL engine and then &#39;&lt;i&gt;Execute&lt;/i&gt;&#39; F# scripts, and you observe any output via the Rx stream exposed as the &#39;&lt;i&gt;Output&lt;/i&gt;&#39; property.&lt;br /&gt;
&lt;br /&gt;
Just like in visual studio I&#39;ll be using the F# interactive as an out of process executable and manipulating the &lt;a href=&quot;http://en.wikipedia.org/wiki/Standard_streams&quot;&gt;standard input &amp;amp; output streams&lt;/a&gt; to communicate. This is done using an instance of the &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/system.diagnostics.process(v=vs.110).aspx&quot;&gt;Process&lt;/a&gt; class and redirecting the input &amp;amp; output streams, shown below is how I&#39;m creating the F# interactive process:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNL_pDuYDNHFyPWsslmFft5N50dyj3zozMCCnMAvdNDTf5kpvd_sFPlNCUorBEG_ui7OTSIY22Kw4z3Wf64wPzzTNqI8dhMDVJ2Zb1YmD3lAbEbyUPxqpA6bELoR3kzOrz4ED_7CsQR3IV/s1600/wpf+fsharp+repl+02.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNL_pDuYDNHFyPWsslmFft5N50dyj3zozMCCnMAvdNDTf5kpvd_sFPlNCUorBEG_ui7OTSIY22Kw4z3Wf64wPzzTNqI8dhMDVJ2Zb1YmD3lAbEbyUPxqpA6bELoR3kzOrz4ED_7CsQR3IV/s1600/wpf+fsharp+repl+02.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;The input stream is used as follows -&lt;i&gt; the stream used to send text input to the process:&lt;/i&gt;&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjLuvtqPGAr_5h4P59hrgjk-w6tZqF2KbDc1YRRsT7z-pEw1ps4mCzOLAIhNar5OFuic4x_qR2WZULg8s-E-6zoXaRdED5uQqNz6HmteGbvGYVDK3OLvjS31IkK_ZvIH2yJe6ZSJqSguXkN/s1600/wpf+fsharp+repl+03.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjLuvtqPGAr_5h4P59hrgjk-w6tZqF2KbDc1YRRsT7z-pEw1ps4mCzOLAIhNar5OFuic4x_qR2WZULg8s-E-6zoXaRdED5uQqNz6HmteGbvGYVDK3OLvjS31IkK_ZvIH2yJe6ZSJqSguXkN/s1600/wpf+fsharp+repl+03.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;Using the output stream is a little more complicated because reading a line of text from the process is a blocking operation in v4.0 of .net&amp;nbsp; - a simple extension method gets around this issue:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_0ZdAcRKomJ4hbwUq8RKgktEwBZt1xKOp1tYV0PzQX_JJdkrPl4oY_QCfawR_pR-hr1ZVq_l2q7px_3CT_LXjeKVzbbUkYQCw_TE6GgaZdSG4-VKiMPQftx5HWlX3UB0ZAm3npuGhqks_/s1600/wpf+fsharp+repl+04.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_0ZdAcRKomJ4hbwUq8RKgktEwBZt1xKOp1tYV0PzQX_JJdkrPl4oY_QCfawR_pR-hr1ZVq_l2q7px_3CT_LXjeKVzbbUkYQCw_TE6GgaZdSG4-VKiMPQftx5HWlX3UB0ZAm3npuGhqks_/s1600/wpf+fsharp+repl+04.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;As you can see this is an infinite loop - it will block the calling thread until the cancel is called on the CancellationTokenSource. To avoid this the code is executed asynchronously using the Rx method &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/hh211971(v=vs.103).aspx&quot;&gt;Observable.Start&lt;/a&gt;, below is the complete method block for reading the output stream:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTFNUJqKAQk2KiCusdgJV7_7PZ40mCmb5mbSU-S9B0pLaFrGUdYmd8xsrRHMa0O9cG6hyphenhyphenmryxxPwGb9CZMwifC_-Ecml-i3VAEjvTZ65oMGysrYMsIJCNaYFs_N3869QZypumtccyP1Elk/s1600/wpf+fsharp+repl+05.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTFNUJqKAQk2KiCusdgJV7_7PZ40mCmb5mbSU-S9B0pLaFrGUdYmd8xsrRHMa0O9cG6hyphenhyphenmryxxPwGb9CZMwifC_-Ecml-i3VAEjvTZ65oMGysrYMsIJCNaYFs_N3869QZypumtccyP1Elk/s1600/wpf+fsharp+repl+05.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;The complete REPL engine is shown below, the F# interactive process is created on the calling thread with the output stream observed on a task pool thread using Rx. There is logic to safely shutdown process &amp;amp; background thread.&amp;nbsp; The API isn&#39;t designed to be thread-safe as I&#39;ll be using this in a WPF app and it will only be called from the UI (dispatcher) thread.&lt;br /&gt;
&lt;div class=&quot;gistLoad&quot; data-id=&quot;8048316&quot; id=&quot;gist8048316&quot;&gt;Loading ....&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;The required F# interactive binaries will be added as a &#39;&lt;i&gt;solution folder&lt;/i&gt;&#39; because I couldn&#39;t find a relevant nuget package - hopefully I&#39;ve just not been able to find it:&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwUSPyDpAyVJ1rj5sb_B7Y8VmOVsK2QFv_wsmCvu91_DUrEtuLrkpf4iJvy1cMNdktmRucUxL6R04jJVaq5DihlEPqleUajmD7WciAofzF3g3XiXgncPBitpM5CeDZ5QX4dkdOnMpDL9Ki/s1600/wpf+fsharp+repl+08.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwUSPyDpAyVJ1rj5sb_B7Y8VmOVsK2QFv_wsmCvu91_DUrEtuLrkpf4iJvy1cMNdktmRucUxL6R04jJVaq5DihlEPqleUajmD7WciAofzF3g3XiXgncPBitpM5CeDZ5QX4dkdOnMpDL9Ki/s1600/wpf+fsharp+repl+08.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Testing this is now easy in a simple console test harness, it&#39;s a bit strange to use a console app to test another console app which has been wrapped behind an interface but it demonstrates perfectly how easy this will be from WPF:&lt;/div&gt;&lt;div class=&quot;gistLoad&quot; data-id=&quot;8048344&quot; id=&quot;gist8048344&quot;&gt;Loading ....&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;With output looking very similar to the F# interactive executable, the only difference is the name of the executable in the title bar:&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjl0tbIyH-iCItDa0eb0HGEXOQjaBEvr8xlBXvcCOXLc0Smh_CaTAfO-7I6HPXcYSBNXAxwtKKRrU34HkLg2MIz88VW6GsrTVERibSEnoMeF8TGT2TEpi4uxJbcK_SAzs3YuyWfA4AK5W80/s1600/wpf+fsharp+repl+07.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjl0tbIyH-iCItDa0eb0HGEXOQjaBEvr8xlBXvcCOXLc0Smh_CaTAfO-7I6HPXcYSBNXAxwtKKRrU34HkLg2MIz88VW6GsrTVERibSEnoMeF8TGT2TEpi4uxJbcK_SAzs3YuyWfA4AK5W80/s1600/wpf+fsharp+repl+07.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;I&#39;ve pushed the code up onto &lt;a href=&quot;https://github.com/oriches/Simple.Wpf.FSharp.Repl&quot;&gt;github&lt;/a&gt;, I&#39;ll be adding the WPF parts to the code base over the next couple of posts.&lt;/div&gt;&lt;/div&gt;&lt;script src=&quot;https://raw.github.com/moski/gist-Blogger/master/public/gistLoader.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://awkwardcoder.blogspot.com/feeds/2820623663738414542/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://awkwardcoder.blogspot.com/2013/12/simple-f-repl-in-wpf-part-1.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/2820623663738414542'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/2820623663738414542'/><link rel='alternate' type='text/html' href='http://awkwardcoder.blogspot.com/2013/12/simple-f-repl-in-wpf-part-1.html' title='Simple F# REPL in WPF - part 1'/><author><name>awkwardcoder</name><uri>http://www.blogger.com/profile/09746266491429238639</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNCVrxgZI0ysSe04Lq2lyQfaYkLNVLBhLda8ryfijkXIytzt_8m2LpnVZqeEjyv3K_DkRQY6nUCjqVapwc3GZCzWZMa7snTHxSYXfBqPkTLMsdoMowuwzBMQbdlaYpwQ/s220/PXL_20210316_143926215.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgimrqRbg52npFBtHjQXgJv6LDbJyyIhaQScLScEgW3n78o3lbhxMw9-2KJHh7MIXHIjMi9uv4m3pHgy4qpdgoPpbF-X2lB6zpHmealiYdeg23WVHMjGjmc7a3gRSaY1-wSKArz5gj2V6C0/s72-c/wpf+fsharp+repl+01.png" height="72" width="72"/><thr:total>0</thr:total><georss:featurename>London N16, UK</georss:featurename><georss:point>51.5623078 -0.076435299999957351</georss:point><georss:box>51.5228228 -0.15711629999995735 51.6017928 0.0042457000000426515</georss:box></entry><entry><id>tag:blogger.com,1999:blog-2559668977390861004.post-1706082144073369591</id><published>2013-12-11T21:50:00.001+00:00</published><updated>2013-12-11T21:50:19.392+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Development"/><category scheme="http://www.blogger.com/atom/ns#" term="MVVM"/><category scheme="http://www.blogger.com/atom/ns#" term="WPF"/><title type='text'>MVVM anti-pattern: Using UI Message Bus to communicate between View Models &amp; Services</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
This anti-pattern is probably more applicable to large MVVM based applications, and it might even just be a pet dislike of mine. I better clarify what I mean, this pattern is known by different terms, it&#39;s also known as Event Broker (PRISM). It shouldn&#39;t be confused with an enterprise message bus, what I&#39;m talking about is a UI layer applicable pattern, which is used to communicate internally by the UI implementation. The UI might well still use an enterprise message bus to communicate with disparate backend systems.&lt;br /&gt;
&lt;br /&gt;
Shown below is a really simple interface &amp;amp; implementation of a message bus, this service would normally be a singleton instance shared between all view models &amp;amp; other services:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivPq7p4K50lbVIu-UHDuRZ_z0-Zz23u7BbwUF7GAMSVqEWuUe_Qp9VkaAbDn7A9nrc3K84x0WmczbsmRVvXHdZdqxiF-TYQ0pME9fxuCmNQvGGcgFlrZ6NicYVZIueCkNFFPyEhhNko1GD/s1600/ap+message+bus+01.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivPq7p4K50lbVIu-UHDuRZ_z0-Zz23u7BbwUF7GAMSVqEWuUe_Qp9VkaAbDn7A9nrc3K84x0WmczbsmRVvXHdZdqxiF-TYQ0pME9fxuCmNQvGGcgFlrZ6NicYVZIueCkNFFPyEhhNko1GD/s1600/ap+message+bus+01.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Conceptually as you can see all it does is connect a publisher to a consumer on a particular topic. Now this a very powerful concept and when used well. It provides a clean way to communicate between disparate view models &amp;amp; services in the UI.&lt;br /&gt;
&lt;br /&gt;
For me the ability to communicate this way, cross-cutting any structure you have for the view models, services &amp;amp; controllers seems wrong - when you&#39;ve gone to the effort to separate out the classes and logically grouped them this all seems to be undone by using a message bus.&lt;br /&gt;
&lt;br /&gt;
In larger MVVM applications you&#39;re more likely to have a controller sitting behind your main view model to orchestrate service communication and interaction between view models &amp;amp; services, and this is probably why I see this as an anti-pattern because it can destroy this structure. It almost could be considered another way to do the Service Locator pattern.&lt;br /&gt;
&lt;br /&gt;
Another downside (just as important IMO) comes when you&#39;re debugging or re-factoring a code base - how difficult can it be to find where a message came from or which subscriber is causing an issue, especially when the call stack has been lost because the subscriber is handling the message on another thread.&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://awkwardcoder.blogspot.com/feeds/1706082144073369591/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://awkwardcoder.blogspot.com/2013/12/mvvm-anti-pattern-using-ui-message-bus.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/1706082144073369591'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/1706082144073369591'/><link rel='alternate' type='text/html' href='http://awkwardcoder.blogspot.com/2013/12/mvvm-anti-pattern-using-ui-message-bus.html' title='MVVM anti-pattern: Using UI Message Bus to communicate between View Models &amp; Services'/><author><name>awkwardcoder</name><uri>http://www.blogger.com/profile/09746266491429238639</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNCVrxgZI0ysSe04Lq2lyQfaYkLNVLBhLda8ryfijkXIytzt_8m2LpnVZqeEjyv3K_DkRQY6nUCjqVapwc3GZCzWZMa7snTHxSYXfBqPkTLMsdoMowuwzBMQbdlaYpwQ/s220/PXL_20210316_143926215.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivPq7p4K50lbVIu-UHDuRZ_z0-Zz23u7BbwUF7GAMSVqEWuUe_Qp9VkaAbDn7A9nrc3K84x0WmczbsmRVvXHdZdqxiF-TYQ0pME9fxuCmNQvGGcgFlrZ6NicYVZIueCkNFFPyEhhNko1GD/s72-c/ap+message+bus+01.png" height="72" width="72"/><thr:total>0</thr:total><georss:featurename>London N16, UK</georss:featurename><georss:point>51.5623078 -0.076435299999957351</georss:point><georss:box>51.5228228 -0.15711629999995735 51.6017928 0.0042457000000426515</georss:box></entry><entry><id>tag:blogger.com,1999:blog-2559668977390861004.post-2905434418877869417</id><published>2013-11-28T23:17:00.002+00:00</published><updated>2013-11-28T23:21:12.883+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="C#"/><category scheme="http://www.blogger.com/atom/ns#" term="Development"/><category scheme="http://www.blogger.com/atom/ns#" term="MVVM"/><category scheme="http://www.blogger.com/atom/ns#" term="WPF"/><category scheme="http://www.blogger.com/atom/ns#" term="XAML"/><title type='text'>MVVM anti-pattern: Injecting the IoC container into a View Model</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
This is another anti-pattern I&#39;ve seen a lot recently, the dynamic use of the IoC container inside a view model to resolve child view models &amp;amp; services - service locator pattern: &lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5KO189p85yesyb6jwUqOmiYVOAVJwnqgAk35vLkz2ENbv6AvG5C-PYe5_kvJ1Ub4JrKT0V9mqgV8aP6QsP3VEplcTmeShbReYqmtGwMeFzkwXjwO-NyUQ_p0qzXyxcDpNKiWcDwpY5mXa/s1600/ap+injecting+container+01.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5KO189p85yesyb6jwUqOmiYVOAVJwnqgAk35vLkz2ENbv6AvG5C-PYe5_kvJ1Ub4JrKT0V9mqgV8aP6QsP3VEplcTmeShbReYqmtGwMeFzkwXjwO-NyUQ_p0qzXyxcDpNKiWcDwpY5mXa/s1600/ap+injecting+container+01.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
The service locator pattern has been around for a while - &lt;a href=&quot;http://martinfowler.com/articles/injection.html#UsingAServiceLocator&quot;&gt;Fowler&lt;/a&gt; was writing about this back in 2004!&lt;br /&gt;
&lt;br /&gt;
It&#39;s not a pattern that is specific to MVVM, it&#39;s a pattern associated with using DI &amp;amp; IoC, if you&#39;re doing MVVM you should be using DI &amp;amp; IoC&lt;i&gt;.&lt;/i&gt; A lot has also be written about this being an anti-pattern and I agree completely with &lt;a href=&quot;http://blog.ploeh.dk/2010/02/03/ServiceLocatorisanAnti-Pattern/&quot;&gt;Mark Seaman&lt;/a&gt; on the topic.&lt;br /&gt;
&lt;br /&gt;
For me why this is an anti-pattern for MVVM is for the following reasons: &lt;br /&gt;
&lt;ol style=&quot;text-align: left;&quot;&gt;&lt;/ol&gt;
&lt;b&gt;Breaks &lt;a href=&quot;http://en.wikipedia.org/wiki/SOLID_(object-oriented_design)&quot;&gt;SOLID&lt;/a&gt; principles &lt;/b&gt;-&lt;i&gt; the view model now has multiple responsibilities and not all dependencies are being explicitly injected. The view model is now responsible for the lifetime of anything it has resolved (this includes scope as well)&lt;/i&gt;, &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Encourages view models to become god-like objects&lt;/b&gt; - &lt;i&gt;they become bloated - all the implementation in a single view model, it&#39;s no better than a testable code-behind file&lt;/i&gt;,&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Makes unit testing brittle&lt;/b&gt;&amp;nbsp; - &lt;i&gt;when having to test such a view model you have either look through the whole class to see all the dependancies you need to mock or just try a &#39;hit &amp;amp; hope&#39; approach and keep running and refeactoring the test until it passes. Either way you end up with a lot of test setup which is a smell in it&#39;s own right and importantly greatly discourages a developer to write tests&lt;/i&gt;,&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;And generally destroys the structure and ethos of the MVC (MVVM) pattern&lt;/b&gt; - &lt;i&gt;if I can resolve anything anywhere eventually you&#39;ll end up with spaghetti code which has no discernable architecture and for me this is probably the most important point when dealing with a large XAML application.&amp;nbsp;&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
What&#39;s also interesting about the above example is the fact it actually mixes normal DI with service locator, injecting both other interfaces as well as the IContainer interface - neither one nor the other. The example wasn&#39;t contrived to do this it was taken from a real world example - with names changed to protect the innocent.&lt;i&gt;&amp;nbsp;&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
There are times when I believe using the service locator pattern is justified, but these are few and far between. An obvious one is when the creation of a class is costly in time or memory (if this was ever the scenario for me with a view model it would be a code smell and need to be refactored out).&lt;br /&gt;
&lt;br /&gt;
But if I &lt;i&gt;had &lt;/i&gt;to use a service locator I would be either injecting a strongly typed factory or by injecting a Func&amp;lt;T&amp;gt; - &lt;i&gt;all&lt;/i&gt; IoC containers support this feature. A couple of examples are shown below:&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBRwJ6Cf8tNEk6zqlbQkByuGCBuOD6zMER2IkrOZuzP7yDoTGBwPW-3Z6iAZne8nwis2Pme-z2zBFniBiVtu7lVVhL19n9Hz44svNXXab_jx58LJRrULrKZErPdKuohLyo0JSR2DUM8u2L/s1600/ap+injecting+container+02.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBRwJ6Cf8tNEk6zqlbQkByuGCBuOD6zMER2IkrOZuzP7yDoTGBwPW-3Z6iAZne8nwis2Pme-z2zBFniBiVtu7lVVhL19n9Hz44svNXXab_jx58LJRrULrKZErPdKuohLyo0JSR2DUM8u2L/s1600/ap+injecting+container+02.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://awkwardcoder.blogspot.com/feeds/2905434418877869417/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://awkwardcoder.blogspot.com/2013/11/mvvm-anti-pattern-injecting-ioc.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/2905434418877869417'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/2905434418877869417'/><link rel='alternate' type='text/html' href='http://awkwardcoder.blogspot.com/2013/11/mvvm-anti-pattern-injecting-ioc.html' title='MVVM anti-pattern: Injecting the IoC container into a View Model'/><author><name>awkwardcoder</name><uri>http://www.blogger.com/profile/09746266491429238639</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNCVrxgZI0ysSe04Lq2lyQfaYkLNVLBhLda8ryfijkXIytzt_8m2LpnVZqeEjyv3K_DkRQY6nUCjqVapwc3GZCzWZMa7snTHxSYXfBqPkTLMsdoMowuwzBMQbdlaYpwQ/s220/PXL_20210316_143926215.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5KO189p85yesyb6jwUqOmiYVOAVJwnqgAk35vLkz2ENbv6AvG5C-PYe5_kvJ1Ub4JrKT0V9mqgV8aP6QsP3VEplcTmeShbReYqmtGwMeFzkwXjwO-NyUQ_p0qzXyxcDpNKiWcDwpY5mXa/s72-c/ap+injecting+container+01.png" height="72" width="72"/><thr:total>0</thr:total><georss:featurename>London N16, UK</georss:featurename><georss:point>51.5623078 -0.076435299999957351</georss:point><georss:box>51.5228228 -0.15711629999995735 51.6017928 0.0042457000000426515</georss:box></entry><entry><id>tag:blogger.com,1999:blog-2559668977390861004.post-3868540137492185617</id><published>2013-11-18T22:13:00.002+00:00</published><updated>2013-11-18T22:16:54.473+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Development"/><category scheme="http://www.blogger.com/atom/ns#" term="MVVM"/><category scheme="http://www.blogger.com/atom/ns#" term="WPF"/><title type='text'>MVVM anti-pattern: View code behind with no implementation</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
I&#39;ve seen rather a lot of this anti-pattern recently, to be explicit about what I mean, lets define this in terms of a WPF user control. Imagine the code behind file is nothing more than the auto generated code, but the XAML file contains the usual controls and bindings:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTlfCIMAnre5Oekf9TiPWQZCeHzVADF8eePc_SX0oxAJ1VIFKgadA1n8pjkyiTSeDLRPtbv1UYcTp6qMYaKXpjWKA7bHDJlVzlVNdOaojAsRIAuqZRBU5ny-_GbxMW5xCBv5Ns-nyZZK7N/s1600/ap+no+code+behind+02.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTlfCIMAnre5Oekf9TiPWQZCeHzVADF8eePc_SX0oxAJ1VIFKgadA1n8pjkyiTSeDLRPtbv1UYcTp6qMYaKXpjWKA7bHDJlVzlVNdOaojAsRIAuqZRBU5ny-_GbxMW5xCBv5Ns-nyZZK7N/s1600/ap+no+code+behind+02.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjccJ8KxO7x5WNVkC3JyXbDHKh0l6b_pLWPABtITmpDFs1imHHIJ5cnYLhrk_X7RxWrRoNNKlFJXMlEnshb59f6RyWLrpMva3Fq9Qiug7d5T9zCYUQ9WujBpd7atCtSsXKhFalDzGJaPEdE/s1600/ap+no+code+behind+01.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjccJ8KxO7x5WNVkC3JyXbDHKh0l6b_pLWPABtITmpDFs1imHHIJ5cnYLhrk_X7RxWrRoNNKlFJXMlEnshb59f6RyWLrpMva3Fq9Qiug7d5T9zCYUQ9WujBpd7atCtSsXKhFalDzGJaPEdE/s1600/ap+no+code+behind+01.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
The user control is used in one or more data templates as follows:&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuAfPf0J-8l-5THOY-8Sjb09a8jaJfEoLpUVEXsryJQxlI7od4kRmFUw7nINA2ZhLI9HnnhkQ5y4CWcVm5YokuSS3xjafTtpQSa_I7iAYSgmT7f0jkYbT9QeqfuKq1UxcT3xsrUWm9zaz-/s1600/ap+no+code+behind+03.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuAfPf0J-8l-5THOY-8Sjb09a8jaJfEoLpUVEXsryJQxlI7od4kRmFUw7nINA2ZhLI9HnnhkQ5y4CWcVm5YokuSS3xjafTtpQSa_I7iAYSgmT7f0jkYbT9QeqfuKq1UxcT3xsrUWm9zaz-/s1600/ap+no+code+behind+03.png&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
The reason this is an anti-pattern is because it has introduced files into the solution which aren&#39;t required: &lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzn4EC8-CQF4wQaujEJrPVHMKVS9zD4zbot_0DWQhiKzsFTJtO7v_EK-s6_MqKMcNMkIs7z6Byh3FVhL92CEh-u4_oO1s4XBa014bFSB2VLTAEhzhv35gUEUBcYjvMDDURguSZH5sKDBNZ/s1600/ap+no+code+behind+04.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzn4EC8-CQF4wQaujEJrPVHMKVS9zD4zbot_0DWQhiKzsFTJtO7v_EK-s6_MqKMcNMkIs7z6Byh3FVhL92CEh-u4_oO1s4XBa014bFSB2VLTAEhzhv35gUEUBcYjvMDDURguSZH5sKDBNZ/s1600/ap+no+code+behind+04.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
The two highlighted files are the user control files - XAML and code behind, the resources.xaml file contains the hosting data templates.&lt;br /&gt;
&lt;br /&gt;
The reason why these aren&#39;t required is because the code behind for the user control is doing nothing, and therefore can be removed and the XAML can be moved into the hosting data template - now the view (MVVM) is no more than a data template:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuqmyil8cIvZC8r-TBg2Pbr0fQ1XVzg14Uj5907Q5iP-FmtbERgigncAG0BNa4GPGEHcn_9VPmGK1ysm_L6lGO-wZNTJCxkMOxK3BPMteWHL3g9gjaQIKvFUeMqQHOmt-cnAbqxfeXu5dN/s1600/ap+no+code+behind+05.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuqmyil8cIvZC8r-TBg2Pbr0fQ1XVzg14Uj5907Q5iP-FmtbERgigncAG0BNa4GPGEHcn_9VPmGK1ysm_L6lGO-wZNTJCxkMOxK3BPMteWHL3g9gjaQIKvFUeMqQHOmt-cnAbqxfeXu5dN/s1600/ap+no+code+behind+05.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&amp;nbsp;And you can now see the user control files have been removed from the solution:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPB4E8qkoS_14Wws68l8yQPhv6AAUx5n3WyBn193cpgxPQ6hy85y2JG_ZGpn0Kljzt27SIRGgDDVaUmEfe2PHknU_kHO6QZ9fPIRJutsag9eGCHiOADadDi8SHg-lMKhb5yR_t86gkdl-f/s1600/ap+no+code+behind+06.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPB4E8qkoS_14Wws68l8yQPhv6AAUx5n3WyBn193cpgxPQ6hy85y2JG_ZGpn0Kljzt27SIRGgDDVaUmEfe2PHknU_kHO6QZ9fPIRJutsag9eGCHiOADadDi8SHg-lMKhb5yR_t86gkdl-f/s1600/ap+no+code+behind+06.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://awkwardcoder.blogspot.com/feeds/3868540137492185617/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://awkwardcoder.blogspot.com/2013/11/mvvm-anti-pattern-view-code-behind-with.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/3868540137492185617'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/3868540137492185617'/><link rel='alternate' type='text/html' href='http://awkwardcoder.blogspot.com/2013/11/mvvm-anti-pattern-view-code-behind-with.html' title='MVVM anti-pattern: View code behind with no implementation'/><author><name>awkwardcoder</name><uri>http://www.blogger.com/profile/09746266491429238639</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNCVrxgZI0ysSe04Lq2lyQfaYkLNVLBhLda8ryfijkXIytzt_8m2LpnVZqeEjyv3K_DkRQY6nUCjqVapwc3GZCzWZMa7snTHxSYXfBqPkTLMsdoMowuwzBMQbdlaYpwQ/s220/PXL_20210316_143926215.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTlfCIMAnre5Oekf9TiPWQZCeHzVADF8eePc_SX0oxAJ1VIFKgadA1n8pjkyiTSeDLRPtbv1UYcTp6qMYaKXpjWKA7bHDJlVzlVNdOaojAsRIAuqZRBU5ny-_GbxMW5xCBv5Ns-nyZZK7N/s72-c/ap+no+code+behind+02.png" height="72" width="72"/><thr:total>0</thr:total><georss:featurename>London N16 8EB, UK</georss:featurename><georss:point>51.556352399999987 -0.076537400000006528</georss:point><georss:box>51.555118399999991 -0.079058900000006524 51.557586399999984 -0.074015900000006532</georss:box></entry><entry><id>tag:blogger.com,1999:blog-2559668977390861004.post-6311913967445130338</id><published>2013-11-17T13:41:00.001+00:00</published><updated>2013-11-18T22:23:20.848+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Development"/><category scheme="http://www.blogger.com/atom/ns#" term="MVVM"/><category scheme="http://www.blogger.com/atom/ns#" term="WPF"/><title type='text'>MVVM anti-pattern: explicitly using data context in View code behind</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
I believe explicitly using the data context in the code behind of the view (custom, user control etc) in any MVVM application is an anti-pattern. The view has no need to explicitly access the data context it is there purely for binding concerns. The following screen shot illustrates what I mean:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTNRF_CSnf2gOi4hr10qpPt9Lt_ZSsGuJdKLiU7wipHCfSzgeiRHSNaTnfOJnHqAfuP1OSzD91ZJr_CWnitHef4PrDcgD569qSz5oE3yQYG4pe_pmvbbS9jcZbr6YUoP0nkOJRphWOoyqh/s1600/ap+data+context+01.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTNRF_CSnf2gOi4hr10qpPt9Lt_ZSsGuJdKLiU7wipHCfSzgeiRHSNaTnfOJnHqAfuP1OSzD91ZJr_CWnitHef4PrDcgD569qSz5oE3yQYG4pe_pmvbbS9jcZbr6YUoP0nkOJRphWOoyqh/s1600/ap+data+context+01.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
This is an anti-pattern because the view knows about the view model - as you can see the data context is being cast to the DataContextViewModel. The view (user control) is explicitly coupled to the view model and has reduced the cohesiveness of the view - it can now only be bound to instance of DataContextViewModel. Now you could argue if it was interface this would make is more useful but this doesn&#39;t reduce the tight coupling it just gives the illusion.&lt;br /&gt;
&lt;br /&gt;
I guess the reason why this is common is because it makes the XAML appear very clean and simple, but this is also not ideal because it&#39;s not obvious what&#39;s being bound between the view model and the view:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWvCzsA5zN7QefDC4DihtBGDnIxh15rA5BfZ0_kqFLnEIxBHECmSmyiW-kAiI-IwQjpFzpJZDjNG2Z5pHRqlSimfDpb1mC1JHo88nHyLj05ODanmW6IAnvsGkzvLIGO7N83MLT0DdiVWlp/s1600/ap+data+context+02.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWvCzsA5zN7QefDC4DihtBGDnIxh15rA5BfZ0_kqFLnEIxBHECmSmyiW-kAiI-IwQjpFzpJZDjNG2Z5pHRqlSimfDpb1mC1JHo88nHyLj05ODanmW6IAnvsGkzvLIGO7N83MLT0DdiVWlp/s1600/ap+data+context+02.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;i&gt;How should this have been done?&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
By defining a&lt;a href=&quot;http://wpftutorial.net/DependencyProperties.html&quot;&gt; Dependancy Property&lt;/a&gt; on the view (user control) and then binding this in the XAML to the FirstNames property of the view model, then there is no need to access the DataContext in the code behind of the view:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhF-KH5RlB993dg6oyYjUMq-T0OaWV2yBZR_jTqdOhgrQFtBUSAtlbyj_DXGMbOOBDTqG7hwaOA0iPOE0FWMA1ppXWOHnK1MhGLo7hKF_FQT1oIY5L7qtNSbNuGefsIOSfqYE9VE7w_T3MD/s1600/ap+data+context+03.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhF-KH5RlB993dg6oyYjUMq-T0OaWV2yBZR_jTqdOhgrQFtBUSAtlbyj_DXGMbOOBDTqG7hwaOA0iPOE0FWMA1ppXWOHnK1MhGLo7hKF_FQT1oIY5L7qtNSbNuGefsIOSfqYE9VE7w_T3MD/s1600/ap+data+context+03.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
The XAML has now changed to be more declarative, which is a good thing:)&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7pFHKZF0e14uf60xaA-IJQhcSDvLHLHi_RVR0asJ09SYTeMec5IWBV2p3Q3ohhs-85kKsCUyXcRbLckBfDmD2lnMXWzGAn4khvpojKbvJeZKD-sj1Imu_uRFgAREz0xtw8Xmu7z_oxnCX/s1600/ap+data+context+04.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7pFHKZF0e14uf60xaA-IJQhcSDvLHLHi_RVR0asJ09SYTeMec5IWBV2p3Q3ohhs-85kKsCUyXcRbLckBfDmD2lnMXWzGAn4khvpojKbvJeZKD-sj1Imu_uRFgAREz0xtw8Xmu7z_oxnCX/s1600/ap+data+context+04.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://awkwardcoder.blogspot.com/feeds/6311913967445130338/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://awkwardcoder.blogspot.com/2013/11/mvvm-anti-pattern-explicitly-using-data.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/6311913967445130338'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/6311913967445130338'/><link rel='alternate' type='text/html' href='http://awkwardcoder.blogspot.com/2013/11/mvvm-anti-pattern-explicitly-using-data.html' title='MVVM anti-pattern: explicitly using data context in View code behind'/><author><name>awkwardcoder</name><uri>http://www.blogger.com/profile/09746266491429238639</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNCVrxgZI0ysSe04Lq2lyQfaYkLNVLBhLda8ryfijkXIytzt_8m2LpnVZqeEjyv3K_DkRQY6nUCjqVapwc3GZCzWZMa7snTHxSYXfBqPkTLMsdoMowuwzBMQbdlaYpwQ/s220/PXL_20210316_143926215.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTNRF_CSnf2gOi4hr10qpPt9Lt_ZSsGuJdKLiU7wipHCfSzgeiRHSNaTnfOJnHqAfuP1OSzD91ZJr_CWnitHef4PrDcgD569qSz5oE3yQYG4pe_pmvbbS9jcZbr6YUoP0nkOJRphWOoyqh/s72-c/ap+data+context+01.png" height="72" width="72"/><thr:total>1</thr:total><georss:featurename>London N16, UK</georss:featurename><georss:point>51.5623078 -0.076435299999957351</georss:point><georss:box>51.5228228 -0.15711629999995735 51.6017928 0.0042457000000426515</georss:box></entry><entry><id>tag:blogger.com,1999:blog-2559668977390861004.post-6064611241245510959</id><published>2013-11-10T16:29:00.000+00:00</published><updated>2013-11-10T16:30:55.244+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="C#"/><category scheme="http://www.blogger.com/atom/ns#" term="Development"/><category scheme="http://www.blogger.com/atom/ns#" term="MVVM"/><category scheme="http://www.blogger.com/atom/ns#" term="WPF"/><title type='text'>Implementing a message box using a visual overlay in MVVM</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
I&#39;ve &lt;a href=&quot;http://awkwardcoder.blogspot.co.uk/2013/06/implementing-busy-indicator-using.html?q=overlay&quot;&gt;blogged&lt;/a&gt; about implementing a busy indicator before, this post is an extension of this pattern to implement a message box - this is instead of using the &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/system.windows.messagebox(v=vs.110).aspx&quot;&gt;namespace&lt;/a&gt; provide by the .Net framework.&lt;br /&gt;
&lt;br /&gt;
The UI is shown below, and when the button is clicked in the middle content it will display the message as an overlay - as you can see I&#39;ve coloured it green to get your attention:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKf8pfRseLgiOxbRU5RWpgUr6HCeDlqMEVYTciLw3ijR_u-h56OwDgunwk70wF52fgPD7w7mwf3IVEUefEBcpoXBkFZ-GsSukFfztEVrESbj5bATGCtKCoDK6AVQn7RCepFE_W66HKxlay/s1600/message+overlay+01.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKf8pfRseLgiOxbRU5RWpgUr6HCeDlqMEVYTciLw3ijR_u-h56OwDgunwk70wF52fgPD7w7mwf3IVEUefEBcpoXBkFZ-GsSukFfztEVrESbj5bATGCtKCoDK6AVQn7RCepFE_W66HKxlay/s1600/message+overlay+01.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
As with the previous &lt;a href=&quot;http://awkwardcoder.blogspot.co.uk/2013/06/implementing-busy-indicator-using.html?q=overlay&quot;&gt;post&lt;/a&gt;, the XAML for the View hasn&#39;t changed it&#39;s still very simple:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1DNF28h1cfoTh-3dsxyxkhRXp8GKhAvE13hh9ohrNe6Z0djwTqcGUlA04HED5CYDQzxssICDI39m-c3U5f4cZfcOQPrsvPOm8LAc-pZo0H_x2Fgw5f2HM9OD8t3Ingwixedj-ueMjKoMU/s1600/busy+overlay+02.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1DNF28h1cfoTh-3dsxyxkhRXp8GKhAvE13hh9ohrNe6Z0djwTqcGUlA04HED5CYDQzxssICDI39m-c3U5f4cZfcOQPrsvPOm8LAc-pZo0H_x2Fgw5f2HM9OD8t3Ingwixedj-ueMjKoMU/s1600/busy+overlay+02.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
What&#39;s changed is the style applied to the ViewHost class, as you can see there&#39;s now a MessageOverlay as well as a BusyOverlay. You&#39;ll notice the z-order of the MessageOverlay is one less the BusyOverlay, this is to make sure the busy indicator is always displayed at the highest order and hence would be an overlay on top of the message overlay:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWmRjd3jyUKFI0PiQU6UX1IHMjBU5OpZitCbsZhNqpMRDU-uwzJF9N9KUTEot1KOhG9PhlMCcyKqmAbtoNBaC4hiuL7_xO2UhH3N3kAXugKksAI8UDWYTu2_AAYiAtNSkS0xVQ0iVaocNN/s1600/message+overlay+02.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWmRjd3jyUKFI0PiQU6UX1IHMjBU5OpZitCbsZhNqpMRDU-uwzJF9N9KUTEot1KOhG9PhlMCcyKqmAbtoNBaC4hiuL7_xO2UhH3N3kAXugKksAI8UDWYTu2_AAYiAtNSkS0xVQ0iVaocNN/s1600/message+overlay+02.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
The message overlay is trigger by the binding MessageMonitor, this is an implementation of the following interface, the one I&#39;m using is shown below along with interface: &lt;br /&gt;
&lt;div class=&quot;gistLoad&quot; data-id=&quot;7399878&quot; id=&quot;gist7399878&quot;&gt;
Loading ....&lt;/div&gt;
&lt;/div&gt;
What you see is the message is exposed as a view model implementing the IMessageViewModel interface, the implementation I&#39;m using is shown below as you can see I&#39;m injecting in the actual message and the busy indicator, I use these to simulate an action when the &#39;Show Busy &amp;amp; Close&#39; button is clicked. &lt;br /&gt;
&lt;div class=&quot;gistLoad&quot; data-id=&quot;7399955&quot; id=&quot;gist7399955&quot;&gt;
Loading ....&lt;/div&gt;
&lt;script src=&quot;https://raw.github.com/moski/gist-Blogger/master/public/gistLoader.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;The code is available for download from &lt;a href=&quot;https://github.com/oriches/Wpf.MessageOverlay&quot;&gt;github&lt;/a&gt;.&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://awkwardcoder.blogspot.com/feeds/6064611241245510959/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://awkwardcoder.blogspot.com/2013/11/implementing-message-box-using-visual.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/6064611241245510959'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2559668977390861004/posts/default/6064611241245510959'/><link rel='alternate' type='text/html' href='http://awkwardcoder.blogspot.com/2013/11/implementing-message-box-using-visual.html' title='Implementing a message box using a visual overlay in MVVM'/><author><name>awkwardcoder</name><uri>http://www.blogger.com/profile/09746266491429238639</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNCVrxgZI0ysSe04Lq2lyQfaYkLNVLBhLda8ryfijkXIytzt_8m2LpnVZqeEjyv3K_DkRQY6nUCjqVapwc3GZCzWZMa7snTHxSYXfBqPkTLMsdoMowuwzBMQbdlaYpwQ/s220/PXL_20210316_143926215.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKf8pfRseLgiOxbRU5RWpgUr6HCeDlqMEVYTciLw3ijR_u-h56OwDgunwk70wF52fgPD7w7mwf3IVEUefEBcpoXBkFZ-GsSukFfztEVrESbj5bATGCtKCoDK6AVQn7RCepFE_W66HKxlay/s72-c/message+overlay+01.png" height="72" width="72"/><thr:total>0</thr:total><georss:featurename>London N16, UK</georss:featurename><georss:point>51.5623078 -0.076435299999957351</georss:point><georss:box>51.5228228 -0.15711629999995735 51.6017928 0.0042457000000426515</georss:box></entry></feed>