Xamarin Forms - Load image in a Button - c#

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.

Are no images being displayed at all? Check your locations of the images. Default location in ios is Resources folder, in android it is resources/drawable and in wp it is the root. If you want one image rather than 3 for each solution, put in to the PCL and set the build property to embedded resource and qualify the name with the namespace it is in. ie... ProjectName.Assets.image.png if it is in the PCL Assets directory. Not sure if this is your problem or not, but figured I would offer it up , just in case.

You can solve this by making an Image tap-able using TapGestureRecognizer. For implementation, go through this: http://www.c-sharpcorner.com/UploadFile/e04e9a/xamarin-forms-image-button-recipe/

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.

Related

Localization with C# Windows Forms, cannot access my .resx File

Hi I created this WinForm Program. It has several Forms.
I looked for a tutorial or someting to help and found this on StackoverFlow.
How to use Localization in C#
It was really helpful but..
I created a ResourceString.de-DE.resx File and added it to the Properties Folder.
Added some Strings so i can test it. And changed the Access Modifier to Public.
Then i wanted to access the Properties Folder to Use the ResourceString.de-De.resx File.
But it doesn't get suggested.
The Code has to look like this in the end :
private void setLanguage()
{
btnSwitchLanguage.Text = Properties.ResourceString.de-DE.btnSwitchLanguage;
}
Am I missing something ?
Any Help is appreciated. :)
Thanks
You don't need to add the Strings.resx file, Your project already has the resource file Resources.resx. Therefore, you should add a new resource file with Resources.de.resx name, if required localization for the "de-DE". So, you can put into this resource file not only strings, but images, icons etc.
There is no need to change the Access Modifier to Public unless you are not going to access this resources from another assembly.
NOTE: When you are working in the Visual Studio the Visual Assist
suggestion will be the same for all languages, starting from
Properties.Resources.
You need to create a default 'ResourceString.resx' file along with al your language specific resx files. Make sure to add the same resources in all resx files. (btnSwitchLanguage, ...).
Well i found my mistake, after reading the Thread again, that i linked in my Post.
There should be a File called Strings.resx (or whatever Name you Choose), which contains the original strings.
And the File which contains another language. (German in my Example).
Should have the same name, except the language comes at the end.
Like this :
Strings.de-DE.resx
After that i just had to change my Code to :
private void btnSwitchLanguage_Click(object sender, EventArgs e)
{
if (Thread.CurrentThread.CurrentUICulture.ToString().Equals("de-DE"))
{
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("en-GB");
}
else
{
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("de-DE");
setLanguage();
}
}
private void setLanguage()
{
btnSwitchLanguage.Text = Properties.Strings.btnSwitchLanguage;
}

NoesisGUI - Loading PNG in Noesis.Image Element

I am having troubles assigning a png image to Image element in XAML. At runtime the application crashes with exception:
InvalidCastException: Unable to cast object of type 'System.Drawing.Bitmap' to type 'System.Byte[]'.
My steps are as follows:
App.xaml.cs
protected override TextureProvider GetTextureProvider()
{
EmbeddedTexture[] textures =
{
new EmbeddedTexture {filename="icon.png", resource="icon"},
new EmbeddedTexture {filename="download.jpg", resource="download"}
};
return new EmbeddedTextureProvider(textures, Properties.Resources.ResourceManager);
}
MainWindow.xaml
<Image Source="icon.png"/>
I added icon.png in project dir with build action "Resource" and added the same in Resources.resx file.
I ran the Menu3D sample from Github which loaded png images without any trouble. Can someone please point out what I might be doing wrong? I'd appreciate the help.
Thanks.
I posted this question on their forums and got the workaround here:
http://www.noesisengine.com/forums/viewtopic.php?f=3&t=1404
The workaround was to edit Resources.resx file and replace "System.Drawing.Bitmap, System.Drawing" with "System.Byte[], mscorlib" for every image file. Also change the getters in Resources.Designer.cs and replace "Bitmap" type with "Byte[]" type.

C# WPF Localization - Ignoring other cultures and loading default Resources

I'm trying to localize my app, I've created several Resources.[culture].resx but program ignores them all and always loads default Resources.resx.
I have this code in App construtor (and in OnStartup event)
System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("en-US");
My resources are called Resources.en-US.resx, Resources.cs-CZ.resx and Resources.resx
Code in WPF is
xmlns:p="clr-namespace:WpfThermalLabelEditorApp.Properties"
Title="{x:Static p:Resources.Title}"
This should load en-US localization but it doesn't. Loads default. I tried to delete AssemblyInfo and even putting <UICulture> tags into csproj
Not sure if this is the answer, but FWIW: I always set both CurrentCulture and CurrentUICulture like so;
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(languageAbbreviation);
Thread.CurrentThread.CurrentUICulture = new CultureInfo(languageAbbreviation);
And be sure to double check the abbreviation you use is the same for all references. That should fix your problem.
EDIT1: Make sure your resource files are set to public, the access modifier should be somewhere near the top when you're viewing the resource file. Double check this says public and rebuild. Also, to call your resource file key do so like this:
<TextBlock xmlns:local="clr-namespace:WpfApplication2" Text="{x:Static local:Resource1.myname}"/>
Where...
"WpfApplication2" is replaced with your project name
"Resource1" is replace with the name of your resource file (without culture id, e.g. for your case it would just be Resources)
"myname" is replaced with the key you want
I came across the same problem, the solution was to clean and rebuild the project. No need to create new project.
Well, after 2 days I've solved my problem. My solution was correct. I have no idea what was wrong but I've created a new project, moved all my data to a new one and suddenly everything worked as a charm.
Here is a few usefull links:
WPF localization and globalization
Localization tutorial
Localization tutorial 2

Customizing an icon breaks DataGridView?

I have a DataGridView that displays a list of MMS Messages. To differentiate between sent and received, I put a right arrow and left arrow in a column. Our customer loved it, but wants the right arrow to be green for even more clarity, especially in international environments.
I took the right arrow and opened it in Visual Studio 2003 (I am using VS2010 for writing the application). I recolored the icon and it looked great, however when I went to display the containing Control, I get the following error:
The following exception occurred in the DataGridView:
System.ArgumentException: Parameter is not valid.
at System.Drawing.Image.FromStream(Stream stream, Boolean useEmbeddedColorManagement, Boolean validateImageData)
at System.Drawing.ImageConverter.convertFrom(ITypeDescriptorContext context, CultureInfo culture, Object value)
at System.Windows.Forms.Formatter.FormatObjectInternal(Object value, Type targetType, TypeConverter sourceConverter, TypeConverter targetConverter, String formatString, IFormatProvider formatInfo, Object formattedNullValue, Object dataSourceNullValue)
at System.Windows.Forms.DataGridViewCell.GetFormattedValue(Object value, Int32 rowIndex, DataGridViewCellStyle& cellStyle, TypeConverter valueTypeConverter, TypeConverter formattedValueTypeConverter, DataGridViewDataErrorContexts context)
To replace this default dialog please handle the DataError event.
When I create the DataTable to be populated with the data, I use this on the column that will have the icon
dt.Columns.Add(sDirection);
dt.Columns[sDirection].DataType = typeof(Byte[]);
When I add the data to the rows, I have a method to convert the Icon.
internal static Byte[] ConvertIconToByteArray(Icon pIcon) {
MemoryStream ms = new MemoryStream();
pIcon.Save(ms);
return (ms.GetBuffer());
}
And I add the DataTable to the DataGridView with
grdMMSList.DataSource = dt.DefaultView;
(Method calls removed from the above code for clarity)
I followed through in the debugger, and setting the DefaultView as the DataSource is where the error is getting thrown. I tried placing it in a try/catch block so I could see the Exception, but it doesn't trigger the catch.
Just a few other bits of information:
- The icon is stored as a Resource and is called by Properties.Resources.RightArrow
- After changing the colors, I just Save the file in VS2003, nothing with a Save As. The file still shows up as an Icon everywhere.
- Back in VS2010, the Resource File does have the new color scheme and renders properly there.
Thank you in advance for any help you can provide.
I would not edit the images this way. If you want a valid set of arrows that are all supported for addition into a DataGridView, so to the directory
C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\VS2010ImageLibrary\1033
here you will find a .zip file. Unzip it.
Then you will find varios subdirectories with loads of MS icon and images etc. Navigate to
C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\VS2010ImageLibrary\1033
\VS2010ImageLibrary\VS2010ImageLibrary\Objects\png_format\WinVista
here you will find all different kinds of arrows in all different colours. My advice is use these, not your bitmap edits to existing files.
I hope this helps.

XAML designed fails to load as cannot create a custom object

I have a XAML form for use in my application, and I have subclassed the Frame class to create my own, and edited the interface to specify my own class for the content (as I need to access properties on the content for data binding).
The problem comes then in the designer that the compiler says it cannot create an instance of my control - I've tried to do some designer checks on the offending property bit but that didnt work either.
How can I get the control to display? Works fine at runtime...
XAML:
<Grid Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2">
<views:PageFrame Name="Content_MainPage" Frame.NavigationUIVisibility="Hidden"/>
</Grid>
CS:
public new BaseView Content
{
get
{
if (DesignerProperties.GetIsInDesignMode(this))
{
return new BaseView();
}
else
{
return (BaseView)base.Content;
}
}
set
{
if (DesignerProperties.GetIsInDesignMode(this))
{
base.Content = new BaseView();
FrameTitle = "design mode";
}
else
{
base.Content = value;
FrameTitle = value.Title;
}
}
}
I came across a similar problem when creating my own Panel class.
Is your PageFrame class defined in the same assembly that your XAML lives in?
I found the only way I could get this to work was to move my "PageFrame" class into a new assembly. From memory I think I even had to build that assembly ahead of time, so that the assembly could be referenced via a file reference (as opposed to a project reference).
I hated this solution, so I hope you find a cleaner one :)
Have you got VS2008 SP1 installed? I had hoped MS would fix this bug. I haven't tried removing my workaround to check...
Its in the same assembly - and yes I have VS2008 SP1 installed too. Not that removing the above property lets it work fine from a vs point of view, but obviously not from my point of view!
I will give this a go - thanks Antony.

Categories