Ok so i followed a few tutorials to make it so my app can read a database file and used this https://github.com/jfversluis/ExistingSQLiteDbSample
And it did work for me, but now what I'm trying to do is so my app can use the text stored in the database so it can do a share function using Xamarin.Essentials: Share
I would prefer it was a button but no idea were to even begin (since i want the button to be a image)
The code of my main page is this (its almost 1:1 with the first link), the data that i want to turn into a button is "LocationLink" which i temporary have setup as a Label
MainPage.xaml
<StackLayout>
<CollectionView ItemsSource="{Binding List}">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout>
<BoxView HeightRequest="1" Color="#000000" IsVisible="true"/>
<Label Text="{Binding LocationName}"/>
<!-- Bellow is what i need help with-->
<Label Text="{Binding LocationLink}"/>
<Button/>
<!-- Above is what i need help with-->
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>
Item.cs
public class Temp
{
public Int Id { get; set; }
public string LocationName { get; set; }
public string LocationLink { get; set; }
}
<Button Text="Click Me!" Clicked="ButtonClick" />
then
protected void ButtonClick(object sender, EventArgs args)
{
// get the button
var button = (Button)sender;
// I don't know what your class is called, you will need to put
// the correct name here
var item = (MyListItem)button.BindingContext;
// now you can use item.LocationName, item.LocationLink, etc
// when calling the Share function
}
I need to download static images from my CDN and display them in my Xamarin.Forms view. I'm new to Xamarin specifically and I'm having a hard time figuring out how to load an image from a byte array pulled from a HTTP request.
I have the following XAML in my View:
<ListView ItemsSource="{Binding Images}">
<ListView.ItemTemplate>
<DataTemplate>
<ImageCell ImageSource="{Binding .}">
</ImageCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
In my code behind I'm fetching the image and trying to bind to a Collection of ImageSource instances.
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
public ObservableCollection<ImageSource> Images { get; set; } = new ObservableCollection<ImageSource>();
protected override async void OnAppearing()
{
base.OnAppearing();
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Referer", "https://foo.bar/");
var response = await client.GetAsync("https://foo.bar/library/5.jpg");
byte[] image = await response.Content.ReadAsByteArrayAsync();
var imageSource = ImageSource.FromStream(() => new MemoryStream(image));
this.Images.Add(imageSource);
}
}
When I do this the Image within the StackLayout is empty. I know I can instead just bind to a URL and the ImageSource can download it for me but I'm required to pass a Referrer Header. I can't see anyway for me to force the XAML Image view to allow custom headers, nor can I see a way to do it if I instantiate an instance of ImageSource in my code behind.
When I read the documentation on ImageSource it sounds like it only supports URI, File, Stream and App Resources to load images from. Since I had an array of bytes I wrapped it in a MemoryStream and called ImageSource.FromStream. Nothing loads when the app runs though - the ImageCell is empty.
I know the image was downloaded. I converted the byte[] to a Base64 string then dropped it into Base64 to Image Decoder. The image loads no problem so I know it's being downloaded properly. What I don't understand is why I can't get the image to render on a ImageSource.
I've also tried to just use a normal Image control and have the same problem.
<ScrollView>
<ContentView>
<StackLayout BindableLayout.ItemsSource="{Binding Images}" Orientation="Horizontal">
<BindableLayout.ItemTemplate>
<DataTemplate>
<Image Source="{Binding}"></Image>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</ContentView>
</ScrollView>
Am I doing something completely wrong here or is dynamic downloading of images from the internet with special Headers something I can't do in Xamarin.Forms?
Try to add this.BindingContext = this; in page constructor.
public MainPage()
{
InitializeComponent();
this.BindingContext = this;
}
I have a Xamarin Forms Applikation with a picker in a page defined like this:
<Picker ItemsSource="{Binding AvailableCultures}"
SelectedItem="{Binding SelectedCulture, Mode=TwoWay}"
ItemDisplayBinding="{Binding DisplayName}" />
The relevant parts in the viewmodel are:
private CultureInfo selectedCulture = CultureHelper.CurrentCulture;
public CultureInfo SelectedCulture
{
get => selectedCulture;
set
{
if(value == null)
return;
if(selectedCulture == value)
return;
selectedCulture = value;
settingsFacade.DefaultCulture = selectedCulture.Name;
CultureHelper.CurrentCulture = selectedCulture;
RaisePropertyChanged();
}
}
public ObservableCollection<CultureInfo> AvailableCultures { get; }
private async Task LoadAvailableCulturesAsync()
{
await dialogService.ShowLoadingDialogAsync();
CultureInfo.GetCultures(CultureTypes.AllCultures).OrderBy(x => x.Name).ToList().ForEach(AvailableCultures.Add);
SelectedCulture = AvailableCultures.First(x => x.Name == settingsFacade.DefaultCulture);
await dialogService.HideLoadingDialogAsync();
}
This works without issues on the simulator when I debug. It also works without problems on Android. But when I deploy the application on iOS the texts are empty.
I can scroll through them and select new ones and the value is changed. I thought it might be a problem with the binding, but it persists when I turn linking off completely.
What can cause that?
Repository Link: https://github.com/MoneyFox/MoneyFox
After testing between Debug and Release mode , we will see that DisplayName not shows in Release mode, however EnglishName always shows.
The Debug mode:
The Release mode:
Therefore, there is a workaround to make it works in Release mode.
Modify Xaml code of Picker with binding EnglishName for ItemDisplayBinding as follows:
<Picker x:Name="MyPicker"
ItemsSource="{Binding AvailableCultures}"
SelectedItem="{Binding SelectedCulture, Mode=TwoWay}"
ItemDisplayBinding="{Binding EnglishName}" />
I want to handle the click/tap event on a WebView control
I've tried the GestureRecognizers but nothing happens, i think maybe the WebView has some sort of making the event handled "true".
<WebView>
<WebView.GestureRecognizers>
<TapGestureRecognizer
Tapped="OnWebViewClick"
NumberOfTapsRequired="1" />
</WebView.GestureRecognizers>
</WebView>
And I've tried it using c# code behind too but no luck :/
I am using this hack: put the WebView in a Grid and insert a BoxView in the same cell. Then put a handler on the BoxView.
You can use the HybridWebView from XLabs, and use javascript injection to invoke and handle clicks in your Xamarin control. The injected javascript code can add a click-event listener at capture stage. When a click is detected it uses Native callback to send information back to C# code.
For example - you can define a custom control like this:
public class ClickEventArgs : EventArgs
{
public string Element { get; set; }
}
public class ClickableWebView : XLabs.Forms.Controls.HybridWebView
{
public event EventHandler<ClickEventArgs> Clicked;
public static readonly BindableProperty ClickCommandProperty =
BindableProperty.Create("ClickCommand", typeof(ICommand), typeof(ClickableWebView), null);
public ICommand ClickCommand
{
get { return (ICommand)GetValue(ClickCommandProperty); }
set { SetValue(ClickCommandProperty, value); }
}
public ClickableWebView()
{
LoadFinished += (sender, e) =>
InjectJavaScript(#"
document.body.addEventListener('click', function(e) {
e = e || window.event;
var target = e.target || e.srcElement;
Native('invokeClick', 'tag='+target.tagName+' id='+target.id+' name='+target.name);
}, true /* to ensure we capture it first*/);
");
this.RegisterCallback("invokeClick", (string el) => {
var args = new ClickEventArgs { Element = el };
Clicked?.Invoke(this, args);
ClickCommand?.Execute(args);
});
}
}
Sample XAML usage
<local:ClickableWebView
Uri="https://google.com"
Clicked="Handle_Clicked"
/>
and sample code-behind
void Handle_Clicked(object sender, CustomWebView.ClickEventArgs e)
{
Xamarin.Forms.Application.Current.MainPage.DisplayAlert("WebView Clicked", e.Element, "Dismiss");
}
** Output **
Alternatively, you can also bind ClickCommand property to implement this using MVVM pattern.
Another option is to handle the click in html and do a navigation that doesn't go anywhere. You can put something like this in your html
<div onclick="window.location.href='#click#'">...</div>
So a click anywhere inside there would cause a navigation. If you only have a button, you could just use
<a href='#click'>...</a>
Then in your WebView control wire up the Navigating event, and check if the new url contains "#click". If so, do your click handling code and call e.Cancel=true in the event to prevent the browser from completing the navigation.
Note that onclick handlers don't work on body or document elements in Xamarin Webview. At least not on iOS.
I've found the simplest approach is to use a Grid with two controls, the WebView and a Button
<Grid>
<WebView
Grid.Column="0"
Grid.Row="0"
HeightRequest="100"
WidthRequest="1000" />
<Button
Grid.Column="0"
Grid.Row="0"
BackgroundColor="Transparent"
HorizontalOptions="Fill"
VerticalOptions="Fill"
Clicked="OnWebViewTapped"/>
</Grid>
The button covers the WebView and intercepts taps.
Gesture recognizer doesn't work with WebView. You can try using MR.Gestures
To get all the features you will have to purchase a license.
If you forget to configure the license key properly or the key does not match your app name, then all the events will still be raised, but the properties of the EventArgs will be empty. That may be enough for the tap and long press events, but not for the more complicated ones.
An easier workaround is to use the 'Focused' event on your webview. You can implement it as below:
var wb = new WebView
{
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.FillAndExpand,
Source = "https://stackoverflow.com/questions/56320611/webview-gesturerecognition-not-working-in-xamarin-forms",
};
wb.Focused += (s, e) =>
{
//Handle your logic here!
wb.Unfocus();
};
I am trying to bind web address of an image (BigImageURL) with a image control. It works fine mostly but for some images i am getting http 403 error (found out using fiddler) and obviously the image does not get displayed. I want to display a static image in case the http url is not resolved.
<Image x:Name="HoverImage" Source="{Binding BigImageURL}" />
I tried to write a converter
public class UriToImageSourceConverter : IValueConverter
{
public object Convert(object value, Type targetType,object parameter, CultureInfo culture)
{
BitmapImage image = null;
try
{
image = new BitmapImage(new Uri(value.ToString()));
}
catch (Exception ex)
{
image= new BitmapImage(new Uri("..<mydefaultimageUrl>.."));
}
return image;
}
...
}
<Image x:Name="HoverImage" Source="{Binding BigImageURL,Converter={StaticResource myUriToImageSourceConverter}" />
didn't work !!
Even though the image url was not accessible, the converter didn't throw any exception. I don't think it tries to resolve the address or read image stream while creating the BitmapImage
Tried setting up a FallbackValue but it didn't work either.
<Image x:Name="HoverImage" Source="{Binding BigImageURL,FallbackValue=DefaultUrl}"/>
Any pointers ??
Thanks in advance
Actually you have to do something like this
<Image x:Name="HoverImage" Source="{Binding BigImageURL}"
ImageFailed="HoverImage_ImageFailed" />
and add event handler
private void HoverImage_ImageFailed(object sender, ExceptionRoutedEventArgs e)
{
var expection = e.ErrorException; // Here we could know what happend
HoverImage.Source = someDefaultUrl; // And here we add default Url...
}
In silverligth you have to handle not loader image and image exceptions with help of events... do not use databinding for that case..