Xamarin OnLaunched event - c#

I'm looking to create styles (and eventually some of the pages) using C# code behind. Was looking at the write up on https://learn.microsoft.com/en-us/windows/apps/design/style/xaml-resource-dictionary and when I duplicate that code it gives me an error that LaunchActivatedEventArgs is unknown.
My starting App.xaml.cs file:
using System;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace FieldDataTemplateSelectorSample
{
sealed partial class App : Application
{
public App()
{
InitializeComponent();
MainPage = new MainPage();
}
protected override void OnStart()
{
}
protected override void OnSleep()
{
}
protected override void OnResume()
{
}
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
// add styles here
}
}
}
It doesn't know the type or namespace for LaunchActivatedEventArgs. If I look at the list of potential fixes, it suggests that I add a using for Windows.ApplicationModel.Activation to the list of usings. If I do that, then it complains about OnLaunched not having a suitable method to override. If I take out the override, and change the signature to
using System;
using Windows.ApplicationModel.Activation;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using FieldDataTemplateSelectorSample.AppStyles;
namespace FieldDataTemplateSelectorSample
{
public partial class App : Application
{
public App()
{
InitializeComponent();
MainPage = new MainPage();
}
protected override void OnStart()
{
}
protected override void OnSleep()
{
}
protected override void OnResume()
{
}
protected void OnLaunched(LaunchActivatedEventArgs e)
{
Resources = InitStyles.GetAppStyles();
}
}
}
The application compiles but the OnLaunched method never gets hit if I put a break point in there. What am I missing? Right now I'm using a UWP project for getting my feet wet, and eventually will add android and ios.
Thanks

OnLaunched is a Windows or UWP API, not a Xamarin API.
Put your code in OnStart instead.
For cross-platform code, find "Windows.Forms" docs, instead of "Windows App Development" docs.
OR sometimes you'll want code in your .UWP or .Windows project - but I don't think this is one of those situations.

Related

How to update a "label" in ViewController.cs from another C# file in Xamarin MacOS development?

I am working on a small MacOS app in Xamarin and using 'Visual Studio for MAC'. I am unable to figure out how to update the value of a label in the ViewController.cs file from another .cs file.
using System;
using AppKit;
using Foundation;
namespace FramesMac
{
public partial class ViewController : NSViewController
{
public ViewController(IntPtr handle) : base(handle)
{
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
// Do any additional setup after loading the view.
lbl_message.StringValue="Processing..."
}
public override NSObject RepresentedObject
{
get
{
return base.RepresentedObject;
}
set
{
base.RepresentedObject = value;
// Update the view, if already loaded.
}
}
}
}
I simply want to update lbl_message.StringValue="Processing..." from another .cs file.
The easiest way in my knowledge would be using Actions, first create a method:
private void SetLabelText(string Text)
{
lbl_message.StringValue=Text;
}
Now pass the reference of this method to the next class using actions through the constructor:
public AnotherClass(Action<string> MyLabelCallback)
make an instance of it from the viewController like:
new AnotherClass(SetLabelText);
After getting it you can just call this method and pass a string to set the new text:
MyLabelCallback("Boom");

Xamarin Forms - Prism - OnNavigatedTo Calling Twice

So, I've been developing an App for 2 months with prism, and just now I've realized that the method OnNavigatedTo is been calling twice when I select an Item from a MasterDetailPage.
I have no clue why it is happening, I'm sure I'm missing something but I'm about two days trying to solve it.
I'll put some code here, and if u guys need more info I can post more detailed.
Observation: When I'm in the page "A" and I choose the page "A" in the master detail item list, the OnNavigatedTo is called only once, but when I'm in Page "B" and I choose the page "A", The OnNavigatedTo is called twice.
Since now, Thank you guys and sorry about the ignorance.
MasterDetailPage MVVM:
public class PrincipalMasterDetailPageViewModel : ViewModelBase {
public ObservableCollection<PrincipalMasterPageItem> MenuItems { get; set; }
public PrincipalMasterDetailPageViewModel(INavigationService navigationService) : base(navigationService)
{
MenuItems = new ObservableCollection<PrincipalMasterPageItem>();
}
public async override void OnNavigatedTo(NavigationParameters parameters) {
base.OnNavigatedTo(parameters);
.. Here I'm calling an API, thats why I have the async
}
}
Custom Navigation Page MVVM:
public class PrincipalNavigationPageViewModel : ViewModelBase {
public PrincipalNavigationPageViewModel(INavigationService navigationService) : base(navigationService) {
}
}
The Page that I actually show when I select an item in masterdetailpage item list:
public class NewPageTestViewModel : ViewModelBase
{
public NewPageTestViewModel(INavigationService navigationService) : base(navigationService)
{
}
public override void OnNavigatedTo(NavigationParameters parameters)
{
base.OnNavigatedTo(parameters);
Debug.WriteLine("Calling twice HERE!");
}
}
The RegisterTypes of these three examples:
containerRegistry.RegisterForNavigation<PrincipalMasterDetailPage>();
containerRegistry.RegisterForNavigation<PrincipalNavigationPage>();
containerRegistry.RegisterForNavigation<NewPageTest>();
How do I call other pages from PrincipalMasterDetailPageViewModel:
NavigationService.NavigateAsync(string.Format("PrincipalNavigationPage/{0}", item.TargetPageName));
In App.cs I start like the following because I need the login page first:
protected override async void OnInitialized()
{
InitializeComponent();
await NavigationService.NavigateAsync("LoginPage");
}
When the user log in, It navigate like this:
await NavigationService.NavigateAsync("/PrincipalMasterDetailPage/PrincipalNavigationPage/WhateverPageIWantTo");
I don't know if anybody is still interested in this but I ran into the same issue and figured out what is going on.
All code samples I found register a NavigationPage like this:
containerRegistry.RegisterForNavigation<NavigationPage>("Navigation");
In order to be able to do something like this on app launch:
NavigationService.NavigateAsync($"Main/Navigation/Home");
However, the problem seems to be that when this NavigationPage is instantiated without a specific ViewModel assinged to it, the 'INavigationAware' events are somehow propagated to the MasterDetailPage's ViewModel resulting in the events on that one to be called twice.
I fixed it by registering the NavigationPage for Navigation with a ViewModel like this:
containerRegistry.RegisterForNavigation<NavigationPage, NavigationPageViewModel>("Navigation");
The ViewModel itself is nothing special:
using Prism.Commands;
using Prism.Mvvm;
using Prism.Navigation;
using System;
using System.Collections.Generic;
using System.Linq;
using Unity.Attributes;
namespace SocialRecipe.ViewModels
{
public class NavigationPageViewModel : ViewModelBase
{
public NavigationPageViewModel()
{
}
public override void OnNavigatedFrom(INavigationParameters parameters)
{
}
public override void OnNavigatedTo(INavigationParameters parameters)
{
}
public override void OnNavigatingTo(INavigationParameters parameters)
{
}
}
}
This way the events of the NavigationPage are routed to the NavigationPageViewModel and are no longer propagated to the MasterDetailPageā€¦
I've noticed some inconsistent results with Prism as well from a previous project. If you are only seeing it now and it worked previously I would try and backtrack to see if the version you used was different.
https://github.com/PrismLibrary/Prism/issues

Caliburn.Micro Xamarin.Forms ViewModel does not initialize

I created a new Xamarin.Forms project and I'm having issues with the view model initializing. Nothing happens. I'm using the samples from the Features. I modified the sample code to the following:
public FormsApp(SimpleContainer container)
{
//...
DisplayRootView<ConductorView>();
}
This works as expected, but on my project it simply does not work.
I am using .NET Standard 1.5 (not sure if this is causing the issue). In any case here is my code
App.cs:
using System;
using Caliburn.Micro;
using Caliburn.Micro.Xamarin.Forms;
using UniversalSqlManager.ViewModels;
using Xamarin.Forms;
using INavigationService = Caliburn.Micro.Xamarin.Forms.INavigationService;
using UniversalSqlManager.Views;
namespace UniversalSqlManager
{
public class App : FormsApplication
{
private readonly SimpleContainer container;
public App(SimpleContainer container)
{
this.container = container;
container
.PerRequest<ShellViewModel>();
this.DisplayRootView<ShellView>();
}
protected override void PrepareViewFirst(NavigationPage navigationPage)
{
container.Instance<INavigationService>(new NavigationPageAdapter(navigationPage));
}
}
}
ShellView.xaml:
<?xml version="1.0" encoding="utf-8"?>
<TabbedPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:UniversalSqlManager"
x:Class="UniversalSqlManager.Views.ShellView"
xmlns:cm="clr-namespace:Caliburn.Micro.Xamarin.Forms;assembly=Caliburn.Micro.Platform.Xamarin.Forms"
ItemsSource="{Binding Items}"
SelectedItem="{Binding ActiveItem, Mode=TwoWay}"
Title="Universal SQL Manager">
<TabbedPage.ItemTemplate>
<DataTemplate>
<ContentPage Title="{Binding DisplayName}" cm:View.Model="{Binding}" />
</DataTemplate>
</TabbedPage.ItemTemplate>
</TabbedPage>
ShellView.xaml.cs:
using Xamarin.Forms;
namespace UniversalSqlManager.Views
{
public partial class ShellView
{
public ShellView()
{
InitializeComponent();
}
}
}
ShellViewModel.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using Caliburn.Micro;
using Caliburn.Micro.Xamarin.Forms;
using UniversalSqlManager.ViewModels.Interfaces;
namespace UniversalSqlManager.ViewModels
{
public class ShellViewModel : Conductor<ITabItem>.Collection.OneActive
{
protected override void OnInitialize()
{
//both view models implement ITabItem (which has no methods) and inherit form Screen
Items.Add(new ServersViewModel());
Items.Add(new SettingsViewModel());
ActivateItem(Items[0]);
}
}
}
I'll show iOS as that's the first platform I'm testing on
AppDelegate.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using Caliburn.Micro;
using Foundation;
using UIKit;
namespace UniversalSqlManager.iOS
{
[Register(nameof(AppDelegate))]
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
{
private readonly CaliburnAppDelegate appDelegate = new CaliburnAppDelegate();
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
global::Xamarin.Forms.Forms.Init();
LoadApplication(IoC.Get<App>());
return base.FinishedLaunching(app, options);
}
}
}
CaliburnAppdelegate.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Caliburn.Micro;
using UniversalSqlManager.ViewModels.Interfaces;
namespace UniversalSqlManager.iOS
{
public class CaliburnAppDelegate : CaliburnApplicationDelegate
{
private SimpleContainer container;
public CaliburnAppDelegate()
{
Initialize();
}
protected override void Configure()
{
container = new SimpleContainer();
container.Instance(container);
container.Singleton<App>();
container.Singleton<IEventAggregator, EventAggregator>();
}
protected override void BuildUp(object instance)
{
container.BuildUp(instance);
}
protected override IEnumerable<object> GetAllInstances(Type service)
{
return container.GetAllInstances(service);
}
protected override object GetInstance(Type service, string key)
{
return container.GetInstance(service, key);
}
}
}
So when I run this the ShellView UI shows up, but the ShellViewModel does not get initialized and I get no tabs. Even if I switch to SettingsView or ServersView, the corresponding view models never get initialized. What am I doing wrong? This is my first time with Caliburn Micro on Xamarin.Forms. I've used WPF in the past without issues. Just the documentation is confusing, because it just seems like we have these examples to go by and some blogs that aren't as detailed as the WPF documentation. Any help would be appreciated. I can post my csproj and project.json if that will help too, but I'm hesitant to switch the project type as it was a pain to set that up. I guess another alternative would be to create a new project with a PCL and see if that works? Running out of ideas. Any help is appreciated!
So it turns out the problem was that I was not telling the framework which assemblies to use. The Features samples don't use libraries for the share code. So I added this to CaliburnAppDelegate.cs and to Application.cs to iOS and Android respectively:
protected override IEnumerable<Assembly> SelectAssemblies()
{
return this.GetAssemblies();
}
This is an extension I created in my class library:
public static class Bootstrapper
{
//...
public static IEnumerable<Assembly> GetAssemblies(this object o)
{
IEnumerable<Assembly> assemblies =
new[]
{
o.GetType().GetTypeInfo().Assembly,
typeof(ShellViewModel).GetTypeInfo().Assembly
};
return assemblies;
}
//...
}
and this solves the problem. I hope this help someone else who is having issues hooking up the sample using a class library. By the way I figured this out when comparing with the setup samples.

Simple Prism Bootstrapper

im currently porting my program to using Prism 6, it's a WPF application.
So i installed Prism.Unity (6.1.1) which came with Prism.Wpf (6.1.0), Prism.Core (6.1.0), Unity (4.0.1) and CommonServiceLocator (1.3.0).
Then i came along those PRISM samples, but for the love of god i can't get it to run.
Here's my Bootstrapper:
public class Bootstrapper : Prism.Unity.UnityBootstrapper
{
/// <exception cref="ActivationException">If there are errors resolving the shell instance.</exception>
protected override DependencyObject CreateShell()
{
return Container.Resolve<Shell>();
}
protected override void InitializeShell()
{
base.InitializeShell();
Application.Current.MainWindow = (Window)this.Shell;
Application.Current.MainWindow.Show();
}
protected override void ConfigureContainer()
{
base.ConfigureContainer();
this.RegisterTypeIfMissing(typeof(IWorkRepository), typeof(WorkRepository), true);
}
}
Unfortunately i can't start it. VS 2015 says it needs System.Runtime to run
return Container.Resolve<Shell>();
but once added the whole class is marked as error. If i start it directly i get the exception it couldn't load Microsoft.Practices.ServiceLocation.
I'm wondering of the dependency since several posts (including ms) suggests to remove all Practices.*.
Help would be really appreciated, since i can't get it to run. :(
What usings do you use?
The whole bootstrapper can be as simple as this (created by the Prism-template):
using Microsoft.Practices.Unity;
using Prism.Unity;
using PrismUnityApp2.Views;
using System.Windows;
namespace PrismUnityApp2
{
class Bootstrapper : UnityBootstrapper
{
protected override DependencyObject CreateShell()
{
return Container.Resolve<MainWindow>();
}
protected override void InitializeShell()
{
Application.Current.MainWindow.Show();
}
}
}
and System.Runtime isn't needed as reference. Probably you inadvertently use a namespace from that (instead of Microsoft.Practices.Unity where the Container.Resolve<> extension is).

How does one use ManagementEventWatcher to keep track of suspend/resume?

I am trying to use ManagementEventWatcher in a service to keep track of when a computer goes in and out of sleep mode. I am new to .NET and C# so I am struggling quite a bit to come up with syntax to make this work.
I have found a blog post that details how he used ManagementEventWatcher to keep track of this status, but he did not post up his entire code. I am trying to go through and make a simple service that creates a .txt log file stating that the computer has been suspended/resumed but am running into problems with the namespaces and types.
Here is the code to the service.cs file:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Management;
namespace SleepNotifierService
{
public class WqlEventQuery : EventQuery { }
public partial class Service1 : ServiceBase
{
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
WqlEventQuery query = new WqlEventQuery("Win32_PowerManagementEvent");
_watcher = new ManagementEventWatcher(query);
_watcher.EventArrived += new EventArrivedEventHandler(watcher_EventArrived);
_watcher.Start();
}
protected override void OnStop()
{
_watcher.Stop();
}
void watcher_EventArrived(object sender, EventArrivedEventArgs e)
{
try
{
int eventType = Convert.ToInt32(e.NewEvent.Properties["EventType"].Value);
switch (eventType)
{
case 4:
Sleep();
break;
case 7:
Resume();
break;
}
}
catch (Exception ex)
{
//Log(ex.Message);
}
}
public void Sleep()
{
}
public void Resume()
{
}
}
}
Again, this is the first time that I am programming with .NET and C# so I apologize for my ignorance.
I am getting namespace errors such as:
The type or namespace name
'ManagementEventWatcher' could not be
found (are you missing a using
directive or an assembly reference?)
Thanks,
Tomek
You need the System.Management namespace, which is included in the code sample provided by you. I believe you need to reference the System.Management library in your project settings. Follow the following steps to do this( I am assuming you are suing Visual Studio):
Go to the Solution Explorer, and expand your project, right click on the References folder/option and select Add References from the context menu. Now select the .Net tab and select the System.Management from the list and click OK.

Categories