Compiled Experience Windows Platform Development http://compiledexperience.com en Wed, 19 Jul 2017 11:06:35 +0000 Wed, 19 Jul 2017 11:06:35 +0000 Generation of Assembly Info in Visual Studio 2017 <p>One feature of the new <code class="highlighter-rouge">csproj</code> format (is there an official name for these?) that I wasn’t aware of is the automatic generation of the <code class="highlighter-rouge">assmebly:</code> attributes we would normally see in <code class="highlighter-rouge">AssemblyInfo.cs</code>. This can catch you by surprise with some odd errors, especially when migrating existing projects to the format.</p> <p>This feature allows you to define assembly properties such as title, description and version as project properties defined in the <code class="highlighter-rouge">.csproj</code> that looks like the following.</p> <div class="language-xml highlighter-rouge"><pre class="highlight"><code><span class="nt">&lt;PropertyGroup&gt;</span> <span class="nt">&lt;Company&gt;</span>Compiled Expericne<span class="nt">&lt;/Company&gt;</span> <span class="nt">&lt;Authors&gt;</span>Nigel Sampson<span class="nt">&lt;/Authors&gt;</span> <span class="nt">&lt;PackageId&gt;</span>AssemblyDemo<span class="nt">&lt;/PackageId&gt;</span> <span class="nt">&lt;Version&gt;</span>1.0.0<span class="nt">&lt;/Version&gt;</span> <span class="nt">&lt;AssemblyVersion&gt;</span>1.0.1.0<span class="nt">&lt;/AssemblyVersion&gt;</span> <span class="nt">&lt;FileVersion&gt;</span>1.0.1.0<span class="nt">&lt;/FileVersion&gt;</span> <span class="nt">&lt;/PropertyGroup&gt;</span> </code></pre> </div> <p>If you don’t want to edit the project file manually these can be set through the project properties and the Package tab. One of the reasons for this is that it combines both the assembly and package information (now the build system can create your nuget packages for you) letting you define shared properties in one place.</p> <p>At compile the following <code class="highlighter-rouge">AssemblyInfo.cs</code> is generated in the <code class="highlighter-rouge">obj</code> folder.</p> <div class="language-csharp highlighter-rouge"><pre class="highlight"><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> <span class="k">using</span> <span class="nn">System.Reflection</span><span class="p">;</span> <span class="na">[assembly: System.Reflection.AssemblyCompanyAttribute("Compiled Expericne")]</span> <span class="na">[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]</span> <span class="na">[assembly: System.Reflection.AssemblyDescriptionAttribute("Package Description")]</span> <span class="na">[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.1.0")]</span> <span class="na">[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")]</span> <span class="na">[assembly: System.Reflection.AssemblyProductAttribute("AssemblyTest")]</span> <span class="na">[assembly: System.Reflection.AssemblyTitleAttribute("AssemblyTest")]</span> <span class="na">[assembly: System.Reflection.AssemblyVersionAttribute("1.0.1.0")]</span> </code></pre> </div> <p>If you’re migrating an exsiting project you’ll most likely have an existing <code class="highlighter-rouge">AssemblyInfo.cs</code> or using one due to properties being shared across projects with a <code class="highlighter-rouge">GlobalAssemblyInfo.cs</code> (what I was doing) meaning you’ll see erorrs such as <code class="highlighter-rouge">CS0579 Duplicate 'System.Reflection.AssemblyCompanyAttribute' attribute</code>.</p> <p>You can either shift to setting the new project properties and remove your existing file or turn off the new feature (which I chose to do) with the following project property.</p> <div class="language-xml highlighter-rouge"><pre class="highlight"><code><span class="nt">&lt;PropertyGroup&gt;</span> <span class="nt">&lt;GenerateAssemblyInfo&gt;</span>false<span class="nt">&lt;/GenerateAssemblyInfo&gt;</span> <span class="nt">&lt;/PropertyGroup&gt;</span> </code></pre> </div> <p>Now the <code class="highlighter-rouge">AssemblyInfo.cs</code> won’t be automatically generated and conflict with your already defined attributes.</p> Wed, 19 Jul 2017 00:00:00 +0000 http://compiledexperience.com/blog/posts/assemblyinfo-generation http://compiledexperience.com/blog/posts/assemblyinfo-generation nigel.sampson@compiledexperience.com (Nigel Sampson) csharp Adding functionality to Caliburn.Micro conventions <p>The binding conventions in Caliburn.Micro can be extended to do almost anything you want. The method <code class="highlighter-rouge">ConventionManager.AddElementConvention&lt;T&gt;</code> returns a <code class="highlighter-rouge">ElementConvention</code> which can be further customised. In this post I’ll show what things we can do with this by modifying the <code class="highlighter-rouge">ElementConvention.ApplyBinding</code> action.</p> <p>Internally Caliburn.Micro already modifies some of the conventions with extra functionality. It’s what turns</p> <div class="language-xml highlighter-rouge"><pre class="highlight"><code><span class="nt">&lt;TabControl</span> <span class="na">x:Name=</span><span class="s">"Items"</span> <span class="nt">/&gt;</span> </code></pre> </div> <p>into</p> <div class="language-xml highlighter-rouge"><pre class="highlight"><code><span class="nt">&lt;TabControl</span> <span class="na">ItemsSource=</span><span class="s">"{Binding Items}"</span> <span class="na">SelectedItem=</span><span class="s">"{Binding ActiveItem, Mode=TwoWay}"</span><span class="nt">&gt;</span> <span class="nt">&lt;TabControl.ContentTemplate&gt;</span> <span class="nt">&lt;DataTemplate&gt;</span> <span class="nt">&lt;ContentControl</span> <span class="na">cal:View.Model=</span><span class="s">"{Binding}"</span> <span class="na">VerticalContentAlignment=</span><span class="s">"Stretch"</span> <span class="na">HorizontalContentAlignment=</span><span class="s">"Stretch"</span> <span class="na">IsTabStop=</span><span class="s">"False"</span> <span class="nt">/&gt;</span> <span class="nt">&lt;/DataTemplate&gt;</span> <span class="nt">&lt;/TabControl.ContentTemplate&gt;</span> <span class="nt">&lt;TabControl.HeaderTemplate&gt;</span> <span class="nt">&lt;DataTemplate&gt;</span> <span class="nt">&lt;TextBlock</span> <span class="na">Text=</span><span class="s">"{Binding DisplayName}"</span> <span class="nt">/&gt;</span> <span class="nt">&lt;/DataTemplate&gt;</span> <span class="nt">&lt;/TabControl.HeaderTemplate&gt;</span> <span class="nt">&lt;/TabControl&gt;</span> </code></pre> </div> <p>We can add our own extensions as well. In this example I’ll demonstrate how we can modify the convention for <code class="highlighter-rouge">TextBox</code> to take into account the <code class="highlighter-rouge">System.ComponentModel.DataAnnotations</code> attributes.</p> <p>Let’s imagine we have a view model with <code class="highlighter-rouge">FirstName</code> property that looks like the one below, it would be great if we can by convention apply these attributes to the control the property is bound to. This should let us define in one place all the metadata about this property.</p> <div class="language-csharp highlighter-rouge"><pre class="highlight"><code><span class="na">[StringLength(50)]</span> <span class="na">[Display(Name = "First Name", Prompt = "John")]</span> <span class="k">public</span> <span class="kt">string</span> <span class="n">FirstName</span> <span class="p">{</span> <span class="k">get</span> <span class="p">{</span> <span class="k">return</span> <span class="n">firstName</span><span class="p">;</span> <span class="p">}</span> <span class="k">set</span> <span class="p">{</span> <span class="n">firstName</span> <span class="p">=</span> <span class="k">value</span><span class="p">;</span> <span class="nf">NotifyOfPropertyChange</span><span class="p">();</span> <span class="p">}</span> <span class="p">}</span> </code></pre> </div> <p>This turns out to be really easy, we simply have something like the following in our app startup code.</p> <div class="language-csharp highlighter-rouge"><pre class="highlight"><code><span class="n">ConventionManager</span><span class="p">.</span><span class="n">AddElementConvention</span><span class="p">&lt;</span><span class="n">TextBox</span><span class="p">&gt;(</span><span class="n">TextBox</span><span class="p">.</span><span class="n">TextProperty</span><span class="p">,</span> <span class="s">"Text"</span><span class="p">,</span> <span class="s">"TextChanged"</span><span class="p">)</span> <span class="p">.</span><span class="n">ApplyBinding</span> <span class="p">=</span> <span class="p">(</span><span class="n">viewModelType</span><span class="p">,</span> <span class="n">path</span><span class="p">,</span> <span class="n">property</span><span class="p">,</span> <span class="n">element</span><span class="p">,</span> <span class="n">convention</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span> <span class="k">if</span> <span class="p">(!</span><span class="n">ConventionManager</span><span class="p">.</span><span class="nf">SetBindingWithoutBindingOverwrite</span><span class="p">(</span><span class="n">viewModelType</span><span class="p">,</span> <span class="n">path</span><span class="p">,</span> <span class="n">property</span><span class="p">,</span> <span class="n">element</span><span class="p">,</span> <span class="n">convention</span><span class="p">,</span> <span class="n">TextBox</span><span class="p">.</span><span class="n">TextProperty</span><span class="p">))</span> <span class="p">{</span> <span class="k">return</span> <span class="k">false</span><span class="p">;</span> <span class="p">}</span> <span class="kt">var</span> <span class="n">textBox</span> <span class="p">=</span> <span class="p">(</span><span class="n">TextBox</span><span class="p">)</span> <span class="n">element</span><span class="p">;</span> <span class="kt">var</span> <span class="n">display</span> <span class="p">=</span> <span class="n">property</span><span class="p">.</span><span class="n">GetAttributes</span><span class="p">&lt;</span><span class="n">DisplayAttribute</span><span class="p">&gt;(</span><span class="k">true</span><span class="p">).</span><span class="nf">FirstOrDefault</span><span class="p">();</span> <span class="kt">var</span> <span class="n">length</span> <span class="p">=</span> <span class="n">property</span><span class="p">.</span><span class="n">GetAttributes</span><span class="p">&lt;</span><span class="n">StringLengthAttribute</span><span class="p">&gt;(</span><span class="k">true</span><span class="p">).</span><span class="nf">FirstOrDefault</span><span class="p">();</span> <span class="k">if</span> <span class="p">(</span><span class="n">display</span> <span class="p">!=</span> <span class="k">null</span><span class="p">)</span> <span class="p">{</span> <span class="n">textBox</span><span class="p">.</span><span class="n">Header</span> <span class="p">=</span> <span class="n">display</span><span class="p">.</span><span class="nf">GetName</span><span class="p">();</span> <span class="n">textBox</span><span class="p">.</span><span class="n">PlaceholderText</span> <span class="p">=</span> <span class="n">display</span><span class="p">.</span><span class="nf">GetPrompt</span><span class="p">();</span> <span class="p">}</span> <span class="k">if</span> <span class="p">(</span><span class="n">length</span> <span class="p">!=</span> <span class="k">null</span><span class="p">)</span> <span class="p">{</span> <span class="n">textBox</span><span class="p">.</span><span class="n">MaxLength</span> <span class="p">=</span> <span class="n">length</span><span class="p">.</span><span class="n">MaximumLength</span><span class="p">;</span> <span class="p">}</span> <span class="k">return</span> <span class="k">true</span><span class="p">;</span> <span class="p">};</span> </code></pre> </div> <p>IF we try to apply the binding between the view model and the <code class="highlighter-rouge">Text</code> property on the control. If this fails (there’s already a binding) then we exit out. We then check the property for the attributes in question and if they exist apply their values to the <code class="highlighter-rouge">TextBox</code>.</p> <p>We don’t need to make any modifications to the xaml so it can be very simple and still have most of the values it needs applied by the convention itself.</p> <div class="language-xml highlighter-rouge"><pre class="highlight"><code><span class="nt">&lt;TextBox</span> <span class="na">x:Name=</span><span class="s">"FirstName"</span> <span class="nt">/&gt;</span> </code></pre> </div> <p>Feel free to experiement in customising your conventions. I hope this gives you all some ideas on what you can do. Let me know what you find.</p> Thu, 08 Jun 2017 00:00:00 +0000 http://compiledexperience.com/blog/posts/extending-conventions http://compiledexperience.com/blog/posts/extending-conventions nigel.sampson@compiledexperience.com (Nigel Sampson) caliburn-micro Speaking at NDC Sydney <p>Really proud to say that I’ll be speaking in August at <a href="http://ndcsydney.com/">NDC Sydney</a> on <a href="http://ndcsydney.com/speaker/nigel-sampson/">Techniques in creating great cross platform apps.</a>. This talk will be a spiritual successor to <a href="https://www.youtube.com/watch?v=x266Vy4tfT0">last years talk</a> where I’ll cover some of the newer code sharing options in Visual Studio 2017 and expanding on the ideas of the view model composition that Caliburn.Micro supports.</p> <p>There’s a fantastic <a href="http://ndcsydney.com/speakers/">speakers list</a> and some really exciting talks I’m looking forward to seeing.</p> <p>Getting this many great speakers in the same event in this part of the world is a rare feat so I’d recommend taking advantage of it and getting <a href="http://ndcsydney.com/page/tickets">your ticket</a> soon. If you do attend I’d love it you reach out and we can chat about how you build apps in a modern environment.</p> Tue, 16 May 2017 00:00:00 +0000 http://compiledexperience.com/blog/posts/ndc-2017 http://compiledexperience.com/blog/posts/ndc-2017 nigel.sampson@compiledexperience.com (Nigel Sampson) xamarin caliburn-micro mvvm talks Supporting Xamarin.Forms Master Detail Page in Caliburn.Micro <p>Previously I’ve talked about <a href="/blog/posts/tabbed-page-conductor">Supporting Xamarin.Forms Tabbed Page in Caliburn.Micro</a> using conductors and Caliburns excellent view location features. I’d like to now show how we can do the same with the <code class="highlighter-rouge">MasterDetailPage</code>.</p> <p>The Master / Details pattern is very common in mobile apps providing where a master list of items is presented to the user and when one is select the view is switched to more details.</p> <p>When using <code class="highlighter-rouge">MasterDetailPage</code> with <code class="highlighter-rouge">Caliburn.Micro</code> we want to hit a number of goals.</p> <ol> <li>Our main view shouldn’t deal with displaying either the master or details and just handle creating the shell of the page.</li> <li>Our main view model should should follow a similar goal only coordinating between master and details.</li> <li>Handle creating two different views for one view model.</li> </ol> <p>In this sample our master / detail item will be characters from the upcoming TV show American Gods. Each character will have a single view model.</p> <div class="language-csharp highlighter-rouge"><pre class="highlight"><code><span class="k">public</span> <span class="k">class</span> <span class="nc">CharacterViewModel</span> <span class="p">:</span> <span class="n">PropertyChangedBase</span> <span class="p">{</span> <span class="k">public</span> <span class="nf">CharacterViewModel</span><span class="p">(</span><span class="kt">string</span> <span class="n">name</span><span class="p">,</span> <span class="kt">string</span> <span class="n">tagline</span><span class="p">,</span> <span class="kt">string</span> <span class="n">image</span><span class="p">)</span> <span class="p">{</span> <span class="n">Name</span> <span class="p">=</span> <span class="n">name</span><span class="p">;</span> <span class="n">Tagline</span> <span class="p">=</span> <span class="n">tagline</span><span class="p">;</span> <span class="n">Image</span> <span class="p">=</span> <span class="n">image</span><span class="p">;</span> <span class="p">}</span> <span class="k">public</span> <span class="kt">string</span> <span class="n">Name</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="p">}</span> <span class="k">public</span> <span class="kt">string</span> <span class="n">Tagline</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="p">}</span> <span class="k">public</span> <span class="kt">string</span> <span class="n">Image</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="p">}</span> <span class="p">}</span> </code></pre> </div> <p>We’ll then create our <code class="highlighter-rouge">ShellViewModel</code>, it will need to contain a collection of our characters as well as the currently selected character. We’ll also need a property that indicicate whether the master menu is currently available. A first draft looks something like:</p> <div class="language-csharp highlighter-rouge"><pre class="highlight"><code><span class="k">public</span> <span class="k">class</span> <span class="nc">ShellViewModel</span> <span class="p">:</span> <span class="n">Screen</span> <span class="p">{</span> <span class="k">private</span> <span class="n">CharacterViewModel</span> <span class="n">selectedCharacter</span><span class="p">;</span> <span class="k">private</span> <span class="kt">bool</span> <span class="n">masterListAvailable</span><span class="p">;</span> <span class="k">public</span> <span class="nf">ShellViewModel</span><span class="p">()</span> <span class="p">{</span> <span class="n">MasterListAvailable</span> <span class="p">=</span> <span class="k">true</span><span class="p">;</span> <span class="n">Characters</span> <span class="p">=</span> <span class="k">new</span> <span class="n">BindableCollection</span><span class="p">&lt;</span><span class="n">CharacterViewModel</span><span class="p">&gt;</span> <span class="p">{</span> <span class="k">new</span> <span class="nf">CharacterViewModel</span><span class="p">(</span><span class="s">"Shadow Moon"</span><span class="p">,</span> <span class="s">"The Ex-Con"</span><span class="p">,</span> <span class="s">"character1.jpg"</span><span class="p">),</span> <span class="p">...</span> <span class="k">new</span> <span class="nf">CharacterViewModel</span><span class="p">(</span><span class="s">"Easter"</span><span class="p">,</span> <span class="s">"The Godess of Spring"</span><span class="p">,</span> <span class="s">"character10.jpg"</span><span class="p">),</span> <span class="p">};</span> <span class="p">}</span> <span class="k">public</span> <span class="n">BindableCollection</span><span class="p">&lt;</span><span class="n">CharacterViewModel</span><span class="p">&gt;</span> <span class="n">Characters</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="p">}</span> <span class="k">public</span> <span class="n">CharacterViewModel</span> <span class="n">SelectedCharacter</span> <span class="p">{</span> <span class="k">get</span> <span class="p">{</span> <span class="k">return</span> <span class="n">selectedCharacter</span><span class="p">;</span> <span class="p">}</span> <span class="k">set</span> <span class="p">{</span> <span class="n">selectedCharacter</span> <span class="p">=</span> <span class="k">value</span><span class="p">;</span> <span class="nf">NotifyOfPropertyChange</span><span class="p">();</span> <span class="n">MasterListAvailable</span> <span class="p">=</span> <span class="n">SelectedCharacter</span> <span class="p">==</span> <span class="k">null</span><span class="p">;</span> <span class="p">}</span> <span class="p">}</span> <span class="k">public</span> <span class="kt">bool</span> <span class="n">MasterListAvailable</span> <span class="p">{</span> <span class="k">get</span> <span class="p">{</span> <span class="k">return</span> <span class="n">masterListAvailable</span><span class="p">;</span> <span class="p">}</span> <span class="k">set</span> <span class="p">{</span> <span class="n">masterListAvailable</span> <span class="p">=</span> <span class="k">value</span><span class="p">;</span> <span class="nf">NotifyOfPropertyChange</span><span class="p">();</span> <span class="p">}</span> <span class="p">}</span> <span class="p">}</span> </code></pre> </div> <p>The most interesting things in here are populating the data in the constuctor, really this is only things specific to characters in the entire view model, but could easily be abstracted away. The other is that when the <code class="highlighter-rouge">SelectedCharacter</code> is set we update <code class="highlighter-rouge">MasterListAvailable</code> depending on the value. What this will do ultimately in the UI is that when a character is selected in the master list the UI will switch over to the details view.</p> <p>We already have a conductor in the framework that can handle this <code class="highlighter-rouge">Conductor&lt;T&gt;.Collection.OneActive</code> leaving us with.</p> <div class="language-csharp highlighter-rouge"><pre class="highlight"><code> <span class="k">public</span> <span class="k">class</span> <span class="nc">ShellViewModel</span> <span class="p">:</span> <span class="n">Conductor</span><span class="p">&lt;</span><span class="n">CharacterViewModel</span><span class="p">&gt;.</span><span class="n">Collection</span><span class="p">.</span><span class="n">OneActive</span> <span class="p">{</span> <span class="k">private</span> <span class="kt">bool</span> <span class="n">masterListAvailable</span><span class="p">;</span> <span class="k">public</span> <span class="nf">ShellViewModel</span><span class="p">()</span> <span class="p">{</span> <span class="n">MasterListAvailable</span> <span class="p">=</span> <span class="k">true</span><span class="p">;</span> <span class="n">Items</span><span class="p">.</span><span class="nf">AddRange</span><span class="p">(</span><span class="k">new</span> <span class="p">[]</span> <span class="p">{</span> <span class="k">new</span> <span class="nf">CharacterViewModel</span><span class="p">(</span><span class="s">"Shadow Moon"</span><span class="p">,</span> <span class="s">"The Ex-Con"</span><span class="p">,</span> <span class="s">"character1.jpg"</span><span class="p">),</span> <span class="p">...</span> <span class="k">new</span> <span class="nf">CharacterViewModel</span><span class="p">(</span><span class="s">"Easter"</span><span class="p">,</span> <span class="s">"The Godess of Spring"</span><span class="p">,</span> <span class="s">"character10.jpg"</span><span class="p">),</span> <span class="p">});</span> <span class="p">}</span> <span class="k">protected</span> <span class="k">override</span> <span class="k">void</span> <span class="nf">OnActivationProcessed</span><span class="p">(</span><span class="n">CharacterViewModel</span> <span class="n">item</span><span class="p">,</span> <span class="kt">bool</span> <span class="n">success</span><span class="p">)</span> <span class="p">{</span> <span class="n">MasterListAvailable</span> <span class="p">=</span> <span class="n">item</span> <span class="p">==</span> <span class="k">null</span><span class="p">;</span> <span class="p">}</span> <span class="k">public</span> <span class="kt">bool</span> <span class="n">MasterListAvailable</span> <span class="p">{</span> <span class="k">get</span> <span class="p">{</span> <span class="k">return</span> <span class="n">masterListAvailable</span><span class="p">;</span> <span class="p">}</span> <span class="k">set</span> <span class="p">{</span> <span class="n">masterListAvailable</span> <span class="p">=</span> <span class="k">value</span><span class="p">;</span> <span class="nf">NotifyOfPropertyChange</span><span class="p">();</span> <span class="p">}</span> <span class="p">}</span> <span class="p">}</span> </code></pre> </div> <p>Our <code class="highlighter-rouge">ShellView</code> comes next, an important point to note here is that no where in the view do we declare how a character should be display we simple style the master list and the container for the detail content. This view could be reused across any master / details view in the application.</p> <div class="language-xml highlighter-rouge"><pre class="highlight"><code><span class="cp">&lt;?xml version="1.0" encoding="utf-8" ?&gt;</span> <span class="nt">&lt;MasterDetailPage</span> <span class="na">xmlns=</span><span class="s">"http://xamarin.com/schemas/2014/forms"</span> <span class="na">xmlns:x=</span><span class="s">"http://schemas.microsoft.com/winfx/2009/xaml"</span> <span class="na">xmlns:views=</span><span class="s">"clr-namespace:MasterDetail.Views;assembly=MasterDetail"</span> <span class="na">xmlns:cm=</span><span class="s">"clr-namespace:Caliburn.Micro.Xamarin.Forms;assembly=Caliburn.Micro.Platform.Xamarin.Forms"</span> <span class="na">x:Class=</span><span class="s">"MasterDetail.Views.ShellView"</span> <span class="na">IsPresented=</span><span class="s">"{Binding MasterListAvailable}"</span><span class="nt">&gt;</span> <span class="nt">&lt;MasterDetailPage.Master&gt;</span> <span class="nt">&lt;ContentPage</span> <span class="na">Title=</span><span class="s">"Master"</span><span class="nt">&gt;</span> <span class="nt">&lt;ListView</span> <span class="na">ItemsSource=</span><span class="s">"{Binding Items}"</span> <span class="na">SelectedItem=</span><span class="s">"{Binding ActiveItem, Mode=TwoWay}"</span><span class="nt">&gt;</span> <span class="nt">&lt;ListView.ItemTemplate&gt;</span> <span class="nt">&lt;DataTemplate&gt;</span> <span class="nt">&lt;ViewCell&gt;</span> <span class="nt">&lt;ContentView</span> <span class="na">cm:View.Model=</span><span class="s">"{Binding}"</span> <span class="na">cm:View.Context=</span><span class="s">"MasterView"</span> <span class="nt">/&gt;</span> <span class="nt">&lt;/ViewCell&gt;</span> <span class="nt">&lt;/DataTemplate&gt;</span> <span class="nt">&lt;/ListView.ItemTemplate&gt;</span> <span class="nt">&lt;/ListView&gt;</span> <span class="nt">&lt;/ContentPage&gt;</span> <span class="nt">&lt;/MasterDetailPage.Master&gt;</span> <span class="nt">&lt;MasterDetailPage.Detail&gt;</span> <span class="nt">&lt;ContentPage</span> <span class="na">cm:View.Model=</span><span class="s">"{Binding ActiveItem}"</span> <span class="na">cm:View.Context=</span><span class="s">"DetailView"</span> <span class="na">Title=</span><span class="s">"Master"</span> <span class="nt">/&gt;</span> <span class="nt">&lt;/MasterDetailPage.Detail&gt;</span> <span class="nt">&lt;/MasterDetailPage&gt;</span> </code></pre> </div> <p>The imporatant part to note here is we’re using <code class="highlighter-rouge">View.Model</code> in the same way as our <a href="/blog/posts/tabbed-page-conductor">last post about TabbedPage</a>. Normally this would be since both the master data template and details content page are both being bound to a <code class="highlighter-rouge">CharacterViewModel</code> then a <code class="highlighter-rouge">CharacterView</code> could be injected.</p> <p>This wouldn’t be desirable since we don’t want the same view for both places. Instead we use <code class="highlighter-rouge">View.Content</code> to provide some extra view location.</p> <p>For the master list item we provide a context of <code class="highlighter-rouge">MasterView</code>, this means when resolving the view for <code class="highlighter-rouge">MasterDetail.ViewModels.CharacterViewModel</code> the result will not be the typical <code class="highlighter-rouge">MasterDetail.Views.CharacterView</code> but <code class="highlighter-rouge">MasterDetail.Views.Character.MasterView</code> and <code class="highlighter-rouge">MasterDetail.Views.Character.DetaisView</code> for our details panel. We now have two views for the same view model based on their context which can significantly reduce the complexity of our view models.</p> <p>The contents of the master and details view are straight forward.</p> <div class="language-xml highlighter-rouge"><pre class="highlight"><code><span class="cp">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span> <span class="nt">&lt;ContentView</span> <span class="na">xmlns=</span><span class="s">"http://xamarin.com/schemas/2014/forms"</span> <span class="na">xmlns:x=</span><span class="s">"http://schemas.microsoft.com/winfx/2009/xaml"</span> <span class="na">x:Class=</span><span class="s">"MasterDetail.Views.Character.MasterView"</span><span class="nt">&gt;</span> <span class="nt">&lt;ContentView.Content&gt;</span> <span class="nt">&lt;StackLayout</span> <span class="na">Padding=</span><span class="s">"12"</span><span class="nt">&gt;</span> <span class="nt">&lt;Label</span> <span class="na">Text=</span><span class="s">"{Binding Name}"</span> <span class="nt">/&gt;</span> <span class="nt">&lt;/StackLayout&gt;</span> <span class="nt">&lt;/ContentView.Content&gt;</span> <span class="nt">&lt;/ContentView&gt;</span> </code></pre> </div> <div class="language-xml highlighter-rouge"><pre class="highlight"><code><span class="cp">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span> <span class="nt">&lt;ContentView</span> <span class="na">xmlns=</span><span class="s">"http://xamarin.com/schemas/2014/forms"</span> <span class="na">xmlns:x=</span><span class="s">"http://schemas.microsoft.com/winfx/2009/xaml"</span> <span class="na">x:Class=</span><span class="s">"MasterDetail.Views.Character.DetailView"</span><span class="nt">&gt;</span> <span class="nt">&lt;ContentView.Content&gt;</span> <span class="nt">&lt;Grid&gt;</span> <span class="nt">&lt;Image</span> <span class="na">Source=</span><span class="s">"{Binding Image}"</span> <span class="na">Grid.Row=</span><span class="s">"0"</span> <span class="na">Aspect=</span><span class="s">"AspectFill"</span> <span class="nt">/&gt;</span> <span class="nt">&lt;StackLayout</span> <span class="na">Grid.Row=</span><span class="s">"0"</span> <span class="na">Padding=</span><span class="s">"24"</span> <span class="na">BackgroundColor=</span><span class="s">"#66000000"</span><span class="nt">&gt;</span> <span class="nt">&lt;Label</span> <span class="na">Text=</span><span class="s">"{Binding Name}"</span> <span class="na">TextColor=</span><span class="s">"#FFFFFF"</span> <span class="na">FontSize=</span><span class="s">"24"</span> <span class="na">FontAttributes=</span><span class="s">"Bold"</span> <span class="na">HorizontalTextAlignment=</span><span class="s">"Center"</span> <span class="nt">/&gt;</span> <span class="nt">&lt;Label</span> <span class="na">Text=</span><span class="s">"{Binding Tagline}"</span> <span class="na">TextColor=</span><span class="s">"#FFFFFF"</span> <span class="na">FontAttributes=</span><span class="s">"Italic"</span> <span class="na">HorizontalTextAlignment=</span><span class="s">"Center"</span> <span class="nt">/&gt;</span> <span class="nt">&lt;/StackLayout&gt;</span> <span class="nt">&lt;/Grid&gt;</span> <span class="nt">&lt;/ContentView.Content&gt;</span> <span class="nt">&lt;/ContentView&gt;</span> </code></pre> </div> <p>So there we have it, by making use of <code class="highlighter-rouge">View.Model</code> and <code class="highlighter-rouge">View.Context</code> we can create conducting view and view models that can be responsible for only the flow between master and details and not be mixed up with the data or display of the items themselves.</p> <p>We can use contexts to have multiples views for a view model even further reducing this complexity.</p> <p>The code for all of this is up on a new <a href="https://github.com/nigel-sampson/samples/tree/master/MasterDetail">GitHub samples repository</a> where I plan to post more of the code from posts like these.</p> Wed, 29 Mar 2017 00:00:00 +0000 http://compiledexperience.com/blog/posts/master-detail-forms http://compiledexperience.com/blog/posts/master-detail-forms nigel.sampson@compiledexperience.com (Nigel Sampson) caliburn-micro xamarin Caliburn.Micro roadmap <p>In the last couple of days I’ve put together and published a <a href="http://caliburnmicro.com/roadmap">roadmap</a> for Caliburn.Micro, there’s a couple of reasons for this. The first is help me plan what I want to do and what will be needed, the second to let people know what to expect in the future (although I deliberately didn’t attach dates to anything).</p> <p>It’s been a rough six months for me personally in terms of getting time to do open source development, but my life has settled down a lot now and I’m hoping to get back into it. This roadmap is the first step in that path.</p> <p>Part of this is also working out how I want to do development on these disparate areas and hopefully encourage other people to help out. I’m considering using GitHub projects to sketch things out in terms of adding notes and potentially pointing the way for others.</p> <p>Would love to know your thoughts on any of this and the <a href="http://caliburnmicro.com/roadmap">roadmap</a> itself.</p> Fri, 17 Feb 2017 00:00:00 +0000 http://compiledexperience.com/blog/posts/caliburn-micro-roadmap http://compiledexperience.com/blog/posts/caliburn-micro-roadmap nigel.sampson@compiledexperience.com (Nigel Sampson) caliburn-micro Supporting Xamarin.Forms Tabbed Page in Caliburn.Micro <p>One of the best features of Caliburn.Micro in my opinion is get away from “one view model per screen” and starting to compose view models together to form the screen.</p> <p>The framework itself supplies conductors to help facilitate this, as well as the behaviour of <code class="highlighter-rouge">View.Model</code> as as “Template Selector” on steroids.</p> <p>As a quick refresher what <code class="highlighter-rouge">View.Model</code> does when applied to <code class="highlighter-rouge">ContentControl</code> (or <code class="highlighter-rouge">ContentView</code> in Xamarin.Forms) is locate the view appropriate to the bound view model and inject it into the control (while binding the view and view model together).</p> <p>For instance given the following xaml:</p> <div class="language-xml highlighter-rouge"><pre class="highlight"><code><span class="nt">&lt;Grid&gt;</span> <span class="nt">&lt;ContentControl</span> <span class="na">cm:View.Model=</span><span class="s">"{Binding ActiveItem}"</span> <span class="nt">/&gt;</span> <span class="nt">&lt;/Grid&gt;</span> </code></pre> </div> <p>The contents of the <code class="highlighter-rouge">ContentControl</code> will be the view appropriate for the type of <code class="highlighter-rouge">ActiveItem</code>. If for instance it was <code class="highlighter-rouge">ProductsListViewModel</code> then the contents would be <code class="highlighter-rouge">ProductsListView</code>. What’s really great is that as <code class="highlighter-rouge">ActiveItem</code> changes to am instance of another type then the contents wil update with the new view as well.</p> <p>So how does this fit with <code class="highlighter-rouge">TabbedPage</code> in Xamarin.Forms?</p> <p>Well it works pretty seamlessly with a few tricks.</p> <p>First we’ll start with the view model that represents the tabbed page itself, I typically call this the shell. It inherits from <code class="highlighter-rouge">Conductor&lt;PageViewModel&gt;.Collection.OneActive</code> which essentially means that this view model conducts a collection of page view models where one is active at a time. This maps nicely to how a tab UI works.</p> <div class="language-csharp highlighter-rouge"><pre class="highlight"><code><span class="k">public</span> <span class="k">class</span> <span class="nc">ShellViewModel</span> <span class="p">:</span> <span class="n">Conductor</span><span class="p">&lt;</span><span class="n">PageViewModel</span><span class="p">&gt;.</span><span class="n">Collection</span><span class="p">.</span><span class="n">OneActive</span> <span class="p">{</span> <span class="p">...</span> <span class="p">}</span> </code></pre> </div> <p>In our shell view we have the <code class="highlighter-rouge">TabbedPage</code> itself, bound to the <code class="highlighter-rouge">Items</code> and <code class="highlighter-rouge">ActiveItem</code> of the shell view model. For the item template we have one gotcha. <code class="highlighter-rouge">TabbedPage</code> expects it’s contents to inherit from <code class="highlighter-rouge">Page</code>, so the root element of our data template but be <code class="highlighter-rouge">ContentPage</code>. Fortunately <code class="highlighter-rouge">View.Model</code> can handle this with no problem. We also make use of the display name property on <code class="highlighter-rouge">Screen</code> to supply the title for each tab.</p> <div class="language-xml highlighter-rouge"><pre class="highlight"><code><span class="nt">&lt;TabbedPage</span> <span class="na">ItemsSource=</span><span class="s">"{Binding Items}"</span> <span class="na">SelectedItem=</span><span class="s">"{Binding ActiveItem, Mode=TwoWay}"</span><span class="nt">&gt;</span> <span class="nt">&lt;TabbedPage.ItemTemplate&gt;</span> <span class="nt">&lt;DataTemplate&gt;</span> <span class="nt">&lt;ContentPage</span> <span class="na">Title=</span><span class="s">"{Binding DisplayName}"</span> <span class="na">cm:View.Model=</span><span class="s">"{Binding}"</span> <span class="nt">/&gt;</span> <span class="nt">&lt;/DataTemplate&gt;</span> <span class="nt">&lt;/TabbedPage.ItemTemplate&gt;</span> <span class="err">&lt;</span>/TabbedPage </code></pre> </div> <p>In our shell we can now add some pages:</p> <div class="language-csharp highlighter-rouge"><pre class="highlight"><code><span class="k">protected</span> <span class="k">override</span> <span class="k">void</span> <span class="nf">OnInitialize</span><span class="p">()</span> <span class="p">{</span> <span class="n">Items</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="k">new</span> <span class="nf">ProductsListViewModel</span><span class="p">());</span> <span class="n">Items</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="k">new</span> <span class="nf">LocationsViewModel</span><span class="p">());</span> <span class="n">Items</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="k">new</span> <span class="nf">ContactViewModel</span><span class="p">());</span> <span class="nf">ActivateItem</span><span class="p">(</span><span class="n">Items</span><span class="p">[</span><span class="m">0</span><span class="p">]);</span> <span class="p">}</span> </code></pre> </div> <p>As the tabs are selected our item template will locate the correct view for the above view models.</p> <p>What’s really interesting about this is that our shell doesn’t have to care about how the pages below it look or work. It can focus on it’s single reponsiblity which is the tabs themselves and any behaviour conducting their flow.</p> Thu, 02 Feb 2017 00:00:00 +0000 http://compiledexperience.com/blog/posts/tabbed-page-conductor http://compiledexperience.com/blog/posts/tabbed-page-conductor nigel.sampson@compiledexperience.com (Nigel Sampson) caliburn-micro xamarin Customising Pluralisation in Caliburn.Micro <p>Caliburn.Micro uses pluralisation in it’s conventions. It’s what turns an <code class="highlighter-rouge">x:Name</code> of <code class="highlighter-rouge">Products</code> into bindings of the <code class="highlighter-rouge">Products</code> and <code class="highlighter-rouge">SelectedProduct</code> properties.</p> <p>To be more accurate Caliburn.Micro uses Singularisation, and it’s implementation is rather naive that certainly don’t cope with the variety the english language provides, let alone other languages.</p> <p>It’s current implementation is:</p> <div class="language-csharp highlighter-rouge"><pre class="highlight"><code><span class="k">public</span> <span class="k">static</span> <span class="n">Func</span><span class="p">&lt;</span><span class="kt">string</span><span class="p">,</span> <span class="kt">string</span><span class="p">&gt;</span> <span class="n">Singularize</span> <span class="p">=</span> <span class="n">original</span> <span class="p">=&gt;</span> <span class="p">{</span> <span class="k">return</span> <span class="n">original</span><span class="p">.</span><span class="nf">EndsWith</span><span class="p">(</span><span class="s">"ies"</span><span class="p">)</span> <span class="p">?</span> <span class="n">original</span><span class="p">.</span><span class="nf">TrimEnd</span><span class="p">(</span><span class="sc">'s'</span><span class="p">).</span><span class="nf">TrimEnd</span><span class="p">(</span><span class="sc">'e'</span><span class="p">).</span><span class="nf">TrimEnd</span><span class="p">(</span><span class="sc">'i'</span><span class="p">)</span> <span class="p">+</span> <span class="s">"y"</span> <span class="p">:</span> <span class="n">original</span><span class="p">.</span><span class="nf">TrimEnd</span><span class="p">(</span><span class="sc">'s'</span><span class="p">);</span> <span class="p">};</span> </code></pre> </div> <p>There are however some fanstasic libraries out there to deal with manipulating language in this way, and Caliburn.Micro can be updated to use them. I’m talking in particular about the library <a href="https://github.com/Humanizr/Humanizer">Humanizer</a>.</p> <p>Having the following in our application configure code switches the framework to use Humanizer for it’s conventions and be able to deal with all the property names it couldn’t deal with before.</p> <div class="language-csharp highlighter-rouge"><pre class="highlight"><code><span class="n">ConventionManager</span><span class="p">.</span><span class="n">Singularize</span> <span class="p">=</span> <span class="n">original</span> <span class="p">=&gt;</span> <span class="n">original</span><span class="p">.</span><span class="nf">Singularize</span><span class="p">(</span><span class="n">inputIsKnownToBePlural</span><span class="p">:</span> <span class="k">false</span><span class="p">);</span> </code></pre> </div> Fri, 20 Jan 2017 00:00:00 +0000 http://compiledexperience.com/blog/posts/customising-pluralisation http://compiledexperience.com/blog/posts/customising-pluralisation nigel.sampson@compiledexperience.com (Nigel Sampson) caliburn-micro NDC Sydney Video <p>Forgot to post about it at the time, but the video for talk <a href="https://www.youtube.com/watch?v=x266Vy4tfT0">Cross Platform Mobile with XAML and MVVM</a> from NDC Sydney is available online..</p> <p>All the demos for this talk can be found on <a href="https://github.com/nigel-sampson/talks/tree/master/ndc-sydney">GitHub</a>.</p> Tue, 10 Jan 2017 00:00:00 +0000 http://compiledexperience.com/blog/posts/NDC-Sydney-Video http://compiledexperience.com/blog/posts/NDC-Sydney-Video nigel.sampson@compiledexperience.com (Nigel Sampson) xamarin caliburn-micro mvvm talks MVP renewed for 2017 <p>Pleased to say that I’ve had my Microsoft MVP renewed for the fourth year.</p> <p>Last year was a reasonably quiet year in terms of activity and I’m certainly looking to step it up this year.</p> <p>Although according to some TED talks announcing goals increase the likelihood of failure, so you’ll just have to wait and see.</p> Mon, 09 Jan 2017 00:00:00 +0000 http://compiledexperience.com/blog/posts/2017-MVP http://compiledexperience.com/blog/posts/2017-MVP nigel.sampson@compiledexperience.com (Nigel Sampson) My new cross platform setup <p>These days I’m doing more cross platform mobile work at home and decided to try a new approach.</p> <p>I’m using a Mac Mini for iOS / Xamarin work but having a dedicated monitor for it felt wasteful since it wasn’t used that often (it mostly functioned as a built server).</p> <p>I’ve been hearing people lately raving about ultra wide screen monitors and thought I’d give it a go.</p> <p>I picked up a <a href="http://accessories.ap.dell.com/sna/productdetail.aspx?c=hk&amp;l=en&amp;s=bsd&amp;cs=hkbsd1&amp;sku=210-AEBV">Dell U3415W</a> and so far am in love with it. While doing Windows &amp; Android development I can give the full screen real estate to Windows, the Dell Display Manager that comes with the monitor lets me set up custom snap points for my windows. So far the one I like the best is two thirds for Visual Studio, then divide the rest of the horizontal space in two vertically for things like Powershell, emulators and the like. The total available resolution is 3440 x 1440.</p> <p>Where it really steps up is doing iOS / Xamarin development, I can switch on Picture by Picture mode giving half the screen to the Windows machine and half to the Mac. The Windows machine is using HDMI and the Mac Display Port. This gives each device 1720 x 1440 to play with which is plenty.</p> <p><a href="/content/images/posts/cross-platform-setup.jpg"><img width="600" src="/content/images/posts/cross-platform-setup.jpg" /></a></p> <p>Installing <a href="http://symless.com/">Synergy</a> on both machines means I can use the same mouse and keyboard for both including copy &amp; pasting. The whole thing is so seamless I occasionally find myself trying to drag windows from one side to the other.</p> <p>It’s only been a few weeks so far but at the moment I can highly recommend it.</p> Sat, 28 May 2016 00:00:00 +0000 http://compiledexperience.com/blog/posts/cross-platform-setup http://compiledexperience.com/blog/posts/cross-platform-setup nigel.sampson@compiledexperience.com (Nigel Sampson) xamarin