I want to run a method every minute that's started from my OnAppearing(). Do I need to run this as a task?
You can do this simpler by returning the correct value from Device.StartTimer
, to repeat true
, to not repeat false
and not use a StopWatch
. (source states that While the callback returns true, the timer will keep recurring.
And as you see from the source, the method doesn't need a Func<Task<bool>>
it only needs a Func<bool>
callback so there is no need to use a Task
.)
in the class
volatile bool run;
in OnAppearing
run = true;
Device.StartTimer(new TimeSpan(0, 1, 0), () => {
if (run) { /*do what you want;*/ return true; }
else { return false; }
});
in OnDisappearing
run = false;
EDIT - as requested by OP
Here is the code. I am leaving my original answer to help anyone else who needs this.
volatile bool run;
protected async override void OnAppearing()
{
base.OnAppearing();
BindingContext = vm;
cts = new CancellationTokenSource();
if (Settings.mode == MO.Practice)
{
run = true;
Device.StartTimer(new TimeSpan(0, 1, 0), () =>
{
if (run)
{
if (App.DB.ReducePoints() == true)
Device.BeginInvokeOnMainThread(() =>
{
vm.PifInfo = GetPifInfo();
});
return true;
}
else { return false; }
});
await GetCards(cts.Token);
}
}
protected override void OnDisappearing()
{
run = false;
Unsubscribe();
cts.Cancel();
base.OnDisappearing();
}
With code that opens a new page in an async method, do I need to run that on the main thread and if so how can I do this?
To run code on the UI thread (or the mainthread) you should use the code below which forces the code to run on the MainThread.
Be aware that any async method 'could' have code running in any other thread as Xamarin sees fit.
There are some smart ways for the program to know if your code should run on the MainThread whe using async methods.
If you want to know the full ins and outs please check this article that my manager sent me:
https://devblogs.microsoft.com/dotnet/configureawait-faq/
Xamarin.Forms.Device.BeginInvokeOnMainThread(() =>
{
App.NavigationService.SetAsRoot(nameof(Views.StartPage));
});
For calling async await methods:
Xamarin.Forms.Device.BeginInvokeOnMainThread(async() =>
{
await App.NavigationService.NavigateTo(nameof(Views.StartPage));
});
how to call async method in MainPage
If you don't want to call this in the OnAppearing() method and specifically in the contructor, you can do this (watch out for possible thread blocking though):
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
// watch out for possible thread blocking!
Task.Run(async() =>
{
await Permissions.CheckStatusAsync<Permissions.LocationWhenInUse>();
});
}
}
OnApearing() method is not firing second time in Mater details page of xamarin forms
I used IsPresentedChanged
property. Please check the below code.
public MainMasterDetailPage()
{
InitializeComponent();
NavigationPage.SetHasBackButton(this, false);
NavigationPage.SetHasNavigationBar(this, false);
ListOfSettings.IsVisible = false;
this.IsPresented = false;
Detail = new NavigationPage(new DashboardTabbedPage());
this.IsPresentedChanged += hideSettingMenu;
}
public void hideSettingMenu(object sender, EventArgs args)
{
ListOfSettings.IsVisible = false;
}
Getting initial data pattern in Xamarin Forms
create an Init
method on your VM
public class DataFeedViewModel : BaseViewModel
{
public DateFeedViewModel()
{
Title = "My Feed";
}
public List<FeedItem> Feed { get; set; }
public async void Init()
{
Feed = await _myApiService.GetFeed();
}
}
and then have your page call it
private DataFeedViewModel VM { get; set; }
public MainPage()
{
InitializeComponent();
this.BindingContext = VM = new DataFeedViewModel();
}
protected override async void OnAppearing()
{
base.OnAppearing();
await VM.Init();
}
How can I detect focus on child view inside a Tabbed Page in Xamarin.Forms?
Just like
ToolmakerSteve sayed, the tabbedpage has the CurrentPageChanged event, so you can override the OnCurrentPageChanged()
method of the TabbedPage. Such as:
public partial class TabbedPage1 : TabbedPage
{
public TabbedPage1()
{
InitializeComponent();
}
protected override void OnCurrentPageChanged()
{
if(CurrentPage == Children[0])//Children[0] is the page A
{
....
}else if(CurrentPage == Children[1])//Children[1] is the page B
{
.....
}
else
{
......
}
base.OnCurrentPageChanged();
}
}
OnAppearing() method is performing before calling the OnCurrentPageChanged() method
In Android, onAppearing
is called before OnCurrentPageChanged
while in iOS OnCurrentPageChanged
is called before onAppearing
.
1.As jgoldberger
suggested, you can call method in each Page after CurrentPageChanged
:
override protected void OnCurrentPageChanged()
{
if (this.CurrentPage.Title == "Week")
{
Xamarin.Forms.Application.Current.Properties["weekOnAppear"] = true;
NavigationPage naviPage = this.Children[0] as NavigationPage;
WeekPage page = naviPage.RootPage as WeekPage;
page.test();
}else if (this.CurrentPage.Title == "Month")
{
Xamarin.Forms.Application.Current.Properties["monthOnAppear"] = true;
NavigationPage naviPage = this.Children[1] as NavigationPage;
MonthPage page = naviPage.RootPage as MonthPage;
page.test();
}
else
{
Xamarin.Forms.Application.Current.Properties["dayOnAppear"] = true;
NavigationPage naviPage = this.Children[2] as NavigationPage;
DayPage page = naviPage.RootPage as DayPage;
page.test();
}
base.OnCurrentPageChanged();
}
}
2.You can use messaging-center to notify specific page to perform some actions after CurrentPageChanged
:
override protected void OnCurrentPageChanged()
{
string testStr;
if (this.CurrentPage.Title == "Week")
{
testStr = "Week";
}else if (this.CurrentPage.Title == "Month")
{
testStr = "Month";
}
else
{
testStr = "Day";
}
MessagingCenter.Send<object, string>(new object(), "CurrentPageChanged", testStr);
base.OnCurrentPageChanged();
}
And in each page:
public partial class MonthPage : ContentPage
{
public MonthPage()
{
InitializeComponent();
MessagingCenter.Subscribe<object, string>(new object(), "CurrentPageChanged", async (sender, arg) =>
{
if (arg == "Month")
{
Console.WriteLine(arg);
//do something
}
});
}
public void test() {
Console.WriteLine("test");
//do something
}
}
BTW, you should use if...else if...else
instead of if...if...else
in your control statement.
Related Topics
How to Perform Join Between Multiple Tables in Linq Lambda
How to Correctly Write Parallel.For With Async Methods
How to Change Cell Background Color in Wpf Datagrid
Passing Datetimeoffset as Webapi Query String
Reference External Dll in .Net Core Project
Asp.Net Core, Change Default Redirect for Unauthorized
Kill Child Process When Parent Process Is Killed
Select Distinct by Two Properties in a List
Replace Single Backslash With Double Backslash
Removing Text Between 2 Strings
Get Value from Jtoken That May Not Exist (Best Practices)
Redirect from Controller to Another View of Another Controller
Save Byte[] into a SQL Server Database from C#
How to Count Number of Visitors for Website in ASP.NET C#
How to Get the Am/Pm Value from a Datetime
Cast Class into Another Class or Convert Class to Another