<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[This Old Brain]]></title><description><![CDATA[Tech, thoughts, and Weird Doings from Jason DeBoever's wrinkled grey mass]]></description><link>https://thisoldbrain.com/</link><image><url>https://thisoldbrain.com/favicon.png</url><title>This Old Brain</title><link>https://thisoldbrain.com/</link></image><generator>Ghost 1.19</generator><lastBuildDate>Mon, 20 Apr 2026 01:31:25 GMT</lastBuildDate><atom:link href="https://thisoldbrain.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Ultimate Guide to Deep Source Stepping Into [almost] Anything [in Visual Studio]]]></title><description><![CDATA[<div class="kg-card-markdown"><p>Sometimes our code doesn't work (no seriously, it happens). We debug and step through, all looks well, at some point it enters into some method we don't control -maybe part of the core framework- and <strong>BOOM</strong> an exception. Or maybe the data just comes out the other end all ugly</p></div>]]></description><link>https://thisoldbrain.com/source-step-into-anything/</link><guid isPermaLink="false">5ac77bcf6fc1b72508a77c22</guid><category><![CDATA[Xamarin]]></category><category><![CDATA[VisualStudio]]></category><dc:creator><![CDATA[Jason DeBoever]]></dc:creator><pubDate>Sun, 15 Apr 2018 21:08:49 GMT</pubDate><media:content url="https://thisoldbrain.com/content/images/2018/04/callstacktitle.png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://thisoldbrain.com/content/images/2018/04/callstacktitle.png" alt="Ultimate Guide to Deep Source Stepping Into [almost] Anything [in Visual Studio]"><p>Sometimes our code doesn't work (no seriously, it happens). We debug and step through, all looks well, at some point it enters into some method we don't control -maybe part of the core framework- and <strong>BOOM</strong> an exception. Or maybe the data just comes out the other end all ugly and wrong.</p>
<p>In this post you'll find out exactly how to step right in to this 'foreign source code', breakpoints and all. I've used these techniques just in the last few weeks to peak into Xamarin inner workings as well as figure out why the openIdConnect library was periodically refusing to validate my tokens. Once you can do this, it's a tool you'll never want to live without.</p>
<p>Of course the .Net Framework and many, many of the libraries we use are open source, but this does not automatically make it easy to debug into them. To compile the source ourselves for debugging, even in the easiest scenario we have to clone the repo, find the build script, change our project, and hope.</p>
<p>Things rarely go that easily. Often git repos aren't tagged with releases so you don't which revision to grab. You may have a reference hierarchy relying on strong naming, and while you may have source, you certainly don't have signing keys. And of course if you're not sure what's going on, you may have several different libraries you need to build and integrate and walk through and that can be extremely time-consuming.</p>
<p>Many of you will know that Visual Studio has long had <code>Enable Source Server Support</code> option and <code>Enable .Net Framework source stepping</code> but those never quite seemed to work the way we wanted. If we add the source servers from <a href="http://SymbolSource.org">http://SymbolSource.org</a> we get a bit more help. They maintain their own servers with debugging symbols (often with source code), and include many of the instructions necessary to get things working (all of which are included in my complete instructions below). While this helped, it wasn't complete.</p>
<p>A few of you may even know that Visual Studio has added <code>Enable Source Link Support</code> which will be a whole lot better and easier to use than the <code>Enable Source Server</code> option, but until the whole world including all of our legacy version references support it, we're going to need a blended approach, and even with source link, some of the steps you'll find below can be required. A lot more information on &quot;Source Link&quot; here: <a href="https://github.com/dotnet/designs/blob/master/accepted/diagnostics/source-link.md">https://github.com/dotnet/designs/blob/master/accepted/diagnostics/source-link.md</a>.</p>
<p>The <code>Source Link</code> and <code>Source Server</code> options are, unfortunately, mutually exclusive - or at least they are in practice - you can check both but the <code>Source Server</code> option will take precedence. This means that part of the <em>ultimate solution</em> is to toggle the options and see what works best with the symbols you have available to you.</p>
<blockquote>
<p><code>Source Link</code> and <code>Source Server</code> (as well as other helpful debug info) rely on something called &quot;debug symbols&quot;. What are those? When a module is compiled for release, it's generally made as small and performant as possible, meaning a lot of information is omitted -- information that would be helpful in troubleshooting and debugging. Things like variable and method names, and how to correlate an executing instruction to a line in a source file. That information, which we refer to as &quot;debug symbols&quot; is omitted from the compiled module itself, but can be included in a separate file that usually has the extension <code>.pdb</code>. Sometimes the 'pdb' files are distributed with the module and sometimes we can find them from well known locations called &quot;Symbol Servers&quot; (as discussed below)</p>
</blockquote>
<p>The final complexity we have to address is that if we want to step into framework and release libraries, we'll often be dealing &quot;Compiler optimizations&quot;. That means that what is loaded into memory and executing does not match the code that existed when the library was compiled and the .pdb (debugging symbols) was generated. The compiler optimizations are allowed to change the code itself, as long as they don't change the symantics - that is, as long as they don't change how the program behaves to an outside observer. To put it yet another way: for given inputs, the outputs and side-effects are not changed. These optimizations can make step-through and breakpoints <em>partially</em> work for a given module: some breakpoints being hit, others being ignored. <strong>It's quite frustrating.</strong></p>
<p>Compiler optimizations can take two forms:<br>
1. JIT'ing: In other words the assembly is compiled to CIL (.Net's meta-language) and is CIL on disk but as the code was loaded into memory, it was compiled to native with optimizations turned on. To avoid this, we simply need enable the Debugging option <code>Suppress JIT optimization on module Load</code>.<br>
2. The other form is when an assembly was compiled to native image on disk (the author would have done this with NGEN.exe for performance reasons [using NGEN yourself is outside the scope of this article]). The solution to this is a bit more awkward: you have to instruct your system to always look for a regular 'CIL' version of the assembly and prefer that to the native image. You can  do this by having an environment variable set while launching Visual Studio. Since you really don't want this option on all the time, you'll probably want to launch VS from a command line. The environment variable is <code>set COMPLUS_ZapDisable=1</code>. (In fact, there are other ways around this too, check out this link for more: <a href="https://github.com/Microsoft/dotnet/blob/master/Documentation/testing-with-ryujit.md">https://github.com/Microsoft/dotnet/blob/master/Documentation/testing-with-ryujit.md</a>).</p>
<h1 id="thestepbystep">The Step by Step</h1>
<h2 id="1setupyourdebuggingoptions">1. Set up your debugging options##</h2>
<p><img src="https://thisoldbrain.com/content/images/2018/04/debuggingOptions-1.png" alt="Ultimate Guide to Deep Source Stepping Into [almost] Anything [in Visual Studio]"></p>
<p>Ok, first the easy ones</p>
<ol>
<li><code>Enable Just My Code</code> - <em>OFF</em> - This one should be obvious.</li>
<li><code>Require source files to exactly match the original version</code> - <em>OFF</em> - This doesn't really seem to help much you still need a perfect match for your .pdb -- you'll rarely have the exact matching .pdb but have it pointing at not-quite-matching source files -- but turn it off anyway.</li>
</ol>
<p>It would be super if we could go through <em>all</em> those options one-by-one, but there are some complex interdependencies as we discussed above. So you may need to try some different combinations.</p>
<p>Let's start by trying the &quot;New Hotness&quot; way<br>
2. <code>Enable .Net Framework Source Stepping</code> - <em>ON</em> - More on this one later, but we'll try &quot;on&quot; first.<br>
3. <code>Enable Source Server Support</code> - <em>OFF</em> - To quote Will Smith, this is the &quot;old and busted&quot;. It's not really busted, just less ideal, so we're going to try this one later.<br>
4. <code>Enable Source Link Support</code> - <em>ON</em> - Agent J in a new suit - See above for more discussion on this and a link to the real deep stuff.<br>
6. <code>Suppress JIT optimization on Module Load</code> - <em>OFF</em> - Turn this bad boy off so we can breakdance and get stepping. I mean hit breakpoint and step through the source.</p>
<p>We're going to go with these options to start. Let's move on to the other steps.</p>
<h2 id="2setsymbolservers">2. Set Symbol Servers</h2>
<p>While you're in that options window let's go down to the Debugging &gt; Symbols window.</p>
<p><img src="https://thisoldbrain.com/content/images/2018/04/Symbols.png" alt="Ultimate Guide to Deep Source Stepping Into [almost] Anything [in Visual Studio]"></p>
<p>Under symbol file locations copy the values in the screenshot. Under Automatic Symbol Loading Preference, you can select &quot;all&quot; but it will take a <em>looooooooong</em> time to launch any debugging sessions. We'll address how to handle them individually later. So for now you should probably select <code>Load Only Specified Modules</code>. Don't worry about specifying them yet.</p>
<h2 id="3launchvisualstudioinaspecialway">3. Launch Visual Studio in a Special Way</h2>
<p>This step may actually be optional. If you can debug into everything you need to debug into without it, well, my friend, good for you.</p>
<p>As discussed above there are a few ways to handle this environment variable, but we're going to go with the temporary, easy way. Fire up a command prompt (if you need visual studio to launch with Administator privileges then your command prompt should be launched with Administrator privileges). Enter the following:</p>
<pre>
<code>
    set COMPLUS_ZapDisable=1 
    cd /d "%ProgramFiles(X86)%\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\" 
    start devenv.exe 
</code>
</pre>
<p>If that path doesn't match your path, adjust appropriately.</p>
<h2 id="4loadsymbols">4. Load Symbols</h2>
<p>The first thing you need to understand is you will not be able just &quot;Go To Definition&quot; and get into some source. (Though that is a sorely needed feature). To get into the foreign source we're going to first need to set a breakpoint in our own code. So go do that. Then start debugging.</p>
<p>Once you are on a breakpoint, it's time load the foreign symbols. You have two options for this:</p>
<ol>
<li>If you are lucky enough to be able to put your breakpoint in a spot where the foreign library is in the call stack (like in a callback), then you can go to your call stack window (Ctrl+Alt+C), right click on the line with the foreign module and select &quot;Load Symbols&quot; or &quot;Always Load Automatically&quot;. The latter will put this module in the list that will be fetched pro-actively every time you debug from here on out.</li>
</ol>
<p><img src="https://thisoldbrain.com/content/images/2018/04/LoadSymbols.png" alt="Ultimate Guide to Deep Source Stepping Into [almost] Anything [in Visual Studio]"></p>
<ol start="2">
<li>The other option still requires you to be on a breakpoint, but that's all. Go to your Modules window (no hotkey, Debug-&gt;Windows-&gt;Modules). Once again you can right click and select &quot;Load Symbols&quot; or &quot;Always Load Automatically&quot;.</li>
</ol>
<p>Annnnd hopefully that's it for loading symbols. If they are available in any of the servers listed above all is well and it will show in the Call Stack or Modules Window that symbols are loaded.</p>
<p>If not, it will prompt you to find them. If they aren't available from any of those servers you may get lucky and they included in the nuget package (Xamarin.Forms does this, for example), so check your nuget various nuget caches, find the assembly, and see if it has a .pdb with it (the .pdb is the symbol file you want).</p>
<h4 id="commonnugetlocations">Common Nuget Locations</h4>
<ol>
<li>If there is a <code>Packages</code> folder as a sibling of your .sln file</li>
<li>%userprofile%.nuget\packages</li>
</ol>
<p>If this doesn't work, you may need to try the other option <code>Enable Source Server Support</code> - jump to Step 6, you won't need to tweak much. Or, if you just can't find a .pdb you may need to contact the author of the module (Microsoft put out .pdb's for pretty much <em>everything</em> it publishes).</p>
<h2 id="5debug">5. Debug!</h2>
<p>If the module you want to debug is in the call stack you can right click the module you want source for, now that the symbols are loaded a new option may appear: <code>Go To Source Code</code>.</p>
<p>Alternatively you can <code>Step</code> through your code until you get to a line in your own code that calls in to the foreign module. If you <code>Step Into</code> (F11), it should bring you to the source for the foreign module!!!</p>
<p>Not working? Symbols loaded but can't find the source file? No problem, our alternative technique from Step 6 might still work! Alternatively, when it prompts you for where the source file is, if you've got the source, browse to it yourself!</p>
<p>At this point, you can keep stepping, add breakpoints, go nuts! The breakpoints will last through restarting the debug session just like all your other breakpoints, and if you chose to &quot;Always Load Symbols&quot; for this module, it will all just automatically work the next time your start debugging this project!</p>
<h2 id="6itdidntwork">6. It didn't work?</h2>
<p>Ok, it's cool, we have a couple tricks up our sleeve. As of this writing, a lot of existing stuff is still going to require the &quot;old way&quot;. So let's go back to our Options dialog: Debugging-&gt;General</p>
<p><img src="https://thisoldbrain.com/content/images/2018/04/debuggingOptions.png" alt="Ultimate Guide to Deep Source Stepping Into [almost] Anything [in Visual Studio]"></p>
<p>Change 3. to <em>ON</em> and 4. to <em>OFF</em>.</p>
<p>You may want to restart Visual Studio (using the technique described in Step 3), but this might not be necessary.</p>
<p>Try loading symbols and stepping through again (Steps 4 &amp; 5).</p>
<p>Still no? We're getting desperate here now. The last thing to try is turning <code>2. Enable .NET Framwork Source Stepping</code> to <em>OFF</em>. That setting doesn't seem to cause any problems, but some documentation on <a href="http://www.symbolsource.org/Public/Home/VisualStudio">SymbolSource.org</a> indicates that once upon a time it did. So hey, give it a shot.</p>
<p>If you still aren't up and running it could be that there are no symbols available with source code information. That's rare with Microsoft assemblies, but certainly happens with third party components. And that's why there is &quot;Almost&quot; in the title of this blog post :(</p>
</div>]]></content:encoded></item><item><title><![CDATA[Creating a custom button with ripple effect in Xamarin Forms]]></title><description><![CDATA[<div class="kg-card-markdown"><blockquote>
<p>This post is a guest posting from <a href="http://hofmadresu.com">Matt Hoffman (http://www.hofmadresu.com)</a>. He had mentioned to me some of the interesting problems he had getting a ripple effect into a custom Xamarin Forms button. The ultimate solution he found is fairly simple, but some of the obvious choices like</p></blockquote></div>]]></description><link>https://thisoldbrain.com/creating-a-custom-button-with-ripple-effect-in-xamarin-forms/</link><guid isPermaLink="false">5ac7c8636fc1b72508a77c25</guid><category><![CDATA[Xamarin]]></category><dc:creator><![CDATA[Jason DeBoever]]></dc:creator><pubDate>Thu, 12 Apr 2018 15:54:53 GMT</pubDate><media:content url="https://thisoldbrain.com/content/images/2018/04/Screen-Shot-2018-04-12-at-12.18.36-PM.png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><blockquote>
<img src="https://thisoldbrain.com/content/images/2018/04/Screen-Shot-2018-04-12-at-12.18.36-PM.png" alt="Creating a custom button with ripple effect in Xamarin Forms"><p>This post is a guest posting from <a href="http://hofmadresu.com">Matt Hoffman (http://www.hofmadresu.com)</a>. He had mentioned to me some of the interesting problems he had getting a ripple effect into a custom Xamarin Forms button. The ultimate solution he found is fairly simple, but some of the obvious choices like &quot;Use an effect&quot; didn't work for various reasons. So I asked if he'd be interested in writing a post about it! He gives us a solution below that hard codes the &quot;counting behavior&quot; of the button for simplicity of demo, but should be really easy to generalize if you want to do something similar yourself! -Jason DeBoever</p>
</blockquote>
<p>Xamarin Forms is powerful system and allows for a lot of customization out of the box. However, sometimes you need to go beyond the default controls and build something custom. I recently ran into this when I needed to build a multi-line custom button similiar to<br>
<img src="https://thisoldbrain.com/content/images/2018/04/RippleButtonExample-1.gif" width="500" alt="Creating a custom button with ripple effect in Xamarin Forms"></p>
<p>The Button control in Xamarin Forms only allows a single line of text and doesn't provide a way to customize the button's layout. You could create a custom control within Forms using a StackLayout and a TapGestureRecognizer, but you would lose responsive behaviors like color changes on iOS and the ripple effect on Android. This is where custom renderers come in.</p>
<p>Xamarin provides documentation on how to create a custom renderer in several situations <a href="https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/custom-renderer/" target="_blank">here</a> but there isn't anything specific to custom buttons, so I thought I'd write down what I did to create this effect. All of the code for this post is available on <a href="https://github.com/HofmaDresu/XamarinRippleRendererBlogPost" target="_blank">GitHub</a> with tags for each step of the process. If you want to follow along, start with the tag &quot;initial-view-model&quot;</p>
<p>The first thing to do is to set up our view and view model so they handle any bindable data you need. In this case we'll create two buttons that, when clicked, increment a counter. The counter is displayed below each button. The view XAML is:</p>
<pre><code class="language-markup">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;ContentPage 
    xmlns="http://xamarin.com/schemas/2014/forms" 
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
    xmlns:local="clr-namespace:RippleRenderer" 
    x:Class="RippleRenderer.RippleRendererPage"
    xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core" 
    ios:Page.UseSafeArea="true"&gt;
    &lt;StackLayout
        Orientation="Vertical"&gt;
        &lt;Button Text="Click me 1" BackgroundColor="Blue" TextColor="White" Command="{Binding Button1ClickCommand}"/&gt;
        &lt;StackLayout Orientation="Horizontal"&gt;
            &lt;Label Text="Button 1 click count: "/&gt;
            &lt;Label Text="{Binding Button1ClickCount}" /&gt;
        &lt;/StackLayout&gt;
        &lt;Button Text="Click me 2" BackgroundColor="Red" TextColor="White" Command="{Binding Button2ClickCommand}"/&gt;
        &lt;StackLayout Orientation="Horizontal"&gt;
            &lt;Label Text="Button 2 click count: "/&gt;
            &lt;Label Text="{Binding Button2ClickCount}" /&gt;
        &lt;/StackLayout&gt;
    &lt;/StackLayout&gt;
</code></pre>
<p>And the view model code is</p>
<pre><code class="language-csharp">
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using Xamarin.Forms;

namespace RippleRenderer
{
    public class RippleRendererViewModel : INotifyPropertyChanged
    {
        public RippleRendererViewModel()
        {
            Button1ClickCommand = new Command(() => Button1ClickCount++);
            Button2ClickCommand = new Command(() => Button2ClickCount++);
        }

        private int _button1ClickCount = 0;
        public int Button1ClickCount
        {
            get => _button1ClickCount;
            set 
            {
                _button1ClickCount = value;
                OnPropertyChanged(); 
            }
        }

        private int _button2ClickCount = 0;
        public int Button2ClickCount
        {
            get => _button2ClickCount;
            set
            {
                _button2ClickCount = value;
                OnPropertyChanged();
            }
        }

        public Command Button1ClickCommand { get; set; }
        public Command Button2ClickCommand { get; set; }

        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged([CallerMemberName]string propertyName = "") =>
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}                  
</code></pre>
<p>It may seem like overkill to set up the View this way even though we plan to replace the buttons and labels with our own custom content, but it serves a purpose. This way we can verify that we have all the bindings we need in place and working before we start getting into the more interesting, and more complicated, renderer logic.</p>
<h1 id="settingupthecustomrendererinforms">Setting up the custom renderer in Forms</h1>
<p>The first thing we need to do is determine what data we need to bind to our custom button. For this example we need four items: the button title, the button's click count, the button's click command, and the button's background color. We then create a custom control in the Forms project that subclasses View. It may seem like Button would be a better base class, but the Android button has similar limitations to the Xamarin Forms button and can't use a custom layout. To support Android, we need to use the more generic View type. Since our control's UI will be handled by custom renderers, we can create a class with no XAML component:</p>
<pre><code class="language-csharp">
using Xamarin.Forms;

namespace RippleRenderer
{
    public class IncrementingButton : View
    {
        public static readonly BindableProperty TitleProperty = 
            BindableProperty.Create("Title", typeof(string), typeof(IncrementingButton), string.Empty);
        public string Title
        {
            get { return (string)GetValue(TitleProperty); }
            set { SetValue(TitleProperty, value); }
        }
        
        public static readonly BindableProperty ClickCountProperty =
            BindableProperty.Create("ClickCount", typeof(int), typeof(IncrementingButton), 0);
        public int ClickCount
        {
            get { return (int)GetValue(ClickCountProperty); }
            set { SetValue(ClickCountProperty, value); }
        }

        public Command Command
        {
            get => (Command)GetValue(CommandProperty);
            set => SetValue(CommandProperty, value);
        }

        public static readonly BindableProperty CommandProperty =
            BindableProperty.Create("Command", typeof(Command), typeof(IncrementingButton), null);
    }
}              
</code></pre>
<p>Notice that there is no BackgroundColor property in the code. This is because BackgroundColor is already implemented by View and we can use that for our control.<br>
Next we need to use the new control in our View. Since our control is in the same namespace as the view, we can just use the 'local' XML namespace created by Xamarin. If 'local' is missing or the control is in a different namespace, we would need to create a new XML namespace. Now we can use our new control just like any built-in control:</p>
<pre><code class="language-markup">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;ContentPage 
    xmlns="http://xamarin.com/schemas/2014/forms" 
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
    xmlns:local="clr-namespace:RippleRenderer" 
    x:Class="RippleRenderer.RippleRendererPage"
    xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core" 
    ios:Page.UseSafeArea="true"&gt;
    &lt;StackLayout
        Orientation="Vertical"&gt;
        &lt;Button Text="Click me 1" BackgroundColor="Blue" TextColor="White" Command="{Binding Button1ClickCommand}"/&gt;
        &lt;StackLayout Orientation="Horizontal"&gt;
            &lt;Label Text="Button 1 click count: "/&gt;
            &lt;Label Text="{Binding Button1ClickCount}" /&gt;
        &lt;/StackLayout&gt;
        &lt;Button Text="Click me 2" BackgroundColor="Red" TextColor="White" Command="{Binding Button2ClickCommand}"/&gt;
        &lt;StackLayout Orientation="Horizontal"&gt;
            &lt;Label Text="Button 2 click count: "/&gt;
            &lt;Label Text="{Binding Button2ClickCount}" /&gt;
        &lt;/StackLayout&gt;
    &lt;/StackLayout&gt;    
&lt;/ContentPage&gt;
</code></pre>
<p>Note: at this point if we run the app we won't be able to see anything on any platform. Since we haven't create a custom renderer yet, Xamarin defaults to a basic View renderer. And since our views have no content, nothing is displayed. If you want to verify that Xamarin is in fact rendering a view, you can add a non-zero HeightRequest and run the application. The completed code for this step is available at tag &quot;forms-custom-control&quot;.</p>
<h1 id="creatingacustomrendererinandroid">Creating a custom renderer in Android</h1>
<p>Now that we have the custom control in place, we need to tell Xamarin Forms how to display it. The first thing we need to do is create a layout. For this example we're using a basic LinearLayout with two TextViews. Each TextView needs an Id so we can add text later.</p>
<pre><code class="language-markup">
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"&gt;
    &lt;TextView
        android:id="@+id/ButtonTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="#FFFFFF" /&gt;
    &lt;TextView
        android:id="@+id/ClickCount"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="#FFFFFF" /&gt;
&lt;/LinearLayout&gt;
</code></pre>
<p>Next we need to create our custom renderer and consume the layout. This is where things start to get fun, so we're going to take it in multiple steps:</p>
<ol>
<li>The basic renderer</li>
<li>Adding a background with the ripple effect</li>
<li>Responding to click events and updating the click count</li>
</ol>
<h2 id="1thebasicrenderer">1. The basic renderer</h2>
<p>Now we'll create a basic renderer that displays our control with the initial data. We create a class called IncrementingButtonRenderer_Android in the Android project. The &quot;_Android&quot; part of the name is not necessary, but useful to help differentiate our renderers on each platform. The class should be a subclass of ViewRenderer&lt;IncrementingButton, Android.Views.View&gt;. We need to implement the constructor IncrementingButtonRenderer_Android(Context context) : base(context) and store Context in a private field for later use.</p>
<pre><code class="language-csharp">
using System.ComponentModel;
using Android.Content;
using Android.Views;
using Android.Widget;
using RippleRenderer;
using RippleRenderer.Droid;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;

namespace RippleRenderer.Droid
{
    public class IncrementingButtonRenderer_Android : ViewRenderer&lt;IncrementingButton, Android.Views.View&gt;
    {
        private readonly Context _context;

        public IncrementingButtonRenderer_Android(Context context) : base(context)
        {
            _context = context;
        }
    }
}
</code></pre>
<p>Next we'll override OnElement changed. In it we need to inflate our layout, set the text on our TextViews, and tell Xamarin Forms to use the inflated layout for this control. It's good practice to wrap this logic in an if block to prevent re-initilization. We also want to store references to our TextViews in private fields for later use.</p>
<pre><code class="language-csharp">
private TextView _buttonTitleView;
private TextView _clickCountView;

protected override void OnElementChanged(ElementChangedEventArgs e)
{
    base.OnElementChanged(e);

    if (Control == null)
    {
        // Inflate the IncrementingButton layout
        var inflater = _context.GetSystemService(Context.LayoutInflaterService) as LayoutInflater;
        var rootLayout = inflater.Inflate(Resource.Layout.IncrementingButton, null, false);

        // Set text on Textviews
        _buttonTitleView = rootLayout.FindViewById(Resource.Id.ButtonTitle);
        _buttonTitleView.Text = Element.Title;
        _clickCountView = rootLayout.FindViewById(Resource.Id.ClickCount);
        _clickCountView.Text = $"Clicked {Element.ClickCount} times";

        // Tell Xamarin to user our layout for the control
        SetNativeControl(rootLayout);
    }

</code></pre>
<p>The final step for the basic renderer is to add an attribute telling Xamarin Forms to use our custom renderer for the IncrementingButton control.</p>
<pre><code class="language-csharp">
[assembly: ExportRenderer(typeof(IncrementingButton), typeof(IncrementingButtonRenderer_Android))]
namespace RippleRenderer.Droid
{
    public class IncrementingButtonRenderer_Android : ViewRenderer&lt;IncrementingButton, Android.Views.View&gt;
    {
...     
</code></pre>
<p>At this point we can run the application and see our custom buttons on the screen.<br>
<img src="https://thisoldbrain.com/content/images/2018/04/InitialAndroidCustomButtons.png" width="300" alt="Creating a custom button with ripple effect in Xamarin Forms"><br>
The completed code for this step is available at tag &quot;android-initial-custom-control&quot;. Next we'll add the ripple effect.</p>
<h2 id="2addingabackgroundwiththerippleeffect">2. Adding a background with the ripple effect</h2>
<p>Now that the renderer is in place, we want to start giving feedback to the user when they touch our button. On Android we're going to use the Ripple effect, which is availabile starting in API version 21. We'll use Android's Drawable classes to create a statelist that handles the ripple behavior for us. Since we have a different background for each button, we need to create the drawable in code rather than in an xml file.</p>
<pre><code class="language-csharp">
private void SetBackground(Android.Views.View rootLayout)
{
    // Get the background color from Forms element
    var backgroundColor = Element.BackgroundColor.ToAndroid();

    // Create statelist to handle ripple effect
    var enabledBackground = new GradientDrawable(GradientDrawable.Orientation.LeftRight, new int[] { backgroundColor, backgroundColor });
    var stateList = new StateListDrawable();
    var rippleItem = new RippleDrawable(ColorStateList.ValueOf(Android.Graphics.Color.White),
                                        enabledBackground,
                                        null);
    stateList.AddState(new[] { Android.Resource.Attribute.StateEnabled }, rippleItem);

    // Assign background
    rootLayout.Background = stateList;
}
</code></pre>
<p>Call this method in OnElementChanged just before SetNativeControl. If you need to support older versions you can wrap this code in an if block checking for Build.VERSION.SdkInt &gt;= BuildVersionCodes.Lollipop and implement alternate logic in the else block.</p>
<p>If we try to run now, we'll notice that nothing happens when you press the buttons. This is because we need to tell Android to respond to click events on our LinearLayout</p>
<pre><code class="language-markup">
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clickable="true"&gt;
</code></pre>
<p>With this in place, we can run the app and watch the ripple effect respond to our touches!<br>
<img src="https://thisoldbrain.com/content/images/2018/04/AndroidRippleEffect.gif" width="300" alt="Creating a custom button with ripple effect in Xamarin Forms"><br>
The completed code for this step is available at tag &quot;android-ripple&quot;. Next we'll respond to the click event and update the buttons' click counts.</p>
<h2 id="3respondingtoclickeventsandupdatingclickcount">3. Responding to click events and updating click count</h2>
<p>There are two steps remaining to make this button fully functional on Android. First we need to call the bound command when the user taps the button. This can be done in a single line of code in OnElementChanged, right after SetNativeControl</p>
<pre><code class="language-csharp">
...
// Tell Xamarin to user our layout for the control
SetNativeControl(rootLayout);

// Execute the bound command on click
rootLayout.Click += (s, a) => Element.Command?.Execute(null);
}
</code></pre>
<p>Next we need to update the click counts we show the user. For this we override a new method, OnElementPropertyChanged, and watch for any changes to the ClickCountProperty.</p>
<pre><code class="language-csharp">
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
    base.OnElementPropertyChanged(sender, e);
    if (e.PropertyName == IncrementingButton.ClickCountProperty.PropertyName)
    {
        _clickCountView.Text = $"Clicked {Element.ClickCount} times";
    }
}       
</code></pre>     
<p>Now we can run the app and see our click counts<br>
<img src="https://thisoldbrain.com/content/images/2018/04/AndroidUpdateClickCount.gif" width="300" alt="Creating a custom button with ripple effect in Xamarin Forms"><br>
The completed code for this step is available at tag &quot;android-update-click-count&quot;. Now that Android is complete, we'll switch over to iOS and implement a renderer there.</p>
<h1 id="creatingacustomrendererinios">Creating a custom renderer in iOS</h1>
<p>Creating the custom renderer in iOS follows the same basic steps we used for Android. The only differences are that we'll create the layout in code and we're going to change the background color on tap instead of showing the Android ripple effect.</p>
<ol>
<li>The basic renderer</li>
<li>Adding a background that changes color when tapped</li>
<li>Responding to click events and updating the click count</li>
</ol>
<h2 id="1thebasicrenderer">1. The basic renderer</h2>
<p>Much like on Android, the first thing we'll do on iOS is create a basic renderer that displays our control with the initial data. We create a class called IncrementingButtonRenderer_iOS in the iOS project and override OnElementChanged to  create our button's layout.</p>
<pre><code class="language-csharp">
using RippleRenderer;
using RippleRenderer.iOS;
using System;
using System.ComponentModel;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;

[assembly: ExportRenderer(typeof(IncrementingButton), typeof(IncrementingButtonRenderer_iOS))]
namespace RippleRenderer.iOS
{
    class IncrementingButtonRenderer_iOS : ViewRenderer&lt;IncrementingButton, UIView&gt;
    {
        private UILabel _buttonTitleLabel;
        private UILabel _clickCountLabel;

        protected override void OnElementChanged(ElementChangedEventArgs<incrementingbutton> e)
        {
            base.OnElementChanged(e);

            var rootView = CreateLayout();

            AddTouchBehavior(rootView);

            // Tell Xamarin to user our layout for the control
            SetNativeControl(rootView);
        }

        private UIButton CreateLayout()
        {
            var rootView = new UIButton
            {
                BackgroundColor = Element.BackgroundColor.ToUIColor(),                
                UserInteractionEnabled = true,
            };

            // Create button title label
            _buttonTitleLabel = new UILabel
            {
                Text = Element.Title,
                TextColor = UIColor.White,
                TranslatesAutoresizingMaskIntoConstraints = false,
            };
            rootView.AddSubview(_buttonTitleLabel);
            _buttonTitleLabel.TopAnchor.ConstraintEqualTo(rootView.TopAnchor).Active = true;
            _buttonTitleLabel.LeftAnchor.ConstraintEqualTo(rootView.LeftAnchor).Active = true;

            // Create Click Count label
            _clickCountLabel = new UILabel
            {
                Text = $"Clicked {Element.ClickCount} times",
                TextColor = UIColor.White,
                TranslatesAutoresizingMaskIntoConstraints = false,
            };
            rootView.AddSubview(_clickCountLabel);
            _clickCountLabel.TopAnchor.ConstraintEqualTo(_buttonTitleLabel.BottomAnchor).Active = true;
            _clickCountLabel.LeftAnchor.ConstraintEqualTo(rootView.LeftAnchor).Active = true;
            _clickCountLabel.BottomAnchor.ConstraintEqualTo(rootView.BottomAnchor).Active = true;

            return rootView;
        }
}
</incrementingbutton></code></pre>
<p>At this point we can run the application and see our custom buttons on the screen.<br>
<img src="https://thisoldbrain.com/content/images/2018/04/InitialiOSCustomButtons.png" width="300" alt="Creating a custom button with ripple effect in Xamarin Forms"><br>
The completed code for this step is available at tag &quot;ios-initial-custom-control&quot;. Next we'll add the touch effect.</p>
<h2 id="2addingabackgroundthatchangescolorwhentapped">2. Adding a background that changes color when tapped</h2>
<p>Adding the background is where we differ the most from our Android steps. On iOS we're changing the background color of our buttons by subscribing to several of the UIButton touch events.</p>
<pre><code class="language-csharp">
protected override void OnElementChanged(ElementChangedEventArgs&lt;IncrementingButton&gt; e)
{
    base.OnElementChanged(e);

    var rootView = CreateLayout();

    AddTouchBehavior(rootView);

    // Tell Xamarin to user our layout for the control
    SetNativeControl(rootView);
}    

...

private void AddTouchBehavior(UIButton rootView)
{
    rootView.TouchDown += AddTouchBackgroundColor;
    rootView.TouchDragEnter += AddTouchBackgroundColor;
    rootView.TouchUpInside += RemoveTouchBackgroundColor;
    rootView.TouchCancel += RemoveTouchBackgroundColor;
    rootView.TouchDragExit += RemoveTouchBackgroundColor;
}

private void AddTouchBackgroundColor(object sender, EventArgs e)
{
    (sender as UIView).BackgroundColor = Element.BackgroundColor.ToUIColor().ColorWithAlpha(.5f);
}

private void RemoveTouchBackgroundColor(object sender, EventArgs e)
{
    (sender as UIView).BackgroundColor = Element.BackgroundColor.ToUIColor();
}
</code></pre>
<p>With this in place, we can run the app and watch the button background respond to our touches<br>
<img src="https://thisoldbrain.com/content/images/2018/04/iOSBackgroundEffect.gif" width="300" alt="Creating a custom button with ripple effect in Xamarin Forms"><br>
The completed code for this step is available at tag &quot;ios-background-effect&quot;. Next we'll respond to the click event and update the buttons' click counts.</p>
<h2 id="3respondingtoclickeventsandupdatingtheclickcount">3. Responding to click events and updating the click count</h2>
<p>Finally, just like on Android, we need to respond to the click event and update our button's text. On iOS we do this by creating a UITapGestureRecognizer that calls our button's click command.</p>
<pre><code class="language-csharp">
private void AddTouchBehavior(UIButton rootView)
{
    var tapGesture = new UITapGestureRecognizer(() => Element.Command?.Execute(null));
    rootView.AddGestureRecognizer(tapGesture);
...
</code></pre>
<pre><code class="language-csharp">
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
    base.OnElementPropertyChanged(sender, e);
    if (e.PropertyName == IncrementingButton.ClickCountProperty.PropertyName)
    {
        _clickCountView.Text = $"Clicked {Element.ClickCount} times";
    }
}            
</code></pre>
<p>Now we can run the app and see our click counts<br>
<img src="https://thisoldbrain.com/content/images/2018/04/iOSUpdateClickCount.gif" width="300" alt="Creating a custom button with ripple effect in Xamarin Forms"><br>
The completed code for this step is available at tag &quot;ios-update-click-count&quot;.</p>
<p>And there we have it! A fully customized button in Xamarin Forms that works on both iOS and Android. From here we can adjust the button's rendering and behavior as needed on both OSs.</p>
<p>Guest posted by Matt Hoffman (@hofmadresu, <a href="https://github.com/hofmadresu/">https://github.com/hofmadresu/</a>)</p>
</div>]]></content:encoded></item><item><title><![CDATA[.Net Standard multi-targeting explainer]]></title><description><![CDATA[<div class="kg-card-markdown"><p>Ok, technically multi-targeting is a feature of MSBuild, not .Net Standard. In fact you don't even <em>need</em> .Net Standard to be one of your targets, though it's a popular choice. Confused? Want to know more? I have the video for you!</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/zg45M-Mkr9o" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
<p>For more info check out the Merge Conflict podcast</p></div>]]></description><link>https://thisoldbrain.com/net-standard-multi-targeting-explainer/</link><guid isPermaLink="false">5aaa8953d3a035186016e0ee</guid><category><![CDATA[Video]]></category><category><![CDATA[Xamarin]]></category><dc:creator><![CDATA[Jason DeBoever]]></dc:creator><pubDate>Tue, 27 Feb 2018 14:55:00 GMT</pubDate><media:content url="https://thisoldbrain.com/content/images/2018/03/blogpic-5.PNG" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://thisoldbrain.com/content/images/2018/03/blogpic-5.PNG" alt=".Net Standard multi-targeting explainer"><p>Ok, technically multi-targeting is a feature of MSBuild, not .Net Standard. In fact you don't even <em>need</em> .Net Standard to be one of your targets, though it's a popular choice. Confused? Want to know more? I have the video for you!</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/zg45M-Mkr9o" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
<p>For more info check out the Merge Conflict podcast episode that inspired me<br>
<a href="http://www.mergeconflict.fm/85">http://www.mergeconflict.fm/85</a></p>
<p>as well as Oren Novotny's in depth blog post<br>
<a href="https://oren.codes/2017/01/04/multi-targeting-the-world-a-single-project-to-rule-them-all/">https://oren.codes/2017/01/04/multi-targeting-the-world-a-single-project-to-rule-them-all/</a></p>
</div>]]></content:encoded></item><item><title><![CDATA[Six Straight Hours at .NET Conf]]></title><description><![CDATA[<div class="kg-card-markdown"><p>Adrian and I presented for a six hour marathon session on .Net Conf! Covering Azure topics like IoT Hub and Functions and Xamarin Topics like responsive design and the upcoming features.</p>
<p>Check out all the sessions at my Channel 9 page (look for the <code>.Net Conf 2017</code> tag).<br>
<a href="https://channel9.msdn.com/Events/Speakers/jason-deboever">https://channel9.</a></p></div>]]></description><link>https://thisoldbrain.com/six-straight-hours-at-net-conf/</link><guid isPermaLink="false">5aaa7b6ed3a035186016e0db</guid><category><![CDATA[Xamarin]]></category><category><![CDATA[Azure]]></category><category><![CDATA[Video]]></category><dc:creator><![CDATA[Jason DeBoever]]></dc:creator><pubDate>Fri, 15 Sep 2017 14:30:00 GMT</pubDate><media:content url="https://thisoldbrain.com/content/images/2018/03/blogpic-1.PNG" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://thisoldbrain.com/content/images/2018/03/blogpic-1.PNG" alt="Six Straight Hours at .NET Conf"><p>Adrian and I presented for a six hour marathon session on .Net Conf! Covering Azure topics like IoT Hub and Functions and Xamarin Topics like responsive design and the upcoming features.</p>
<p>Check out all the sessions at my Channel 9 page (look for the <code>.Net Conf 2017</code> tag).<br>
<a href="https://channel9.msdn.com/Events/Speakers/jason-deboever">https://channel9.msdn.com/Events/Speakers/jason-deboever</a><br>
<a href="https://channel9.msdn.com/Events/Speakers/jason-deboever"><img src="https://thisoldbrain.com/content/images/2018/03/XamarinWithAzureIoTHub_220.jpg" alt="Six Straight Hours at .NET Conf"></a></p>
</div>]]></content:encoded></item><item><title><![CDATA[Intro to Machine Learning]]></title><description><![CDATA[<div class="kg-card-markdown"><p>Even if you know nothing whatsoever about Machine Learning, my new video will take you from first principles to a working example on Azure Machine Learning Studio -- all in about 75 minutes!</p>
<p><a href="https://channel9.msdn.com/Events/Xamarin/Xamarin-University-Presents-Webinar-Series/Developers-Intro-to-Azure-Machine-Learning">https://channel9.msdn.com/Events/Xamarin/Xamarin-University-Presents-Webinar-Series/Developers-Intro-to-Azure-Machine-Learning</a></p>
</div>]]></description><link>https://thisoldbrain.com/intro-to-machine-learning/</link><guid isPermaLink="false">5aaa85dcd3a035186016e0e5</guid><category><![CDATA[Azure]]></category><category><![CDATA[MachineLearning]]></category><dc:creator><![CDATA[Jason DeBoever]]></dc:creator><pubDate>Fri, 30 Jun 2017 14:37:00 GMT</pubDate><media:content url="https://thisoldbrain.com/content/images/2018/03/blogpic-3.PNG" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://thisoldbrain.com/content/images/2018/03/blogpic-3.PNG" alt="Intro to Machine Learning"><p>Even if you know nothing whatsoever about Machine Learning, my new video will take you from first principles to a working example on Azure Machine Learning Studio -- all in about 75 minutes!</p>
<p><a href="https://channel9.msdn.com/Events/Xamarin/Xamarin-University-Presents-Webinar-Series/Developers-Intro-to-Azure-Machine-Learning">https://channel9.msdn.com/Events/Xamarin/Xamarin-University-Presents-Webinar-Series/Developers-Intro-to-Azure-Machine-Learning</a></p>
</div>]]></content:encoded></item><item><title><![CDATA[End to End Mobile and Server OAuth]]></title><description><![CDATA[<div class="kg-card-markdown"><p>You have a mobile app, a web server, an authentication server, and an api server. You want them all talking together securely and leveraging user accounts over OAuth.</p>
<p>In this video set I'll walk you through the basics of creating all those parts and setting them up to work together.</p></div>]]></description><link>https://thisoldbrain.com/end-to-end-mobile-and-server-oauth/</link><guid isPermaLink="false">5aaa8e60d3a035186016e0f2</guid><category><![CDATA[Xamarin]]></category><category><![CDATA[Video]]></category><category><![CDATA[OAuth]]></category><dc:creator><![CDATA[Jason DeBoever]]></dc:creator><pubDate>Wed, 15 Mar 2017 15:13:00 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p>You have a mobile app, a web server, an authentication server, and an api server. You want them all talking together securely and leveraging user accounts over OAuth.</p>
<p>In this video set I'll walk you through the basics of creating all those parts and setting them up to work together.</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/ZNm8j-Lqjts?rel=0" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
<iframe width="560" height="315" src="https://www.youtube.com/embed/wFC7mTMAuiU?rel=0" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe></div>]]></content:encoded></item><item><title><![CDATA[Azure Mobile App Services Video]]></title><description><![CDATA[<div class="kg-card-markdown"><p>I joined several others from Xamarin University in creating a series of videos that takes from File-&gt;New, all the way to having a working mobile app including an azure back-end and automated UI testing!</p>
<p>My part was the Azure back-end!  Check out the links below.</p>
<ol>
<li>First video in</li></ol></div>]]></description><link>https://thisoldbrain.com/azure-mobile-app-services-video/</link><guid isPermaLink="false">5aaa874dd3a035186016e0ea</guid><category><![CDATA[Azure]]></category><category><![CDATA[Video]]></category><dc:creator><![CDATA[Jason DeBoever]]></dc:creator><pubDate>Wed, 30 Nov 2016 14:43:00 GMT</pubDate><media:content url="https://thisoldbrain.com/content/images/2018/03/blogpic-4.PNG" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://thisoldbrain.com/content/images/2018/03/blogpic-4.PNG" alt="Azure Mobile App Services Video"><p>I joined several others from Xamarin University in creating a series of videos that takes from File-&gt;New, all the way to having a working mobile app including an azure back-end and automated UI testing!</p>
<p>My part was the Azure back-end!  Check out the links below.</p>
<ol>
<li>First video in the series<br>
<a href="https://channel9.msdn.com/Events/Connect/2016/Xamarin101-1">https://channel9.msdn.com/Events/Connect/2016/Xamarin101-1</a></li>
<li>My Mobile App Service video<br>
<a href="https://channel9.msdn.com/Events/Connect/2016/Xamarin101-4">https://channel9.msdn.com/Events/Connect/2016/Xamarin101-4</a></li>
</ol>
</div>]]></content:encoded></item></channel></rss>