Click on LiveTile doesn't show/run my app - c#

In a background agent I create (or update) one of application live tiles and this works as expected.
Problem is that when I click this live tile screen flickers but my app is not "restarted" nor "shown".
What's wrong?
I attach small part of the code, but ask for more is you need.
MAIN PAGE
public partial class MainPage : PhoneApplicationPage
{
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
}
public MainPage()
{
InitializeComponent();
// Runs background agent: code is simplified
StartAgent();
}
}
BACKGROUND AGENT
public class TileAgent : ScheduledTaskAgent
{
protected override void OnInvoke(ScheduledTask task)
{
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
Vars.UpdateTiles();
});
NotifyComplete();
}
}
STATIC CLASS
public class Vars
{
private static Uri uri = new Uri(
"/MainPage.xaml?tile",
UriKind.RelativeOrAbsolute);
private static RadExtendedTileData ExtendedData
{
get
{
return new RadExtendedTileData()
{
VisualElement = frontTile,
BackVisualElement = backTile,
};
}
}
public static void UpdateTiles()
{
// I perform some task here
// Then I create/update live tile
Telerik.Windows.Controls.LiveTileHelper.CreateOrUpdateTile(
ExtendedData, uri);
}
}

Try /MainPage.xaml?tile=true instead of /MainPage.xaml?tile...
And move NotifyComplete() into the dispatcher call. Otherwise it will be called before the operation has been completed...

Related

Navigation to next page in xamarin forms

Assume that i'm in the Page_1 while click the button have to navigate to Page_2.In Page_2 Api call has to done.
MyIssue is when i'm clicking the Button it doesn't navigate to Page_2 immediately it waits for the API response.
How to Navigate Immediately to Page_2 without waiting for the APi response.
Code:
Page_1.cs
public partial class Page_1 : ContentPage
{
public Page_1()
{
InitializeComponent();
}
private void Btn_click(object sender, EventArgs e)
{
Navigation.PushAsync(new Page_2());
}
}
Page_2:
public Page_2()
{
InitializeComponent();
}
protected override void OnAppearing()
{
HttpClient httpClient = new HttpClient();
var obj = httpClient.GetAsync("//Api//").Result;
if (obj.IsSuccessStatusCode)
{
}
}
Same code works good in iOS as expected
You could load your data in an other Task to prevent blocking the UI.
protected override void OnAppearing()
{
Task.Run( () => LoadData());
base.OnAppearing();
}
private async void LoadData()
{
HttpClient httpClient = new HttpClient();
var obj = await httpClient.GetAsync("//Api//");
if (obj.IsSuccessStatusCode)
{
// If you need to set properties on the view be sure to use MainThread
// otherwise you won't see it on the view.
Device.BeginInvokeOnMainThread(() => Name = "your text";);
}
}
As per your question you are calling the API on Page constructor that's why it's taking time to load web API then navigating on page2. If you want to navigate on page2 before a load the api. Check below code
public partial class Page2 : ContentPage
{
bool IsLoading{ get; set; }
public Page2()
{
InitializeComponent();
IsLoading = false;
}
protected async override void OnAppearing()
{
base.OnAppearing();
if (!IsLoading)
{
IsLoading=true
**Call the Web API Method Here**
}
IsLoading=false
}
}

Consuming a restful web service

I am trying to consume an interface but I am having some difficulty here.
I am trying to set it to a xamrin list view in behind a content page
public class xxxApiClient : IApi
{
readonly string url = "http://localhost:81/ ";
readonly IHttpService httpService;
public xxxApiClient(IHttpService httpService)
{
this.httpService = httpService;
}
public Task<List<JobsList>> GetJobs() => httpService.Get<List<JobsList>>($"{url}JobsLists");
}
How ever I am not to sure how I cosume getjobs correclty I am trying the following
public partial class JobsPage : ContentPage ,xxxWC.Interface.IApi
{
public xxxWC.Interface.IApi api = new ful;
public JobsPage ()
{
InitializeComponent ();
}
private Task SetItemSource()
. {
. JobListing.ItemsSource = FuelAp
}
How do I use the get jobs correctly above in the method setItemSource?.
The bit I am having hard time to understand is here.
How do I call the base GetJobs method I have already created in API Client.
Task<List<JobsList>> IApi.GetJobs()
{
throw new NotImplementedException();
}
private Task SetItemSource()
{
JobListings.ItemsSource =await GetJobs();
}
}
Edit 2
Ok based on suggestions below I updated My Code as such
IHttpService httpService;
xxxApiClient _api = newxxxApiClient(httpService);
public JobsPage ()
{
InitializeComponent ();
}
private Task SetItemSource()
{
JobListings.ItemsSource =await GetJobs();
}
But i get the below error
Severity Code Description Project File Line Suppression State
Error CS0236 A field initializer cannot reference the non-static
field, method, or property
'JobsPage.httpService' xxxCallManagmentAppMobile C:\Work\xxxCallAppDev\XamForms\xxxCallManagmentApp\xxxCallManagmentAppMobile\FuelCallManagmentAppMobile\Views\JobsPage.xaml.cs 17 Active
Can someone explain why
Edit 3
Ok i got a bit further but still having some issues. as the main method is not awaited how do I call set SetItemSource.
xxxApiClient _api ;
public JobsPage ()
{
InitializeComponent ()
SetItemSource();
}
private async Task SetItemSource()
{
JobListings.ItemsSource = await client.GetJobs();
}
Assuming that IApi has been mapped to xxxApiClient implementation
Try resolving the service using the DependencyService so that it is available to be used in the view
public partial class JobsPage : ContentPage {
public readonly IApi client;
public JobsPage () {
InitializeComponent ();
client = DependencyService.Get<IApi>();
}
private async Task SetItemSource() {
JobListing.ItemsSource = await client.GetJobs();
//...
}
}
As for calling the SetItemSource, it is async so should be awaited. That can't be done in the constructor.
Consider creating a event that can be raised and its handler used to await the desired behavior.
private event EventHandler loadingData = delegate { };
private async void onLoadingData(object sender, Eventargs args) {
JobListing.ItemsSource = await client.GetJobs();
}
Full code
public partial class JobsPage : ContentPage {
public readonly IApi client;
public JobsPage () {
InitializeComponent ();
//resolving client
client = DependencyService.Get<IApi>();
//subscribing to event
loadingData += onLoadingData;
//raising event
loadingData(this, EventArgs.Empty);
}
private async Task SetItemSource() {
JobListing.ItemsSource = await client.GetJobs();
//...
}
private event EventHandler loadingData = delegate { };
private async void onLoadingData(object sender, Eventargs args) {
JobListing.ItemsSource = await client.GetJobs();
}
}
Although a custom event was created, you could just as easily used on of the event/eventhandler of the view.
All of that code should actually live inside of a view model and then bound to the view in a binding context.

Update a form in parallel with an installation script?

I currently have an installation "framework" that does specific things. What I need now to do is be able to call my form in parallel with my script. Something like this:
InstallationForm f = new InstallationForm();
Application.Run(f);
InstallSoftware(f);
private static void InstallSoftware(InstallationForm f) {
f.WriteToTextbox("Starting installation...");
Utils.Execute(#"C:\temp\setup.msi", #"-s C:\temp\instructions.xml");
...
f.WriteToTextbox("Installation finished");
The current way I can do this is by adding the Form.Shown handler in InstallSoftware, but that seems really messy. Is there anyway I can do this better?
Your code will not work, because Application.Run(f) returns not until the form was closed.
You may use a simplified Model/View/Controller pattern. Create an InstallationFormController class that has several events, e.g. for textual notifications to be written to your textbox. The InstallationForm registers on these events in it's OnLoad() method and then calls InstallationFormController.Initialize(). That method starts your installation (on a worker thread/task). That installation callback method fires several text events.
InstallationForm f = new InstallationForm(new InstallationFormController());
Application.Run(f);
internal class InstallationFormController
{
public event EventHandler<DataEventArgsT<string>> NotificationTextChanged;
public InstallationFormController()
{
}
public void Initialize()
{
Task.Factory.StartNew(DoInstallation);
}
private void DoInstallation()
{
...
OnNotificationTextChanged(new DataEventArgsT<string>("Installation finished"));
}
private void OnNotificationTextChanged(DataEventArgsT<string> e)
{
if(NotificationTextChanged != null)
NotificationTextChanged(this, e);
}
}
public class DataEventArgsT<T> : EventArgs
{
...
public T Data { get; set; }
}
internal class InstallationForm : Form
{
private readonly InstallationFormController _controller;
public InstallationForm()
{
InitializeComponent();
}
public InstallationForm(InstallationFormController controller) : this()
{
if(controller == null)
throw new ArgumentNullException("controller")
_controller = controller;
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
_controller.NotificationTextChanged += Controller_NotificationTextChanged;
_controller.Initialize();
}
protected virtual void Controller_NotificationTextChanged(object sender, DataEventArgsT<string> e)
{
if(this.InvokeRequired)
{ // call this method on UI thread!!!
var callback = new EventHandler<DataEventArgsT<string>>(Controller_NotificationTextChanged);
this.Invoke(callback, new object[] {sender, e});
}
else
{
_myTextBox.Text = e.Data;
}
}
...
}

Update UI from another GPIOListener class

I'm developing an application with windows-10-t platform on raspberry-pi3. The application has several pages and listens GPIO ports asyncrhonously in the background. It collects data from GPIO and sends to the WCF-Service, after a bit the UI should be updated by the data coming from the WCFService. I've also tried using Tasks, Dispatcher.Invoke etc. but nothing worked properly. I can collect data coming from GPIO but cannot update UI. What am I doing wrong?
Here is the background GPIO listener class with static variables (I'm listening GPIO in other pages too.):
public sealed class GPIO{
private static MainPage mainpage;
public static event EventHandler ProgressUpdate;
public static void InitGPIO(MainPage sender)
{
mainpage = sender;
DataPin.DebounceTimeout = TimeSpan.FromMilliseconds(50);
DataPin.ValueChanged += DataPin_ValueChanged;
}
public static void DataPin_ValueChanged(GpioPin sender, GpioPinValueChangedEventArgs e)
{
if (e.Edge == GpioPinEdge.FallingEdge)
{
Task.Run(() => AddData(0));
}
}
public static async void AddData(int prm_Data)
{
// WCF-Service Operation
await Service.wsClient.GPIOValueAddition(prm_Data);
GPIO.ProgressUpdateOperation();
}
private static void ProgressUpdateOperation()
{
mainpage.GPIO_ProgressUpdate(typeof(GPIO), new EventArgs());
}
}
And here is the page that contains the UI to be updated:
public sealed partial class MainPage : Page
{
public MainPage()
{
GPIO.InitGPIO(this);
GPIO.ProgressUpdate += GPIO_ProgressUpdate;
}
public void GPIO_ProgressUpdate(object sender, EventArgs e)
{
// WCF-Service Operation
service_data = (int)Service.wsClient.GetDataFromServicetoUpdateUI(parameter).Result;
// UI-update
txtUpdate.Text = service_data.ToString();
}
}
EDIT: I forgot to add the exception. "The application called an interface that was marshalled for a different thread. (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD))" exception is thrown at AddData function called in DataPin_Valuechanged.
I found the solution in here : https://stackoverflow.com/a/27698035/1093584
Here is the new update-UI function :
public void GPIO_ProgressUpdate(object sender, EventArgs e)
{
await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
{
service_data = await Service.wsClient.GetDataFromServicetoUpdateUI(parameter);
// UI-update
txtUpdate.Text = service_data.ToString();
});
}

How do i call async function xamarin

I'm trying to call an async function but when I try and do it it has the red line underneath it. I want the function to be called when the page is opened, thanks in advance.
public partial class Home : ContentPage
{
public class GoogleProfile
{
public string Id { get; set;}
}
public Home()
{
InitializeComponent();
}
protected override async void OnAppearing()
{
await Check(/*What do i put in here*/);
}
public async Task Check(GoogleProfile googleprofile)
{
if (String.IsNullOrEmpty(googleprofile.Id))
{
}
else {
await Navigation.PushAsync(new LoginPage());
}
}
}
how would i call this? Sorry im new to C# and xamarin
You should make your async calls in ContentPage.OnAppearing(). The OnAppearing() event will be called, as the name suggest, right when your page is being displayed. This is the expected behavior by the user. Also note that I changed your Check() method to return Task because, if you are able to edit the method signature, always try to change the return type of async methods from void to Task:
public partial class LoginPage : ContentPage {
public LoginPage() {
InitializeComponent();
}
protected override async void OnAppearing() {
await Check(/* Add code here to get your GoogleProfile object */);
}
public async Task Check(GoogleProfile googleprofile) {
var ID = googleprofile.Id;
if (string.IsNullOrEmpty(ID)) {
return;
} else {
await Navigation.PushAsync(new Home());
}
}
}
Technically, if you are dead set to not use OnAppearing() you could do the Check() before pushing your LoginPage, though without seeing more code, that would seem like it would defeat the purpose of the LoginPage.

Categories

Resources