Xamarin.UWP CarouselPage OnAppearing() bug - xamarin

App.xaml.cs
MainPage = new NavigationPage(new Home());
Home.xaml.cs
public Home()
{
Children.Insert(0,new CarPage1());
Children.Insert(1,new CarPage2());
Children.Insert(2,new CarPage3());
CurrentPage = Children[1];
}
CarPage1.xaml.cs
protected override void OnAppearing()
{
base.OnAppearing();
DisplayAlert("Page1", null, "ok");
}
CarPage2.xaml.cs
protected override void OnAppearing()
{
base.OnAppearing();
DisplayAlert("Page2", null, "ok");
}
CarPage3.xaml.cs
protected override void OnAppearing()
{
base.OnAppearing();
DisplayAlert("Page3", null, "ok");
}
Run UWP Page2 alert show.
click ok why Page1 alert show?
click UWP left symbol why no Page1 alert show?
Run Xamarin.Android work fine!!

Yes, it is just the case as you said.
And I have created a new issue about this problem. You can follow it up here: https://github.com/xamarin/Xamarin.Forms/issues/15577 .
Thanks for your support and feedback for xamarin.
Have a nice day.

Related

How do I control the content page focus?

I have a listview data on ItemsPage and when I select an item I can edit it and will update on database. My problem is, when a go back to ItemsPage I want to refresh the list
I already tried to call the method OnAppearing to try to refresh in OnItemSelected under the Navigation like this:
namespace TesteMasterDatail.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class ItemsPage : ContentPage
{
ItemsViewModel viewModel;
public ItemsPage()
{
InitializeComponent();
BindingContext = viewModel = new ItemsViewModel();
}
async void OnItemSelected(object sender, SelectedItemChangedEventArgs args)
{
var item = args.SelectedItem as Item;
if (item == null)
return;
await Navigation.PushAsync(new ItemDetailPage(new ItemDetailViewModel(item)));
OnAppearing();
ItemsListView.SelectedItem = null;
}
async void AddItem_Clicked(object sender, EventArgs e)
{
await Navigation.PushModalAsync(new NavigationPage(new NewItemPage()));
}
protected override void OnAppearing()
{
base.OnAppearing();
if (viewModel.Items.Count == 0)
viewModel.LoadItemsCommand.Execute(null);
}
}
}
It didnt work cause the refresh happens before the edition
you could use MessagingCenter to refresh your list after you add new item or edit item in a new page like:
in ItemsPage :
public ItemsPage()
{
InitializeComponent();
BindingContext = viewModel = new ItemsViewModel();
MessagingCenter.Subscribe<ItemsPage> (this, "Refresh", () =>
{
// refresh the list when the "Refresh" message is received
});
}
in ItemDetailPage or NewItemPage,after edit item or add new item:
MessagingCenter.Send<ItemsPage>(this, "Refresh");
Of course you could also pass parameter by MessagingCenter
OnAppearing() should be called for you when the page is navigated to after PopAsync is called - you do not need to manually call it.
However, note that your LoadItemsCommand will still not fire in this case, because the VM is already initialized.
from the docs
When the PopAsync method is invoked, the following events occur:
-The page calling PopAsync has its OnDisappearing override invoked.
-The page being returned to has its OnAppearing override invoked.
-The PopAsync task returns.

Xamarin Forms ToolbarItems shown on the wrong page

I have an Issue with the ToolbarItems.
So i start my application and in the constructor I check if somebody clicked on an element from the listview which is on my main page. If that happens, I'll start a new page. The error I have is that the toolbaritems from the mainpage are still displayed now.
Here this is the Method I use in the constructor :)
public void LoadLastPortal() {
if (App.Current.Properties.ContainsKey("LastPortal"))
{
String LastPortal = App.Current.Properties["LastPortal"].ToString();
if (!string.IsNullOrEmpty(LastPortal))
{
Navigation.PushAsync(new LoginPage(App.Current.Properties["LastPortal"].ToString()));
}
}
I've tried to reproduce your issue, but in my sample app it works. See here the code for the MainPage:
public MainPage()
{
InitializeComponent();
this.ToolbarItems.Add(new ToolbarItem { Text = "test1" });
this.ToolbarItems.Add(new ToolbarItem { Text = "test2" });
this.ToolbarItems.Add(new ToolbarItem { Text = "test3" });
}
private void NavigateButtonOnClicked(object sender, EventArgs e)
{
Navigation.PushAsync(new SecondPage());
}
After I pressed the Button on the MainPage I'm navigating to the SecondPage and the three ToolbarItems aren't shown. Please provide some more information, so I'm able to help you.

Button Clicked in Xamarin Android to call Xamarin.Forms.Page?

I need to call a Xamarin.Forms Page through an Activity in Xamarin.Android.
I had used [Java.Interop.Export("btnOne1Click")] to call the Xamarin.Forms Page.
The code runs without errors if I use App.Current.MainPage = new RootPage(); But it does not navigate to that Page.
I don't want to call the [Java.Interop.Export("btnOne1Click")] on MainActivity.
[Activity(Label = "FailureActivity")]
public class FailureActivity : Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
RequestWindowFeature(WindowFeatures.NoTitle);
SetContentView(Resource.Layout.Failure);
Button button = FindViewById<Button>(Resource.Id.txt_go_onjobs);
}
[Java.Interop.Export("btnOne1Click")]
public void btnOne1Click(Android.Views.View v)
{
try
{
Xamarin.Forms.Forms.Context.StartActivity(typeof(RootPage));
}
catch(Exception ex)
{ }
}
}
Xamarin forms runs on one activity, which is most like your main activity.
There are two sample projects that show you how to communicate between native and form parts of the code, which can be found here:
https://github.com/xamarin/xamarin-forms-samples/tree/master/Forms2Native
https://github.com/xamarin/xamarin-forms-samples/tree/master/Native2Forms
However, to answer your question, you would do something like the following:
button = FindViewById<Button> (Resource.Id.txt_go_onjobs);
button.Click += (sender, e) => {
// this is your Xamarin.Forms screen
StartActivity(typeof(FormsActivity));
};
Now, in your FormsActivity call this:
[Activity (Label = "FormsActivity")]
public class FormsActivity : Xamarin.Forms.Platform.Android.FormsApplicationActivity
{
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
Xamarin.Forms.Forms.Init (this, bundle);
LoadApplication (new App ());
}
}

callback of Itemselected doesn't work in Xamarin?

I have a simple two pages.
One has a listview.
So when clicks an item of the listView, go to another page.
But I click default back button on my win phone then I click an item of one again, navigation page doesn't work completely.
Here is my code snippet.
in first page
listview.itemselected += listview_ItemSelected;
private void listview_ItemSelected(object sender, SelectedItemChangedEventArgs e)
{
if (e.SelectedItem = null){
}
else {
Device.BeginInvokeOnMainThread(() => Navigation.PushAsync(new twopage()));
}
}
Please be aware that I am testing on UWP Project based on Xamarin.Form.
MainPage
Page1
this is my screen short
step 1
public App()
{
InitializeComponent();
var mainpage = new NavigationPage(new MainPage());
MainPage = mainpage;
}
step2
private void ListView_ItemSelected(object sender, SelectedItemChangedEventArgs e)
{
var page = new Page1();
Navigation.PushAsync(page);
}

Why entry's Focus() method isn't working from page's constructor?

In Xamarin Forms, when I use the following code:
public SomePage()
{
InitializeComponent();
someEntry.Focus();
}
the code entry isn't focused by default, however, if I use the following code:
protected override void OnAppearing()
{
base.OnAppearing();
someEntry.Focus();
}
it works as needed (entry is focused). Why is that? Isn't codeEntry already existing and sitting at it's place, fully functional, after InitializeComponent() call? I mean, I sure can change Text property from page constructor.
In Xamarin, every control has equivalent view renderer, that is native UI element which will only be created when control is added to the native element hierarchy. In constructor, native element for entry is not yet created. However, in OnAppering, entry's corresponding native element is created so it can get the focus.
Also this seems like a bug as Xamarin is storing state and applying it when creating the native UI element. Its time to file a bug !!!
When I use Shell this don't work anymore.
protected override void OnAppearing()
{
base.OnAppearing();
someEntry.Focus();
}
But this does work:
protected async override void OnAppearing()
{
base.OnAppearing();
await Task.Delay(100);
someEntry.Focus();
}
File.xaml
<Entry x:Name="txtLPN" Placeholder="Scan LPN." Grid.Row="1" Grid.Column="0" FontSize="15" Focused="txtLPN_Focused" />
File.cs >>>>>
private void txtLPN_Focused(object sender, FocusEventArgs e)
{
txtLPN.CursorPosition = 0;
if (!string.IsNullOrEmpty(txtLPN.Text))
txtLPN.SelectionLength = txtLPN.Text.Length;
}
protected async override void OnAppearing()
{
base.OnAppearing();
await Task.Delay(600);
txtLPN.Focus();
}
I tried all of the above. I think because my page is a pop-up and has some animation none of the above worked. However this worked for me:
BackgroundWorker setFocus = new BackgroundWorker();
In constructor
setFocus.DoWork += SetFocus_DoWork;
private void SetFocus_DoWork(object sender, DoWorkEventArgs e)
{
bool worked = false;
while (!worked)//will keep trying until it can set focus (when MyEntry is rendered)
{
Thread.Sleep(1);
MainThread.InvokeOnMainThreadAsync(()=> worked = MyEntry.Focus());
}
}
protected override void OnAppearing()
{
base.OnAppearing();
if(!setFocus.IsBusy)
{
setFocus.RunWorkerAsync();
}
}
You may want to add something to handle if "worked" is never set to true like try this for a few seconds.
You can use the Xamarin Community Toolkit LifecycleEffect to call some code when the renderer for the Entry is initialized/cleaned up. Combine this with OnAppearing to reliably show the keyboard without using cheap DoEvents hacks like await Task.Yield() or await Task.Delay(100).
XAML:
<Entry x:Name="userName">
<Entry.Effects>
<xct:LifecycleEffect Loaded="LifecycleEffect_Loaded" Unloaded="LifecycleEffect_Unloaded" />
</Entry.Effects>
</Entry>
C#:
private bool userNameLoaded = false;
protected override void OnAppearing()
{
base.OnAppearing();
if (userNameLoaded)
{
userName.Focus();
}
}
private void LifecycleEffect_Loaded(object sender, System.EventArgs e)
{
if (sender == userName)
{
userNameLoaded = true;
userName.Focus();
}
}
private void LifecycleEffect_Unloaded(object sender, System.EventArgs e)
{
if (sender == userName)
{
userNameLoaded = false;
}
}
OnAppearing won't be called after background + resume on iOS, so you'll need to hook into Application.OnResume to show focus if the user backgrounds + restores the app on iOS:
protected override void OnResume()
{
if (Xamarin.Forms.Device.RuntimePlatform == Xamarin.Forms.Device.iOS)
{
// TODO: Use Messenger, check Shell.Current.CurrentPage, etc. to set focus.
}
}
underneath of Xamarin form it is android activity or iOS 's UIviewController's page life cycle works. someEntry.Focus(); will not work in your constructor

Resources