How save session storage in Xamarin Forms? - xamarin.forms

i want to create data to all the application
using static System.Net.Mime.MediaTypeNames;
public class Session
{
void btnLoginClick()
{
NombreUsuario = Username.Text;
Application.Current.Properties["name"] = NombreUsuario;
Application.Current.Properties["IsLoggedIn"] = true;
}
}
i have this error
'MediaTypeNames.Application' does not contain a definition for 'Current'
My app:
namespace Dinamic.Trailer.Mobile.Forms
{
public partial class App : Application
{
public App()
{
Locator.ConfigureIoC();
InitializeComponent();
}
protected override async void OnStart()
{
await InitNavigation();
}
//onsleep()//OnStart
private Task InitNavigation()
{
var navigationService = Content.Resolve<MainNavigation>();
return navigationService.InitializeAsync();
}
}
}

Remove this line
using static System.Net.Mime.MediaTypeNames;
And use import the using Xamarin.Forms;
After that you can use Application.Current.Properties["key"] = value;

Use using xamarin.forms namespace while you use Application.Current.Properties for storing data. Either you could use App.Current.Properties if you do not want to add xamarin.forms namespace in your cs file.
Here App refer your App class in App.xaml.cs which inherit from Xamarin.forms.Application. so you can use App.Current.Properties instead Application.Current.Properties.
Thank you.

Related

dependency injection via container

In Xamarin.Forms I have a simple container (of AutoFac, but it can be any other container) with only 2 mappings:
static class BootStrap
{
public static IContainer Configure()
{
var builder = new ContainerBuilder();
builder.RegisterType<MainPageViewModel>().As<IMainPageViewModel>().SingleInstance();
builder.RegisterType<MainPage>().As<IMainPage>().SingleInstance();
return builder.Build();
}
}
This is the MainPage class, which includes a ctor, with an IMainPageViewModel parameter:
public partial class MainPage : ContentPage, IMainPage
{
private IMainPageViewModel _mainPageViewModel;
public MainPage(IMainPageViewModel mainPageViewModel)
{
InitializeComponent();
_mainPageViewModel = mainPageViewModel;
}
}
This is the MinPageViewModel class:
public class MainPageViewModel : INotifyPropertyChanged, IMainPageViewModel
{
}
In order to establish the mappings I use this App class
public App()
{
InitializeComponent();
MainPage = new NiceMasterDetailPage();
BootStrap.Configure();
}
The error I get is that I don't have a default ctor for MainPage, but I don't want to use the default ctor for MainPage.
I want to use a ctor which has an interface as its parameter - this is how Dependency Injection should work. Does someone have an idea how to overcome this problem?
Resolve the desired page via the container instead of trying to initialize it manually
//...
IContainer container;
public App() {
InitializeComponent();
container = BootStrap.Configure();
MainPage = container.Resolve<MainPage>();
}
//...
That way the container will inject any dependencies of the type being resolved

SqliteConnection Xamarin forms Exception Unhandled?

When i try to run the project, i am getting this kind of error: "System.NullReferenceException: Object reference not set to an instance of an object"
pointing in this code:
sqliteconnection = DependencyService.Get().GetConnection();
This is my Class for DB actions:
namespace DevoApp.DevoAppFinal.Helpers
{
public class DatabaseHelper
{
static SQLiteConnection sqliteconnection;
public const string DbFileName = "Devotion.db";
public DatabaseHelper()
{
sqliteconnection = DependencyService.Get<ISQLite>().GetConnection();
sqliteconnection.CreateTable<Devotion>();
}
// Get All Contact data
public List<Devotion> GetAllDevotionsData()
{
return (from data in sqliteconnection.Table<Devotion>() select data).ToList();
}
//Get Specific Contact data
public Devotion GetDevotionData(int id)
{
return sqliteconnection.Table<Devotion>().FirstOrDefault(t => t.devotionalId == id);
}
// Delete all Contacts Data
public void DeleteAllDevotions()
{
sqliteconnection.DeleteAll<Devotion>();
}
// Delete Specific Contact
public void DeleteDevotion(int id)
{
sqliteconnection.Delete<Devotion>(id);
}
// Insert new Contact to DB
public void InsertDevotion(Devotion contact)
{
sqliteconnection.Insert(contact);
}
// Update Contact Data
public void UpdateDevotion(Devotion contact)
{
sqliteconnection.Update(contact);
}
}
}
When using the DependencyService, you have to implement the interface in each targeted platform project.
In this case, you should have the ISQLite interface implemented on the platforms you're targeting, i.e. iOS and Android.
To make Xamarin find it at runtime, you will have to register the implementation with the Dependency attribute above the namespace. Observe the following example based on a few assumptions of your project.
In your shared library you have declared the interface:
public interface ISQLite
{
// Members here
}
Nothing fancy going on there. Then for each platform, you want to run the app on, do something like this:
[assembly: Xamarin.Forms.Dependency (typeof (SQLiteImplementation_iOS))]
namespace DevoApp.DevoAppFinal.iOS
{
public class SQLiteImplementation_iOS : ISQLite
{
// ... Your code
}
}
From the error, it looks like you forgot to add the attribute

Xamarin Forms overriding OnAppearing causes app to crash

I am trying to do a simple override and load some data when my page loads, I am using the following code in the code behind page.
namespace XYZ
{
public partial class MainPage : ContentPage
{
private Label results;
private Label groupResults;
public MainPage()
{
InitializeComponent();
results = new Label();
groupResults = new Label();
}
protected override void OnAppearing()
{
base.OnAppearing();
storeIdTxt.Text = Settings.StoreIdSetting;
}
}
}
If I uncomment the override things works just fine, the error I am getting seems to be a generic one attached here
my settings class is fairly simple as follows
using System;
using System.Collections.Generic;
using System.Text;
using Plugin.Settings;
using Plugin.Settings.Abstractions;
namespace NWMPosNG.Helpers
{
/// <summary>
/// This is the Settings static class that can be used in your Core solution or in any
/// of your client applications. All settings are laid out the same exact way with getters
/// and setters.
/// </summary>
public static class Settings
{
private static ISettings AppSettings
{
get
{
return CrossSettings.Current;
}
}
#region Setting Constants
private const string SettingsKey = "settings_key";
private static readonly string SettingsDefault = string.Empty;
private const string StoreId = null;
private static readonly string StoreIdDefault = "0";
#endregion
public static string GeneralSettings
{
get
{
return AppSettings.GetValueOrDefault(SettingsKey, SettingsDefault);
}
set
{
AppSettings.AddOrUpdateValue(SettingsKey, value);
}
}
public static string StoreIdSetting
{
get
{
return AppSettings.GetValueOrDefault(StoreId, StoreIdDefault);
}
set
{
AppSettings.AddOrUpdateValue(StoreId, value);
}
}
}
}
I narrowed down the issue to when I access the saved data using
storeIdTxt.Text = Settings.StoreIdSetting;
But I don't understand why that causes the crash.
You are using the Settings Plugin from James Montemagno. Which is pretty much a KeyValuePair that is stored on the local device across sessions.
In your case:
AppSettings.GetValueOrDefault(StoreId, StoreIdDefault);
Translates to:
AppSettings.GetValueOrDefault(null, "0");
Which crashes because 'null' can't be a key. That's why setting the key (StoreId) prevents the crash from happening.
This line was the culprit
private const string StoreId = null;
I don't really understand why but setting this to a non NULL value makes the crash go away

Change default session provider in ASP.NET

I want to change my session proviced to statically typed - I just hate typing strings because of many many errors I do.
What technology am I using? ASP.NET MVC via EXT.NET MVC
I was trying to do that using web.config but the problem is that after add session state to it visual is not going to compile my code because of that session should be using strings as keys.
I want to use session by enums such as :
public enum SessionEnum{Model}
public class Bar{
void foo(){
Session[SessionEnum.Model] = "blah";
}
}
I am aware that I can create wrapper converting enums to strings but it's not very satisfying solution for me.
public class StorageWrapper{
public object this[SessionEnum enum]{ get{return Session[enum.toString()]}; //+set
}
What I did was create static object for base class for all of my controllers and then I was able to use it across them but after closing and opening the page again I wasn't able to get values from it. I guess I should serialize them somehow but I have no idea how.
Is there any way to do that?
EDIT
My session now looks like this :
[Serializable]
public abstract class DataWrapper<T> : HttpSessionStateBase
{
Dictionary<T, object> Dictionary { get; set; } = new Dictionary<T, object>();
public object this[T a]
{
get
{
try
{
return Dictionary[a];
}
catch
{
return null;
}
}
set { Dictionary[a] = value; }
}
}
[Serializable]
public class SessionWrapper : DataWrapper<SessionNames>
{}
public enum SessionNames { Model, Login, LastOpenedFile }
It's very simple.
Create a UserSession object which does everything you want (holds your values as enum etc), instantiate it, then put it in the session.
var US = new UserSession();
US.stuff = somestuff;
Session["UserSess"] = US
Then you can just always use Session["UserSess"].stuff;
Mmmm, wouldn't you use static const string instead of an enum?
using System.Web;
public static class SessionEnum
{
public static const string Model = "_Session_Model";
public static const string Login = "_Session_Login";
public static const string LastOpenedFile = "_Session_LastOpenedFile ";
}
class test
{
void test()
{
Session[SessionEnum.Model] = "blah";
}
}

Set Up INavigation with Xamarin.Forms and MVVMLight IOC

I am beginning using MVVMLight with Xamarin.Forms and need some help to get the IOC set up to create my first ContentPage in App.GetMainPage.
My ViewModels have constructors like so -
public class NewsType1ViewModel : ViewModelBase
{
private readonly IContentService contentService;
private readonly INavigation navigation;
public List<ContentModel> ContentModels { get; set; }
public NewsType1ViewModel (INavigation navigation, IContentService contentService)
{
this.contentService = contentService;
this.navigation = navigation;
}
My ContentPages have constructors like so -
public partial class NewsType1CP : ContentPage
{
private NewsType1ViewModel vm;
public NewsType1CP (NewsType1ViewModel vm)
{
InitializeComponent ();
I am using a ViewModelLocator class as follows -
public class ViewModelLocator
{
public ViewModelLocator ()
{
ServiceLocator.SetLocatorProvider (() => SimpleIoc.Default);
// Services
if (App.StubMode) {
SimpleIoc.Default.Register<IContentService, ContentServiceStub> ();
} else {
SimpleIoc.Default.Register<IContentService, ContentService> ();
}
// How do I wire up INavigation?
// I could not just register default NavigationPage() as it has 2
// possible constructors so tried [PreferredConstructor] on my derived class
SimpleIoc.Default.Register<INavigation, AppNavigationPage> ();
// View Models
SimpleIoc.Default.Register<NewsType1ViewModel> ();
SimpleIoc.Default.Register<NewsDetailsViewModel> ();
}
public NewsType1ViewModel NewsType1ViewModel {
get {
return ServiceLocator.Current.GetInstance<NewsType1ViewModel> ();
}
}
public NewsDetailsViewModel NewsDetailsViewModel {
get {
return ServiceLocator.Current.GetInstance<NewsDetailsViewModel> ();
}
}
public static void Cleanup ()
{
// TODO Clear the ViewModels
}
}
public class AppNavigationPage : NavigationPage
{
[PreferredConstructor]
public AppNavigationPage ()
{
}
}
My App.cs is "in progress" as follows -
public static class App
{
public static AppNavigationPage Nav;
public static ViewModelLocator Locator = new ViewModelLocator ();
public static bool StubMode = true;
public static Page GetMainPage ()
{
try {
// Want to return a Nav with NewsType1CP as the starting Page
NewsType1CP newsType1CP = new NewsType1CP(ServiceLocator.Current.GetInstance<NewsType1ViewModel> ());
Nav.PushAsync (newsType1CP);
return Nav;
} catch (Exception ex) {
//
Exception baseexception = ex.GetBaseException ();
Debug.WriteLine (baseexception.Message);
}
return null;
}
}
My latest exception is -
Cannot cast from source type to destination type.
Am I barking up the wrong tree trying to supply an INavigation to each of my ViewModels like so?
Update: After a couple of answers showing other ways of controlling the Navigation in Xamarin Forms, I think it would help if someone could clarify why attempting constructor injection for Navigation is not such a good thing.
I think my example is a bit confusing with AppNavigationPage as a static, ideally I would like this to be in the IOC also, so I could just call return ServiceLocator.Current.GetInstance< AppNavigationPage >(), but I had a go with various factory methods and am in the middle of debugging this, so the code is obviously half baked ...
If you want a ready to use solution, instead of MVVM Light, you could try to use Xamarin Forms Labs ViewModel base, it injects a Navigation propety in your ViewModel:
that way you cold do something like this:
public Command NavigateToViewModel
{
get
{
return navigateToViewModel ?? (navigateToViewModel = new Command(
async () => await Navigation.PushAsync<NewPageViewModel>(),
() => true));
}
}
I'm not using MvvmLight, but I can tell you that yes, you're barking up the wrong tree in trying to supply an INavigation to each ViewModel.
The easiest way to achieve what you're trying to do is to use a public static on your App.
public static INavigation Navigation
{
get;
set;
}
public static Page GetMainPage()
{
var firstPage = new NavigationPage(new MyRootPage())
{
Navigation = firstPage.Navigation;
return firstPage;
}
}
Now this falls apart when you're using a MasterDetail page because you need your Navigation to wrap your DetailPage, not your MasterDetailPage. Therefore, don't set Navigation in the GetMainPage method, but instead from within the MD Page.
var master = new MainMenuPage();
var detail = new NavigationPage(new FirstPage());
if (App.Navigation == null)
{
App.Navigation = detail.Navigation;
}
Master = master;
Detail = detail;
Oh ok, when looking better at your code i maybe spotted the problem:
SimpleIoc.Default.Register<INavigation, AppNavigationPage> ();
Shoult it be:
SimpleIoc.Default.Register<INavigation, AppNavigationPage.Navigation> ();

Resources