1 million views of my Xamarin / ASP.NET / Core StackOverflow posts

This year I had 1 million views (total ~7m) of my StackOverflow posts on topics related to Xamarin and ASP.NET / Core. I reached the top 0.3% worldwide in terms of reputation.

https://stackoverflow.com/users/172861/ian-vink 

Screen Shot 2020-02-25 at 5.17.31 PM.png

#Xamarin: It’s actually about the money

ca44147d22ccf7fe745b9a59e0054e7c.gifAs developers, we naturally focus on the tech side of tech. Xamarin is a great toolset that allows you to create native, fast apps with a single codebase using the .Net you already know and love.

However, I think the key benefit, the one that gets overlooked in reviews and overviews of the software, is that Xamarin saves your company money. People are expensive so not having to hire an iOS and Android team, and not having to retrain the developers in a language they may not know saves a significant amount of money.

At Maximizer, a long-standing CRM company,  we focus on building great tools, but tools that are affordable as well. The app team which I lead has only 1 group of developers focusing on building a great CRM app. We have one set of Program Managers supporting the single team. There is one build process and one deployment process. No effort is needed to keep the Android and iOS teams in sync as there is only one codebase.

So, glory in the technical wonders of Xamarin, but smile at the money you are saving your company and customers.

I wrote this post after I was surprised as the level of interest in Xamarin and money-saving of one of my recent Twitter posts.

Screenshot 2020-01-21 at 8.27.31 AM.png

 

 

 

#Xamarin Animated #GIFs

In the latest version of Xamarin , version 4.4, Images can now show animated GIFs.

Normally my posts are a bit longer to explain how to implement a new Xamarin feature, but this one is so simple, yet powerful, that only a small post is needed.

Sweet.

The Image tag now has an attribute called IsAnimationPlaying. Set that to true and the source to an animated GIF, either local or remote.

That’s it. Your app can now show Borat.

<Image Source="borat.gif" IsAnimationPlaying="true"></Image>

animation.gif

Xamarin: Using Telerik TabView with Data Trigger Colors

Xamarin TelerikThe Telerik TabView for Xamarin is a great tool to hold and alter the content of several pages. One of the downsides is that the styles offered are a bit limited. I wanted to change the Text color fo the Tab Header Text to be white or off-white depending on the selected state.

No problem as Xamarin as Data Triggers that can change the property of an item depending on the value of data.

Step 1: Add a custom TabViewItem header

<telerikPrimitives:TabViewItem.Header>
	<telerikPrimitives:TabViewHeaderItem>
	   <telerikPrimitives:TabViewHeaderItem.Content>
                <Label Text="SAVED SEARCHES" />
           </telerikPrimitives:TabViewHeaderItem.Content>
	 </telerikPrimitives:TabViewHeaderItem>
</telerikPrimitives:TabViewItem.Header>

In the above, we now have a label for the header. the next step is to add Data Triggers to that Label so that when IsSelected is changed, the Data Trigger will change the Label’s color

Step 2: Attach a Data Trigger to the Label

<Label Text="SAVED SEARCHES">
  <Label.Triggers>
     <DataTrigger TargetType="Label" Binding="{TemplateBinding IsSelected}" Value="True">
	 <Setter Property="TextColor" Value="White"></Setter>
     </DataTrigger>
     <DataTrigger TargetType="Label" Binding="{TemplateBinding IsSelected}" Value="False">
         <Setter Property="TextColor" Value="#aaffffff"></Setter>
     </DataTrigger>
</Label.Triggers>

A Data Trigger is like a sentence. you can read it like this:

WHEN the IsSelected IS true THEN change the TEXTCOLOR to white.

WHEN the IsSelected IS faflseTHEN change the TEXTCOLOR to off-white.

Here’s the result with several tabs:

2019-10-18 11_31_18-iPhone 11 iOS 13.1.png

#Xamarin Forms Currency Entry Field

images.jpgI needed a simple Entry field in Xamarin Forms which would work as a currency field. It should show 0.00 when empty, but then clear out automatically once the user tapped it. I ended up using a simple behavior to accomplish it in a very simply way.

currency.gif

Here’s how:

Create a file called CurrencyBehavior.cs in your shared project:

public class CurrencyBehavior : Behavior<Entry>
    {
	    private bool _hasFormattedOnce = false;
	    protected override void OnAttachedTo(Entry entry)
	    {
		    entry.TextChanged += OnEntryTextChanged;
			entry.Focused += EntryOnFocused;
			entry.Unfocused += EntryOnUnfocused;
		    base.OnAttachedTo(entry);
	    }
 
	    private void EntryOnUnfocused(object senderFocusEventArgs e)
	    {
		    var entry = sender as Entry;
		    if (entry?.Text.HasValues()==false)
		    {
			    entry.Text = "0.00";
		    } 
	    }
 
	    private void EntryOnFocused(object senderFocusEventArgs e)
	    {
		    var entry =  sender as Entry;
		    if (entry?.Text == "0.00")
		    {
			    entry.Text = "";
		    }
	    }
 
	    protected override void OnDetachingFrom(Entry entry)
	    {
		    entry.TextChanged -= OnEntryTextChanged;
		    entry.Focused -= EntryOnFocused;
		    entry.Unfocused -= EntryOnUnfocused;
		    base.OnDetachingFrom(entry);
	    }
 
	    private   void OnEntryTextChanged(object senderTextChangedEventArgs args)
	    {
		    if (!_hasFormattedOnce && args.NewTextValue == "0")
		    {
			    ((Entrysender).Text = "0.00";
			    _hasFormattedOnce = true;
		    }
	    }
 
 
    }

Now, on your Entry control, add the behavior:

	            <Entry 
	                   Text="{Binding MyMoneyPropertyInMyViewModel}"
	                   Keyboard="Numeric">
		            <Entry.Behaviors>
			            <behaviors:CurrencyBehavior />
		            </Entry.Behaviors>
	            </Entry>

 

#Xamarin Forms Shell – How to make it work on iOS 9

images.jpg Xamarin Forms Shell is a great way to reduce your code complexity. It handles a lot of plumbing for you. Highly recommended; I use it in my 50,000 user app.

However, it doesn’t work on iOS 9 as of version 4.1. This article will show you how to get it to work on iOS 9

Credits: Based on discussions from a GitHub forum, code is taken from there so all create to the forum contributors listed there. Thanks! https://github.com/JRPMike

What’s the problem:

Tabs. iOS 9 doesn’t allow certain colorings of tabs (UnselectedItemTintColor), so we need to ensure that we don’t ask for a color to be applied when we are in iOS 9

We are going to add a ShellRenderer so that in iOS we can call the Tab colorings only when we are in iOS 10 and above.

Add a file called MyShellRenderer.cs to your iOS project only.

Then add this:

[assemblyExportRenderer(typeof(Shell), typeof(App.iOS.Renderers.MyShellRenderer))]
namespace App.iOS.Renderers
{

    public class MyShellRenderer : ShellRenderer
    {
 
        protected override void OnElementSet(Shell element)
        {
            base.OnElementSet(element);
        }
 
        protected override IShellTabBarAppearanceTracker CreateTabBarAppearanceTracker()
        {
	        return new MySafeShellTabBarAppearanceTracker();
        }
    
 
        
    }
 
	public class MySafeShellTabBarAppearanceTracker : IShellTabBarAppearanceTracker
	{
		UIColor _defaultBarTint;
		UIColor _defaultTint;
		UIColor _defaultUnselectedTint;
 
		public void ResetAppearance(UITabBarController controller)
		{
			if (_defaultTint == null)
				return;
 
			var tabBar = controller.TabBar;
			tabBar.BarTintColor = _defaultBarTint;
			tabBar.TintColor = _defaultTint;
			tabBar.UnselectedItemTintColor = _defaultUnselectedTint;
		}
 
		public void SetAppearance(UITabBarController controllerShellAppearance appearance)
		{
			IShellAppearanceElement appearanceElement = appearance;
			var backgroundColor = appearanceElement.EffectiveTabBarBackgroundColor;
			var foregroundColor = appearanceElement.EffectiveTabBarForegroundColor// currently unused
			var disabledColor = appearanceElement.EffectiveTabBarDisabledColor// unused on iOS
			var unselectedColor = appearanceElement.EffectiveTabBarUnselectedColor;
			var titleColor = appearanceElement.EffectiveTabBarTitleColor;
 
			var tabBar = controller.TabBar;
			bool operatingSystemHasUnselectedTint = UIDevice.CurrentDevice.CheckSystemVersion(10, 0);
			if (_defaultTint == null)
			{
				_defaultBarTint = tabBar.BarTintColor;
				_defaultTint = tabBar.TintColor;
				if (operatingSystemHasUnselectedTint)
				{
					_defaultUnselectedTint = tabBar.UnselectedItemTintColor;
				}
			}
 
			if (!backgroundColor.IsDefault)	tabBar.BarTintColor = backgroundColor.ToUIColor();
			if (!titleColor.IsDefault)	tabBar.TintColor = titleColor.ToUIColor();
			if (operatingSystemHasUnselectedTint)
			{
				if (!unselectedColor.IsDefault)
					tabBar.UnselectedItemTintColor = unselectedColor.ToUIColor();
			}
		}
 
		public void UpdateLayout(UITabBarController controller)
		{
		}
 
		#region IDisposable Support
 
		protected virtual void Dispose(bool disposing)
		{
		}
 
		public void Dispose()
		{
			Dispose(true);
		}
 
		#endregion
	}
}