I looked extensively online but I couldn't find anything really specific to help me out in this trouble I am having.
I am trying to make a custom renderer for a Button component, in Xamarin forms. Why am I not using the XLabs ImageButton component? Because it's not compatible with Android 4.0.3, which is my current Android target version.
I also tried writing on my own some code that is that much worthless that I am quite shy to post, unless you really require me to :)
I am in need of this code because, without it, images just fail to load in buttons while trying to use them in any button like this:
<Button Image="someImage.png"/>
I tried following a tutorial, here:
http://blog.falafel.com/learning-xamarin-custom-renderers-in-xamarin-forms/
But I failed adapting it to my needs.
The proper way to do this is described in Chapter 13 of Charles Petzold's excellent book on Xamarin Forms: https://developer.xamarin.com/guides/xamarin-forms/creating-mobile-apps-xamarin-forms/
My approach to this problem is (different than the book) to use a converter for the image file path. The Button.Image property is a FileImageSource object and it wants a file path. Unfortunately you cannot use embedded resources or a content file in the PCL. You must add an individual image file in each of the iOS, Android and UWP projects. The way I do this is to add the image to the PCL and use linking (option on the add existing file dialog).
So here is my converter approach to the above issue
<Button Image="{Binding Converter={StaticResource FileImageSourceConverter}, ConverterParameter=someImage.png}" />
The static resource...
<ContentPage.Resources>
<ResourceDictionary>
<local:FileImageSourceConverter x:Key="FileImageSourceConverter"/>
</ResourceDictionary>
</ContentPage.Resources>
The converter...
public class FileImageSourceConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
string filename = parameter as string;
switch(Device.RuntimePlatform)
{
case Device.iOS:
case Device.Android:
default:
return filename;
case Device.Windows:
return Path.Combine("Images", filename);
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
The advantages of this approach is that (1) your XAML is not cluttered up with OnPlatform elements; (2) you don't need to put your images in the root directory of the UWP project; (3) much simpler than using a custom render to solve the same problem as some have suggested.