Programmatically scrolling a CollectionView to end causes exception "Invalid Target Position" - xamarin.forms

The above header refers.
I am trying to implement a chatting app. There are no compilation errors but whenever it starts running and gets to this line:
MessageList.ScrollTo(viewModel.Messages.Last(), null, ScrollToPosition.End, true);
it triggers this error:
"Invalid target position".
This is the stack trace:
"Ex = {Java.Lang.IllegalArgumentException: Invalid target position
at Java.Interop.JniEnvironment+InstanceMethods.CallVoidMethod (Java.Interop.JniObjectReference instance, Java.Interop.JniMethodInfo method, Java.Interop.JniArgumentValue* args) [0x00068] in /Use..."
This is the ChatView.xaml file where MessageList is defined:
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:selectors="clr-namespace:Chat.Selectors"
xmlns:converters="clr-namespace:Chat.Converters"
x:Class="Chat.Views.ChatView">
<ContentPage.Resources>
<selectors:ChatMessageSelector x:Key="SelectMessageTemplate" />
<converters:Base64ToImageConverter x:Key="ToImage" />
</ContentPage.Resources>
<ScrollView>
<ScrollView.Orientation>
<OnPlatform x:TypeArguments="ScrollOrientation">
<On Platform="iOS" Value="Vertical" />
<On Platform="Android" Value="Neither" />
</OnPlatform>
</ScrollView.Orientation>
<Grid x:Name="MainGrid">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="1" />
<RowDefinition>
<RowDefinition.Height>
<OnPlatform x:TypeArguments="GridLength">
<On Platform="iOS" Value="50" />
<On Platform="Android" Value="100" />
</OnPlatform>
</RowDefinition.Height>
</RowDefinition>
</Grid.RowDefinitions>
<CollectionView x:Name="MessageList" ItemsSource="{Binding Messages}"
ItemTemplate="{StaticResource SelectMessageTemplate}">
<CollectionView.Resources>
<ResourceDictionary>
<DataTemplate x:Key="SimpleText">
<Grid Padding="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Frame StyleClass="remoteMessage" HasShadow="false" BackgroundColor="#F04D6A">
<StackLayout>
<Label Text="{Binding Username}" StyleClass="chatHeader" FontAttributes="Bold"/>
<Label Text="{Binding Text}" StyleClass="chatText" />
</StackLayout>
</Frame>
</Grid>
</DataTemplate>
<DataTemplate x:Key="LocalSimpleText">
<Grid Padding="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Frame Grid.Column="1" StyleClass="localMessage" HasShadow="false" BackgroundColor="#24A43B">
<StackLayout>
<Label Text="{Binding Username}" StyleClass="chatHeader" FontAttributes="Bold"/>
<Label Text="{Binding Text}" StyleClass="chatText" />
</StackLayout>
</Frame>
</Grid>
</DataTemplate>
<DataTemplate x:Key="UserConnected">
<StackLayout Padding="10" BackgroundColor="#33000000" Orientation="Horizontal">
<Label Text="{Binding Username}" StyleClass="chatHeader" VerticalOptions="Center" />
<Label Text="connected" StyleClass="chatText" VerticalOptions="Center" />
</StackLayout>
</DataTemplate>
<DataTemplate x:Key="Photo">
<Grid Padding="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<StackLayout>
<Label Text="{Binding Username}" StyleClass="chatHeader" />
<Image Source="{Binding Url}" Aspect="AspectFill"
HeightRequest="150" HorizontalOptions="Fill" />
</StackLayout>
</Grid>
</DataTemplate>
<DataTemplate x:Key="LocalPhoto">
<Grid Padding="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<StackLayout Grid.Column="1">
<Label Text="{Binding Username}" StyleClass="chatHeader" />
<Image Source="{Binding Base64Photo, Converter={StaticResource ToImage}}"
Aspect="AspectFill" HeightRequest="150" HorizontalOptions="Fill" />
</StackLayout>
</Grid>
</DataTemplate>
</ResourceDictionary>
</CollectionView.Resources>
</CollectionView>
<BoxView Grid.Row="1" HeightRequest="1" BackgroundColor="#33000000" />
<Grid Grid.Row="2" Padding="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="30" />
</Grid.ColumnDefinitions>
<Image Source="photo.png"
VerticalOptions="Center" HorizontalOptions="Center" HeightRequest="30">
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Photo}" />
</Image.GestureRecognizers>
</Image>
<Entry Text="{Binding Text}" Grid.Column="1"
ReturnCommand="{Binding Send}" />
<Image Grid.Column="2" Source="send.png"
VerticalOptions="Center" HorizontalOptions="Center" HeightRequest="30" >
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Photo}" />
</Image.GestureRecognizers>
</Image>
</Grid>
</Grid>
</ScrollView>
</ContentPage>
This is the ChatViewModel.cs file:
using Acr.UserDialogs;
using Chat.Services;
using Chat.Messages;
using Plugin.Media;
using Plugin.Media.Abstractions;
using System;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Input;
using Xamarin.Forms;
namespace Chat.ViewModels
{
public class ChatViewModel : BaseViewModel
{
private readonly IChatService chatService;
public ObservableCollection<Message> Messages { get; private set; }
public ChatViewModel(IChatService chatService)
{
this.chatService = chatService;
Messages = new ObservableCollection<Message>();
chatService.NewMessage += ChatService_NewMessage;
Task.Run(async () =>
{
if (!chatService.IsConnected)
{
await chatService.CreateConnection();
}
await chatService.SendMessage(new UserConnectedMessage(User));
});
}
private string text;
public string Text
{
get => text;
set => Set(ref text, value);
}
public ICommand Send => new Command(async () =>
{
var message = new SimpleTextMessage(User)
{
Text = this.Text
};
Messages.Add(new LocalSimpleTextMessage(message));
await chatService.SendMessage(message);
Text = string.Empty;
});
public ICommand Photo => new Command(async () =>
{
var options = new PickMediaOptions
{
CompressionQuality = 50
};
var photo = await CrossMedia.Current.PickPhotoAsync();
UserDialogs.Instance.ShowLoading("Uploading photo");
var stream = photo.GetStream();
var bytes = ReadFully(stream);
var base64photo = Convert.ToBase64String(bytes);
var message = new PhotoMessage(User)
{
Base64Photo = base64photo,
FileEnding = photo.Path.Split('.').Last()
};
Messages.Add(message);
await chatService.SendMessage(message);
UserDialogs.Instance.HideLoading();
});
private void ChatService_NewMessage(object sender, Events.NewMessageEventArgs e)
{
Device.BeginInvokeOnMainThread(() =>
{
if (!Messages.Any(x => x.Id == e.Message.Id))
{
Messages.Add(e.Message);
}
});
}
private byte[] ReadFully(Stream input)
{
using (MemoryStream ms = new MemoryStream())
{
ms.CopyTo(input);
return ms.ToArray();
}
}
private string username;
public string Username { get => username; set => Set(ref username, value); }
private ImageSource url;
public ImageSource Url { get => url; set => Set(ref url, value); }
private ImageSource base64Photo;
public ImageSource Base64Photo { get => base64Photo; set => Set(ref base64Photo, value); }
}
}
This is the ChatView.xaml.cs file:
using Chat.ViewModels;
using System;
using System.Linq;
using Xamarin.Forms;
using Xamarin.Forms.PlatformConfiguration.iOSSpecific;
using Xamarin.Forms.Xaml;
namespace Chat.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class ChatView : ContentPage
{
private ChatViewModel viewModel;
public ChatView(ChatViewModel viewModel)
{
this.viewModel = viewModel;
InitializeComponent();
On<Xamarin.Forms.PlatformConfiguration.iOS>().SetUseSafeArea(true);
viewModel.Messages.CollectionChanged += Messages_CollectionChanged;
BindingContext = viewModel;
}
protected override void OnAppearing()
{
base.OnAppearing();
var safeArea = On<Xamarin.Forms.PlatformConfiguration.iOS>().SafeAreaInsets();
MainGrid.HeightRequest = this.Height - safeArea.Top - safeArea.Bottom;
}
private void Messages_CollectionChanged(object sender,
System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
try
{
int Kounter = viewModel.Messages.Count;
//if (Kounter == 1)
//{
//MessageList.ScrollTo(viewModel.Messages.First(), null, ScrollToPosition.Start, true);
//}
//else
//{
MessageList.ScrollTo(viewModel.Messages.Last(), null, ScrollToPosition.End, true);
//}
}
catch (Exception Ex)
{
Console.WriteLine(Ex);
}
}
}
}
I am using Xamarin.forms version 5.0.0.2515 on Visual Studio version 17.3.
So, what is the issue and how do I sort it out?

Instead of manually scrolling, set CollectionView's ItemsUpdatingScrollMode property.
From Control scroll position when new items are added:
<CollectionView ItemsUpdatingScrollMode="KeepLastItemInView">

Related

how to play multiful audio files in a single page in xamarin forms

Good day all, I can play a audio file now with different pages according to what #Bas H, answered my question for a couple of days and make a small project in respect of it, but now I want him or someone to show me how to play multiple audio files in a single page.
This is an example:
xaml page:
<Frame>
<StackLayout>
<ImageButton
x:Name="btnPlay"
HeightRequest="50"
HorizontalOptions="Center"
Source="Play.png"
VerticalOptions="Center"
WidthRequest="50" />
<ImageButton
x:Name="btnPause"
HeightRequest="50"
HorizontalOptions="Center"
Source="pause.png"
VerticalOptions="Center"
WidthRequest="50"
IsVisible="false"/>
<Label
HorizontalOptions="Start"
Text="Loop:"
VerticalOptions="Center" />
<Switch
x:Name="switchLoop"
HorizontalOptions="Start"
IsToggled="False"
VerticalOptions="Center" />
</StackLayout>
</Frame>
<Frame>
<StackLayout>
<ImageButton
x:Name="btnPlaytwo"
HeightRequest="50"
HorizontalOptions="Center"
Source="Play.png"
VerticalOptions="Center"
WidthRequest="50" />
<ImageButton
x:Name="btnPausetwo"
HeightRequest="50"
HorizontalOptions="Center"
Source="pause.png"
VerticalOptions="Center"
WidthRequest="50"
IsVisible="false"/>
<Label
HorizontalOptions="Start"
Text="Loop:"
VerticalOptions="Center" />
<Switch
x:Name="switchLooptwo"
HorizontalOptions="Start"
IsToggled="False"
VerticalOptions="Center" />
</StackLayout>
</Frame>
<Frame>
<StackLayout>
<ImageButton
x:Name="btnPlaythree"
HeightRequest="50"
HorizontalOptions="Center"
Source="Play.png"
VerticalOptions="Center"
WidthRequest="50" />
<ImageButton
x:Name="btnPausethree"
HeightRequest="50"
HorizontalOptions="Center"
Source="pause.png"
VerticalOptions="Center"
WidthRequest="50"
IsVisible="false"/>
<Label
HorizontalOptions="Start"
Text="Loop:"
VerticalOptions="Center" />
<Switch
x:Name="switchLoopthree"
HorizontalOptions="Start"
IsToggled="False"
VerticalOptions="Center" />
</StackLayout>
</Frame>
code behind:
public HeadProjectAudioPage()
{
InitializeComponent();
btnPause.IsVisible = false;
var player = Plugin.SimpleAudioPlayer.CrossSimpleAudioPlayer.Current;
player.PlaybackEnded += (sender, e) =>
{
btnPlay.IsVisible = true;
btnPause.IsVisible = false;
};
player.Load("running.mp3");
btnPlay.Clicked += BtnPlayClicked;
btnPause.Clicked += BtnPauseClicked;
switchLoop.Toggled += SwitchLoopToggled;
}
protected override void OnAppearing()
{
base.OnAppearing();
btnPause.IsVisible = false;
}
private void SwitchLoopToggled(object sender, ToggledEventArgs e)
{
Plugin.SimpleAudioPlayer.CrossSimpleAudioPlayer.Current.Loop = switchLoop.IsToggled;
}
private void BtnPlayClicked(object sender, EventArgs e)
{
btnPause.IsVisible = true;
btnPlay.IsVisible = false;
Plugin.SimpleAudioPlayer.CrossSimpleAudioPlayer.Current.Play();
}
private void BtnPauseClicked(object sender, EventArgs e)
{
btnPlay.IsVisible = true;
btnPause.IsVisible = false;
Plugin.SimpleAudioPlayer.CrossSimpleAudioPlayer.Current.Pause();
}
}
Thank you for your contributions.
I still used the picker or else the loop did not work.
Because the mp3 is loaded at startup i use a picker to change the mp3 .picker is hidden. Want to change or add a mp3 ad it to the picker.
HeadProjectAudioPage.xaml
<Picker
x:Name="picker"
HorizontalTextAlignment="Center"
SelectedIndexChanged="picker_SelectedIndexChanged"
IsVisible="false">
<Picker.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>running.mp3</x:String>
<x:String>Drup.mp3</x:String>
<x:String>Diminished.mp3</x:String>
</x:Array>
</Picker.ItemsSource>
</Picker>
Ad this after InitializeComponent(); in HeadProjectAudioPage.xaml.cs
picker.SelectedItem = "running.mp3"; ///////// You must selected before start if not a error
Add the 2 ImageButtons in HeadProjectAudioPage.xaml.cs
btnPlaytwo.Clicked += BtnPlaytwoClicked;
btnPlaythree.Clicked += BtnPlaythreeClicked;
And to start the mp3's in HeadProjectAudioPage.xaml.cs
private void BtnPlayClicked(object sender, EventArgs e)
{
picker.SelectedItem = "running.mp3";
Plugin.SimpleAudioPlayer.CrossSimpleAudioPlayer.Current.Play();
}
private void BtnPlaytwoClicked(object sender, EventArgs e)
{
picker.SelectedItem = "Drup.mp3";
Plugin.SimpleAudioPlayer.CrossSimpleAudioPlayer.Current.Play();
}
private void BtnPlaythreeClicked(object sender, EventArgs e)
{
picker.SelectedItem = "Diminished.mp3";
Plugin.SimpleAudioPlayer.CrossSimpleAudioPlayer.Current.Play();
}
When start a mp3 the pickers change and play that mp3 , the loop works also.
You can add the code for all the loops .
Maybe not the best way but it works , the loading of the mp3 can be on different ways. But this is an idea

Xamarin forms webview covers every element in xaml page

I have a webview and a label inside one of my xaml page. I am loading a local html file to the webview inside OnAppearing(). Problem is I cannot see the label. Webview takes whole screen. I tested in Android.
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="Test.Views.MyWebView">
<ContentPage.Content>
<StackLayout BackgroundColor="Red" VerticalOptions="FillAndExpand" Orientation="Vertical">
<Label HeightRequest="100" TextColor="Black" Text="Sample"/>
<StackLayout>
<ScrollView>
<other:HybridWebView x:Name="hybridWebView" VerticalOptions="FillAndExpand"
Navigating="webView_Navigating" HeightRequest="400" Navigated="MywebView_Navigated" />
</ScrollView>
</StackLayout>
</StackLayout>
</ContentPage.Content>
</ContentPage>
Code behind
OnAppearing
protected override void OnAppearing()
{
base.OnAppearing();
NavigationPage.SetHasNavigationBar(this, false);
if (isFirstRun)
{
jsonOutput = JsonConvert.SerializeObject(payData);
//var htmlSource = new HtmlWebViewSource();
var urlSource = new UrlWebViewSource();
string url = DependencyService.Get<IBaseUrl>().Get();
TempUrl = Path.Combine(url, "xamarinhtmlmotor.html");
urlSource.Url = TempUrl;
hybridWebView.Source = urlSource;
isFirstRun = false;
Content = hybridWebView;
}
}
webView_Navigating
private void webView_Navigating(object sender, WebNavigatingEventArgs e)
{
UserDialogs.Instance.ShowLoading("Loading...", MaskType.Black);
}
Here I am currently checking for the android devices
MywebView_Navigated
private async void MywebView_Navigated(object sender, WebNavigatedEventArgs e)
{
UserDialogs.Instance.HideLoading();
if (Device.RuntimePlatform == Device.Android)
{
if (e.Url.Equals("file:///android_asset/web/xamarinhtmlmotor.html"))
{
getResult();
}
else if (e.Url.Equals("http://localhost/receipt_motor.aspx"))
{
string rtNo = "receiptNo";
string cvNo = "<%= hdntxtbxTaksit.ClientID %>";
receiptNo = await hybridWebView.EvaluateJavaScriptAsync($"document.getElementById('{rtNo}').value;");
cvNoteNo = await hybridWebView.EvaluateJavaScriptAsync($"document.getElementById('{cvNo}');");
if (receiptNo != null && !receiptNo.Equals(""))
{
}
if (cvNoteNo != null && !cvNoteNo.Equals(""))
{
}
}
}
}
}
Why don't you try with grid?
<Grid RowSpacing="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Label Grid.Row="0" Text="Sample" FontSize="Large" HorizontalOptions="CenterAndExpand"></Label>
<StackLayout Grid.Row="1" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<other:HybridWebView x:Name="hybridWebView" VerticalOptions="FillAndExpand"
Navigating="webView_Navigating" Navigated="MywebView_Navigated" />
</StackLayout>
</Grid>

How can I get all data from BindableLayout ItemsSource onclick events

I am trying to create a sales app using Xamarin forms but am stuck on adding products to cart. I am using BindableLayout ItemsSource to populate my list horizontally:
<StackLayout BindableLayout.ItemsSource="{Binding NafakaList}" Orientation="Horizontal" Spacing="20"
VerticalOptions="Start">
<BindableLayout.ItemTemplate>
<DataTemplate x:Name="nafakaStackLayout">
<StackLayout VerticalOptions="Start">
<Frame Padding="0" HasShadow="False" HorizontalOptions="Start" VerticalOptions="Start"
CornerRadius="10" HeightRequest="150" WidthRequest="150">
<Image Source="{Binding Image}" Aspect="Fill" HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand" />
</Frame>
<StackLayout Orientation="Horizontal" HorizontalOptions="FillAndExpand">
<StackLayout>
<Label Text="{Binding Name}" TextColor="Black" FontSize="15" x:Name="nameView" />
<Label Text="{Binding Price}" x:Name="Price" Margin="0,-7,0,0" TextColor="#62153B"
FontSize="12" FontFamily="{StaticResource BoldFont}" />
</StackLayout>
<StackLayout Orientation="Horizontal" Margin="0" VerticalOptions="EndAndExpand">
<!--this is the button that I am using to pass data through-->
<Button Command="{Binding .}" BackgroundColor="White" CommandParameter="{Binding Product}"
HeightRequest="35" FontSize="Small" Text="Add to Cart" x:Name="cartAdd"
Clicked="cartAdd_Clicked" />
</StackLayout>
</StackLayout>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
This is my list and button click event:
public void cartAdd_Clicked(object sender, EventArgs e)
{
Object commandParameter = ((Button) sender).CommandParameter;
pr = (Product) NafakaList.GetItem(1);
DisplayAlert(pr.Name, "test", "Ok");
}
List:
public List<Product> NafakaList { get => GetProduct(); }
private List<Product> GetProduct(string name)
{
var products = new List<Product>();
products.Add(new Product {ID= 1, Image = "https://images.unsplash.com/photo-1568347355280-d33fdf77d42a?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=752&q=80", Name = "Mchele", Price = "2500 tsh" });
products.Add(new Product { ID = 2, Image = "https://images.unsplash.com/photo-1574323347407-f5e1ad6d020b?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=680&q=80", Name = "Ngano", Price = "1600 tsh" }); ;
products.Add(new Product { ID = 3, Image = "https://images.unsplash.com/photo-1579705745811-a32bef7856a3?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=750&q=80", Name = "Maharage", Price = "1500 tsh" });
products.Add(new Product { ID = 4, Image = "https://images.unsplash.com/photo-1560705185-d0291220a442?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=667&q=80", Name = "Kunde", Price = "1000 tsh" });
return products;
}
Try This Code also
public void cartAdd_Clicked(object sender, EventArgs e)
{
var item = sender as Button;
var data = item.BindingContext as Product;
...
}
You don't need to bind Command or CommandParameter in your code:
<Button Clicked="cartAdd_Clicked" ... />
Use the BindingContext to get the Product:
public void cartAdd_Clicked(object sender, EventArgs e)
{
var product = (Product)((Button)sender).BindingContext;
...
}

How to sort a list using only 1 button multiply times in Xamarin.Forms?

I'm a beginner at coding in general so I don't have much experience. Is there a way I can use one button to sort/filter a list of cards that I have, multiple times by alphabetic order, type, element, class, etc. I have try different ways but as I said I'm still fairly new. Here is my code in XAML:
<ContentPage.Content>
<StackLayout>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="300"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<SearchBar Grid.Row="0"
Grid.Column="0"
x:Name="CardSearch"
TextChanged="SearchPressed"
Placeholder="Search Cards..."
CancelButtonColor="Red"
TextColor="Green"/>
<Button Grid.Row="0"
Grid.Column="1"
Text="Sort by"
Clicked="CardSorted"
/>
</Grid>
<ListView x:Name="CardsListView">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding Name}"
Detail="{Binding Rest}"
TextColor="ForestGreen"
DetailColor="MediumPurple"
/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
and my c#:
public partial class CardsPage : ContentPage
{
public CardsPage()
{
InitializeComponent();
CardsListView.ItemsSource = App.cardsList;
}
void SearchPressed(object sender, EventArgs w)
{
var cardListSearched = App.cardsList.Where(x => x.Name.Contains(CardSearch.Text));
CardsListView.ItemsSource = cardListSearched;
}
void CardSorted(object sender, EventArgs f)
{
//Need help right here
}
private async void BuilderPage(object sender, EventArgs b)
{
await Navigation.PushAsync(new DeckBuilder());
}
}
int sort = 0;
void CardSorted(object sender, EventArgs f)
{
switch (sort) {
case 0:
CardsListView.ItemsSource = App.cardsList.OrderBy(a => a.Name);
break;
case 1:
CardsListView.ItemsSource = App.cardsList.OrderBy(a => a.Age);
break;
...
}
sort += 1;
if (sort >= max) sort = 0;
}

When I am navigating to a new Xamarin Page, content isnt displaying when I am running System.Timer.Timer code

I used the System.Timers.Timer(); code to do the count down Timer on page load and then I used the Navigate.Push to go into another page.
Timer Code on page load:
public Index()
{
InitializeComponent();
StartCountDownTimer();
}
DateTime endTime = new DateTime(2019, 08, 25, 14, 00, 0);
public void StartCountDownTimer()
{
try
{
timer = new System.Timers.Timer();
timer.Interval = 1000;
timer.Elapsed += t_Tick;
TimeSpan ts = endTime - DateTime.Now;
lblCountDown.Text = ts.ToString("d' Days 'h' Hours 'm' Minutes 's' Seconds'");
timer.Start();
}
catch (Exception ex)
{
string Error = ex.Message;
}
}
System.Timers.Timer timer;
void t_Tick(object sender, EventArgs e)
{
try
{
TimeSpan ts = endTime - DateTime.Now;
string NewTimer = ts.ToString("d' Days 'h' Hours 'm' Minutes 's' Seconds'");
//txtCountDown.Text = NewTimer;
lblCountDown.Text = NewTimer;
if ((ts.TotalMilliseconds < 0) || (ts.TotalMilliseconds < 1000))
{
timer.Stop();
lblCountDown.Text = "The day has arrived";
}
}
catch (Exception ex)
{
string Error = ex.Message;
}
}
Navigate Code using a button click on the same page:
private void ClickAboutTab(object sender, EventArgs e)
{
await Navigation.PushAsync(new ReferralPage());
}
Code of page I am navigating to:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:behavior="clr-namespace:AppName.Validation"
xmlns:views="clr-namespace:AppName"
xmlns:controls="clr-namespace:ImageCircle.Forms.Plugin.Abstractions;assembly=ImageCircle.Forms.Plugin"
xmlns:input="clr-namespace:Plugin.InputKit.Shared.Controls;assembly=Plugin.InputKit"
x:Class="AppName.Pages.ReferralPage"
Title="Referral">
<ContentPage.Content>
<ScrollView>
<AbsoluteLayout>
<StackLayout AbsoluteLayout.LayoutBounds="0,0,1,1"
AbsoluteLayout.LayoutFlags="All" HorizontalOptions="CenterAndExpand">
<StackLayout>
<Grid BackgroundColor="White">
<Grid.RowDefinitions>
<RowDefinition Height="80"/>
<RowDefinition Height="*"/>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<StackLayout Orientation="Horizontal" HorizontalOptions="Center" Margin="0,10,0,0">
<controls:CircleImage Source="Assets/xinix.png" WidthRequest="160" HeightRequest="160" ></controls:CircleImage>
</StackLayout>
<Grid Grid.Row="1" Margin="20,0,20,0">
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition Height="40"/>
<RowDefinition Height="40"/>
<RowDefinition Height="40"/>
<RowDefinition Height="40"/>
<RowDefinition Height="40"/>
</Grid.RowDefinitions>
<Entry Placeholder="First Name" x:Name="txtFirstname" Grid.Row="0"/>
<Entry x:Name="txtLastname" Placeholder="Last Name" Grid.Row="1"/>
<Entry x:Name="txtEmail" Placeholder="name#domain.com" Grid.Row="2"/>
<Entry x:Name="txtPhone" Placeholder="Cell Phone" Grid.Row="3" MaxLength="10" Keyboard="Telephone"/>
<Button Text="Submit" x:Name="btnSubmit" Clicked="btnReferral_clicked" BackgroundColor="#3897F0" TextColor="White" HeightRequest="50" VerticalOptions="Start" Grid.Row="4"/>
</Grid>
</Grid>
</StackLayout>
</StackLayout>
<views:MenuBar AbsoluteLayout.LayoutBounds="0,1,1,52"
AbsoluteLayout.LayoutFlags="PositionProportional,WidthProportional"/>
</AbsoluteLayout>
</ScrollView>
</ContentPage.Content>
</ContentPage>
public ReferralPage()
{
InitializeComponent();
}
Solutions I already tried before navigating are:
timer.Stop();
timer.Dispose();
timer = null;
Device.BeginInvokeOnMainThread(async () =>);
updates to UI elements need to happen on the UI thread
Device.BeginInvokeOnMainThread( () => {
lblCountDown.Text = NewTimer;
});
I have updated my code. The Device.BeginInvokeOnMainThread you tried before, could solve your problem. Maybe you try the wrong way. You could refer to the code below.
void t_Tick(object sender, EventArgs e)
{
Device.BeginInvokeOnMainThread(() =>
{
try
{
TimeSpan ts = endTime - DateTime.Now;
string NewTimer = ts.ToString("d' Days 'h' Hours 'm' Minutes 's' Seconds'");
lblCountDown.Text = NewTimer;
if ((ts.TotalMilliseconds < 0) || (ts.TotalMilliseconds < 1000))
{
timer.Stop();
lblCountDown.Text = "The day has arrived";
}
}
catch (Exception ex)
{
string Error = ex.Message;
}
});
}
My result:

Resources