I am trying to follow the Xamarin documentation about Embedded Images:
https://developer.xamarin.com/guides/xamarin-forms/working-with/images/#Embedded_Images
This is the code snippet that I use in my portable application:
var embeddedImage = new Image { Aspect = Aspect.AspectFit };
embeddedImage.Source = ImageSource.FromResource("<MyNamespace>.<MyFolder>.imageFileName.jpg");
listItem.EmbeddedImage = embeddedImage;
Now I am trying to bind it in XAML, as part of a ListView (note: the <Image Source="{Binding EmbeddedImage}" /> part is probably wrong) :
<ListView x:Name="listView">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout BackgroundColor="#eee"
Orientation="Vertical">
<StackLayout Orientation="Horizontal">
<Image Source="{Binding EmbeddedImage}" /> // This is most likely wrong since it doesn't work
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I've tested this with <Image Source="{Binding ImageUrl}" /> and it works, so the rest of the code seems to be working as it should.
Edit:
Someone suggested this post as a solution:
How to load an image to a ImageCell on Xamarin.Forms?
But the accepted answer there was:
The images go into your "native" projects
...but actually the Xamarin documentation says that it can be done inside the portable project (so you wouldn't need to copy the same images/icons through all the "native" projects).
I know that putting them in every subproject would probably work, but that's not the point of my question.
You can access the resource directly in xaml by using pack://application uri.
<ListView x:Name="listView">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout BackgroundColor="#eee"
Orientation="Vertical">
<StackLayout Orientation="Horizontal">
<Image Source="pack://application:,,,/{AssemblyName};component/Images/MyImage.png" />
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I've combed my hair out over this, and the problem is that Microsoft doesn't tell you the whole story in the Images docs. You have to go over to the Files docs to understand why it won't work.
Yes, you can use embedded resources in the shared project directory, but apparently under only one of two conditions:
You have to use a Markup Extension and then directly specify the resource path in Xaml, a la: <Image Source="{local:ImageResource ProjectName.Images.flower.jpg"/>
You write compiler directives in the code-behind that customize the beginning of the ResourceID per-platform.
Option 1 requires hard-coding the path, so you can't use a dynamically-assigned image, and Option 2 wrecks the whole point of trying to write cross-platform code.
WAY HUGE EDIT: May be solved
This post on the Xamarin forums made a huge difference for me: https://forums.xamarin.com/discussion/17953/helpful-shared-project-image-information
note: the first post basically gives you all the code you need, but a little bit down in the thread there's some advice about project configurations that may be necessary for it to work correctly.
It basically introduces some custom code that programmatically derives the resource ID during runtime, so it's cross-platform code that customizes itself to whatever platform is currently running it. Working beautifully for me! Here's the version of the suggested approach that I'm using:
using System.Linq;
using System.Reflection;
using System.Diagnostics;
using System;
namespace Helpers
{
public class EmbeddedSourceror
{
public static Xamarin.Forms.ImageSource SourceFor(string pclFilePathInResourceFormat)
{
var resources = typeof(EmbeddedSourceror).GetTypeInfo().Assembly.GetManifestResourceNames();
var resourceName = resources.Single(r => r.EndsWith(pclFilePathInResourceFormat, StringComparison.OrdinalIgnoreCase));
Debug.WriteLine("EmbeddedSourceror: resourceName string is " + resourceName);
return Xamarin.Forms.ImageSource.FromResource(resourceName);
}
}
}
This lets you write the Xaml code in a totally normal way, such as:
<Image
x:Name ="backingImage"
Aspect ="AspectFill" />
And in the code-behind all you have to do is:
backingImage.Source = EmbeddedSourceror.SourceFor("flower.jpg");
Related
I am looking for a solution that lets the user pick the folder location where they want to save their file(s). I am aware of FilePicker in the Xamarin.Essentials package, but this only allows the user to pick individual files, not folders. I am trying to accomplish this for all 4 platforms (Windows, iOS, Mac, and UWP). Any help is greatly appreciated.
You can only achieve with Xamarin what is natively possible. If you try to code using native iOS in Objective-C/Swift/SwiftUI, there's no way to select which folder in the photo gallery to save your pictures in.
Therefore it's not technically possible to achieve a solution that you are looking for in all 4 platforms.
For now, no FodlerPicker in Xamarin.Forms.
You could create your own custom folder picker like below. Use the TapGestureRecognizer to simulate the selecting operation to save to the specific location.
<ListView ItemsSource="{Binding folders}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Label Text="{Binding folder}">
<Label.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped"></TapGestureRecognizer>
</Label.GestureRecognizers>
</Label>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
You could post your requirement in GitHub. https://github.com/xamarin/Xamarin.Forms/issues
I'm facing some tricky bugs while trying to use the new CollectionView
feature implemented in Xamarin Forms 4. On the Android project it works very
well after enabling experimental features in MainActivity.cs with:
global::Xamarin.Forms.Forms.SetFlags(new[] { "CollectionView_Experimental", "Shell_Experimental" });
But xamarin documentation doesn't provide any information about UWP project
so first when I tried to compile the UWP project, it throws me this exception
when it tries to render a page that uses CollectionView
System.InvalidOperationException:
'The class, property, or method you are attempting to use ('VerifyCollectionViewFlagEnabled')
is part of CollectionView; to use it, you must opt-in by calling Forms.SetFlags("CollectionView_Experimental")
before calling Forms.Init().'
So I tried to call the SetFlags in App.xaml.cs in UWP project before calling
InitializeComponent() method. So this time it throws me this exception when
it tries to load the page containing CollectionView:
System.NullReferenceException: 'Object reference not set to an instance of an object.'
So like in this example:
await Navigation.PushAsync(new PageWithCollectionView());
The exception is thrown after successful execution of PageWithCollectionView constructor.
Can somebody help me to solve this problem?
UPDATE
Ok, so adding the SetFlags in App.xaml.cs in UWP project works and
the CollectionView gets initialized correctly. But the NRE is still there
(on Android the CollectionView works without problems), while trying to get
rid of this problem I noticed that it's caused when I try to nest the XAML layout this way:
<CollectionView SelectionMode="Single">
<CollectionView.ItemsLayout>
<GridItemsLayout Orientation="Horizontal"
Span="2"/>
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<StackLayout Orientation="Vertical"
Grid.Column="0"
Grid.Row="0">
<Label Text="{Binding Title}"/>
</StackLayout>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
If I remove all the DataTemplate from CollectionView.ItemTemplate, just
leaving it blank like this:
<CollectionView SelectionMode="Single">
<CollectionView.ItemsLayout>
<GridItemsLayout Orientation="Horizontal"
Span="2"/>
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
The page gets rendered a CollectionView shows ItemSource elements with messy
layout (without margin and padding, and calling ToString() method of element
to visualize it inside the cell).
[UPDATE]
After update to Xamarin Forms 4 pre 8, the exception is gone.
I created a code sample that contains CollectionView. According to the document, we need call SetFlag before Xamarin.Forms.Forms.Init(e) in the App.xaml.cs file like the following.
........
Xamarin.Forms.Forms.SetFlags("CollectionView_Experimental");
Xamarin.Forms.Forms.Init(e);
........
Implement CollectionView
<CollectionView>
<CollectionView.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>Baboon</x:String>
<x:String>Capuchin Monkey</x:String>
<x:String>Blue Monkey</x:String>
<x:String>Squirrel Monkey</x:String>
<x:String>Golden Lion Tamarin</x:String>
<x:String>Howler Monkey</x:String>
<x:String>Japanese Macaque</x:String>
</x:Array>
</CollectionView.ItemsSource>
</CollectionView>
And it works well, For NullReferenceException issue, you need check if there is null object in the code behind. Simple implementation of CollectionView does not cause such error.
Update
Please try to update Xamarin Forms 4 to latest pre version.
global::Xamarin.Forms.Forms.SetFlags(“CollectionView_Experimental”);
use MainActivity.cs in Android
I'm planning to design an multiple file downloader app (similar to IDM or Transmission) for macOS based on Aria2 JSON-RPC and C# GUI via Xamarin.Mac. But there is a major issue for UI design. I need a UI control which is similar to "ListView" in XAML.
Basically it's something like in this topic discussed, i.e. I need something equivalent in Xamarin.Mac with this XAML code below:
<ListView x:Name="DownloadItemList">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding DownloadItemTitle}"
Margin="20,0,20,8"
FontSize="24"
FontStyle="Italic"
FontWeight="SemiBold"
Foreground="DarkBlue" />
<TextBlock Text="{Binding DownloadProgressInfo}"
Margin="20,0,20,8"
FontSize="16"
Foreground="DarkGray"
Opacity="0.8" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I also need some data bindings in the UI code if possible. But so far I can't find any similar stuff in Xamarin.Mac. Is there any possible solution like this? Thanks in advance!
You can use NSTableView
static Content :
You can design cells from storyboard, and if required can modify content of these cells at runtime.
Dynamic Content : You can crate template cell at design time (or progrmmatically id requried ), give it identifier and use that cell multiple-time in tableviewd atasource.
You can use something like a table view
Hope this helps.
Link
I am trying to display data using carousel view in my forms application. I am not sure what am I missing but data is not getting populated, I have followed almost all available samples but still I have not found any success. Please help me get out of this problem:
I am using the following code in my xaml file:
<forms:CarouselView x:Name="listview" ItemsSource="postIdList" HeightRequest="200" Margin="5">
<forms:CarouselView.ItemTemplate>
<DataTemplate>
<ContentPage >
<StackLayout >
<Label Text="{Binding .}" FontSize="20" TextColor="Black" HorizontalOptions="Center" />
</StackLayout>
</ContentPage>
</DataTemplate>
</forms:CarouselView.ItemTemplate>
</forms:CarouselView>
And I am trying to populate the data in the following manner in .cs file:
List<string> postIdList = new List<string>
{
"Carousel", "Carousel", "carousel"
};
listview.ItemsSource = postIdList;
If I give a background colour for carousal view I am able to see that colour, but text is not getting displayed.
Please let me know my mistake.
In case of a ListView, you need an ObservableCollection instead of a List. Switch it around and see if it works?
On your XAML you are defining a <ContentPage> inside the <Datatemplate>. Replace the <ContentPage> with a <ViewCell> or a <Grid>
Here is a great example on how to use it, you need to keep in mind that CarouselView work like a ListView, it need to have a Datatemplate.
I have a class library that is essentially a collection of forms to be run. Consider it a module/plugin in a larger program, that can be developed independently, all the larger program cares about is the DLL (and interface).
Running the main form of the class library is fine and works well. My issue is with pictures. I've set up an Images folder in the class library, added an image, set it's Build Action to Embedded Resource and then rebuilt the project, but the images won't appear in the main program.
XAML:
<Button x:Name="btnAdd" Command="{Binding Add}">
<StackPanel Orientation="Horizontal">
<Image x:Name="imgAdd" Source="Resources/Add.png"/>
<Label>New</Label>
</StackPanel>
</Button>
The interesting part though, is that if I create a BitmapSource in code-behind and assign it to imgAdd in the constructor of the form, it works as expected. Does anyone have any ideas as to why this might be the case?
Use Pack URIs for your images.
<Button x:Name="btnAdd" Command="{Binding Add}">
<StackPanel Orientation="Horizontal">
<Image x:Name="imgAdd" Source="pack://application:,,,/ReferencedAssembly;component/Resources/Add.png"/>
<Label>New</Label>
</StackPanel>
</Button>
It turns out that the correct Build Action is actually Resource rather than Embedded Resource. Thinking about it now, Embedded Resource does seem more like a reference to a Resource in another DLL.
I inadvertently found the answer in this post while trying to improve my code.