Windows Phone- How to set LocalSettings first time? - c#

In Desktop Application or Web Projects projects there were App.configs and Web.configs files to store settings. These settings were set in development time (or whenever later) but if this occures, it was ALWAYS once action.
In Windows Phone 8.1 XAML there isn't any App.config file, so developers are able to use Windows.Storage.ApplicationData.Current.LocalSettings. Nice.
How can I set these settings first time (this means on first application run ever, so I can later only read them and sometimes update existing values)? Of course I can set settings whenever I run application but this is time wasting. How do you set LocalSettings in you applications first time? I saw this solution Is there a "first run" flag in WP7 but I don't think so, that this is the only possibility.

var localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;
// Create a simple setting
localSettings.Values["exampleSetting"] = "Hello Windows";
// Read data from a simple setting
Object value = localSettings.Values["exampleSetting"];
if (value == null)
{
// No data
}
else
{
// Access data in value
}
// Delete a simple setting
localSettings.Values.Remove("exampleSetting");
Msdn Reference
Persistance of Data

I have written code:
public void Initialize()
{
var localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;
if (!localSettings.Values.ContainsKey(FirstRunSettingName))
{
localSettings.Values.Add(FirstRunSettingName, false);
}
localSettings.Values.Add(SettingNames.DataFilename, "todo.data.xml");
}
public bool IsFirstRun()
{
var localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;
if (localSettings.Values.ContainsKey(FirstRunSettingName))
{
return (bool)localSettings.Values[FirstRunSettingName];
}
else
{
return true;
}
}
In the App.xaml.cs file:
public App()
{
this.InitializeComponent();
this.Suspending += this.OnSuspending;
var storageService = Container.Get<ISettingsService>();
if (storageService.IsFirstRun())
{
storageService.Initialize();
}
}
I'm not sure this is proper way to set settings first time, but it is some soultion.

Related

Prevent file association from opening the app again

I develop a wpf app and i associated a file type named .fcsc. The application opens when the file is doubled clicked but it execute a new instance of the app. What i want is that if the app is already running, open the file in that instance not in a new one.
How can i archive that?
This is what i have when a file is open:
if (AppDomain.CurrentDomain.SetupInformation != null
&& AppDomain.CurrentDomain.SetupInformation.ActivationArguments != null
&& AppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData != null &&
AppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData.Any())
{
// is a file association invoke, open the window
InstallPluginWindow installPluginWindows = new InstallPluginWindow(AppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData);
installPluginWindows.Show();
installPluginWindows.Owner = this;
this.Opacity = 0.5;
this.IsEnabled = false;
installPluginWindows.WindowStartupLocation = System.Windows.WindowStartupLocation.CenterOwner;
installPluginWindows.Closed += installPluginWindows_Closed;
}
else
{
NegotiateLogin();
}
The easy part is setting up a mutex to check for another instance. In your app main or startup code you waould need to so something like the code below:
bool exclusive;
System.Threading.Mutex appMutex = new System.Threading.Mutex(true, "MyAppName", out exclusive);
if (!exclusive)
{
//Another instance running
} ...
GC.KeepAlive(appMutex);
Next, you need to implement a way to message the first application instance and pass in the filename that was double clicked. You can do this in many ways, however, sending a custom message to the main window seems to be the most straightforward. Here is an alternative to message another application.

How to locate the correct Service Endpoint Uri

I am working on an application which is deployed to a TEST and then a LIVE webserver.
I want the class library I am working on to use the correct service endpoint when it is deployed.
Currently the code is as follows;
var data = new SettingsViewModel()
{
ServiceURI = Constants.LIVE_ENDPOINT_SERVICE_ADDRESS,
AutoSync = Constants.DEFAULT_AUTO_SYNC,
AppDataFolder = Path.Combine(ApplicationData.Current.LocalFolder.Path, Constants.ROOT_FOLDER, Constants.DATA_FOLDER),
MapKey = Constants.BASIC_MAP_KEY,
Logging = false
};
#if DEBUG
data.ServiceURI = Constants.DEV_ENDPOINT_SERVICE_ADDRESS;
#endif
As you can see, this can only pick up the DEV or the LIVE endpoints. This code cannot distinguish whether the webserver is LIVE or TEST
I thought about setting up an App.Config file and get the correct Endpoint from there. But when I create a new item, the Config template is not listed. So how do I do this?
For now I could propose this solution :
public static class Constants
{
public static string GetEndPoint()
{
// Debugging purpose
if (System.Diagnose.Debug.IsAttached)
{
return DEV_ENDPOINT_SERVICE_ADDRESS;
}
else if ( Environment.MachineName == "Test Server" ) // You need to know your test server machine name at hand.
{
return "Return test Server endpoint"
}
else
{
return "Return live server endpoint";
}
}
}
You can used it in your SettingsViewModel like this:
var data = new SettingsViewModel()
{
ServiceURI = Constants.GetEndPoint(),
AutoSync = Constants.DEFAULT_AUTO_SYNC,
AppDataFolder = Path.Combine(ApplicationData.Current.LocalFolder.Path, Constants.ROOT_FOLDER, Constants.DATA_FOLDER),
MapKey = Constants.BASIC_MAP_KEY,
Logging = false
};
The drawback for this solution is, if you change your test server you need to change is manually in your code.
Having done some research I realise I need to clarify something. The application I am working on is a Windows RT application and this does not allow config files. The solution I am meant to use is to use local settings, but these do not reference an external file like an App.Config. If I want to change the location of an EndPoint then I am going to have to specify where that is in the code.

Prompt for file on application launch

I am making an application that can potentially be used on multiple computers by the same user. I currently have implemented backup and restore functionality to keep the SQLite database synchronized. However, when I install a new copy of the application, I would like to prompt the user to select a backup file (if applicable).
Initially, I thought that I would just put the logic in MainPageViewModel.xaml in the OnNavigatedTo method. The problem with that is that it would run through that logic every time navigating back to MainView. So, I thought that it would make sense to put it in OnApplicationLaunchAsync to only run once when the application is launched.
Here is my code currently:
private async Task<StorageFile> SelectFileAsync()
{
StorageFile pickedFile = null;
var settings = Container.Resolve<ISettings>();
var picker = new FileOpenPicker();
picker.FileTypeFilter.Add(".sqlite");
picker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
var file = await picker.PickSingleFileAsync();
if (file != null)
{
var pickedFileToken = StorageApplicationPermissions.FutureAccessList.Add(file);
settings.BackupFileToken = pickedFileToken;
pickedFile = file;
}
return pickedFile;
}
protected async override Task OnLaunchApplicationAsync(LaunchActivatedEventArgs args)
{
var navigationService = Container.Resolve<INavigationService>();
var dialogService = Container.Resolve<IDialogService>();
var settings = Container.Resolve<ISettings>();
if (!string.IsNullOrEmpty(settings.BackupFileToken))
{
var backupFile =
await StorageApplicationPermissions.FutureAccessList.GetFileAsync(settings.BackupFileToken);
var properties = await backupFile.GetBasicPropertiesAsync();
dialogService.Show(string.Format("Backup file found: {0}\r\n" +
"Modified date: {1}", backupFile.Path, properties.DateModified), "");
navigationService.Navigate(Experiences.Main);
}
else
{
navigationService.Navigate(Experiences.Blank);
//dialogService.Show("No backup file specified. Please choose a backup file location.", "");
// TODO: load blank page, then select backup file location, then navigate to main page
await SelectFileAsync();
}
// do not need to return Task.FromResult when OnLaunchApplicationAsync() is async
//return Task.FromResult<object>(null);
}
As you can see, if the BackupFileToken exists, it will check the properties of the file and display a dialog with the file path and last modified date. My problem lies in the situation where it is a new installation/the backup token doesn't exist.
If I try to display a dialog before the FileOpenPicker then the application crashes. I thought perhaps adding a blank view to navigate to, then display the dialog and FileOpenPicker. It just seems like there should be a simpler way to accomplish this (without the need for extra views).
Can someone recommend a way to prompt the user to select a file when the application launches, but let them know the purpose of the FileOpenPicker?
I am aware that my await SelectFileAsync() is losing its return value, this is a temporary situation for testing purposes. I will be sure to assign the return value to the relevant variable once I have found a solution.
Maybe you can use the override
protected override void OnWindowCreated(WindowCreatedEventArgs args) in App.xaml.cs
which is also called once for the creation of the main window.

Detecting current device in Windows Universal App

I am trying out released VS 2013 Update 2 and building a sample Universal Application.
I have created a user control and on both MainPages added GridViews (on Windows Phone and Windows 8).
I want to change some things via code when app is running on Windows Phone.
Is there a way to do something like:
if(<deviceType> == "WindowsPhone")
{
}
else
{
}
Normally when building your app, you can use preprocessor directives. When building app for windows phone, VS as default defines WINDOWS_PHONE_APP (take a look at Project Properties -> Build -> Conditional compilation symbols). Therefore anywhere in your code you can put such a statement:
#if WINDOWS_PHONE_APP
// do when this is compiled as Windows Phone App
#else
// not for windows phoen
#endif
More information you can get at MSDN.
I would advise to use this approach, hence in most cases you know exactly when you will use specific code for Phone (ARM) or other platform. Of course if you need you can define more symbols for specific build configurations/platforms.
Remarks: Since W10, where you need to check the platform in Run-Time, then you can use ApiInformation class and check if specific type exists in the api. For example like this:
if (ApiInformation.IsApiContractPresent("Windows.Phone.PhoneContract", 1))
// do code for mobile
else
// do code for other
That's what worked for me in Universal Windows (Windows 10) project
public static Platform DetectPlatform()
{
bool isHardwareButtonsAPIPresent =
ApiInformation.IsTypePresent("Windows.Phone.UI.Input.HardwareButtons");
if (isHardwareButtonsAPIPresent)
{
return Platform.WindowsPhone;
}
else
{
return Platform.Windows;
}
}
If you want an in-code method of determining the current device, you could try this:
public Windows.Foundation.Metadata.Platform DetectPlatform()
{
try
{
//Calls an unsupported API.
Windows.Networking.BackgroundTransfer.BackgroundDownloader.RequestUncontrainedDownloadsAsync(null);
}
catch (NotImplementedException)
{
//The API isn't supported on Windows Phone. Thus, the current platform is Windows Phone.
return Windows.Foundation.Metadata.Platform.WindowsPhone;
}
catch(Exception)
{
//Otherwise, this is Windows (desktop/RT).
return Windows.Foundation.Metadata.Platform.Windows;
}
}
Source: https://gist.github.com/Amrykid/2fd65ae1815a928fe753
OR you can do this
Add this to
App.Xaml.Cs
public static bool IsMobile
{
get
{
var qualifiers = Windows.ApplicationModel.Resources.Core.ResourceContext.GetForCurrentView().QualifierValues;
return (qualifiers.ContainsKey("DeviceFamily") && qualifiers["DeviceFamily"] == "Mobile");
}
}
From GitHub
public static class DeviceTypeHelper
{
public static DeviceFormFactorType GetDeviceFormFactorType()
{
switch (AnalyticsInfo.VersionInfo.DeviceFamily)
{
case "Windows.Mobile":
return DeviceFormFactorType.Phone;
case "Windows.Desktop":
return UIViewSettings.GetForCurrentView().UserInteractionMode == UserInteractionMode.Mouse
? DeviceFormFactorType.Desktop
: DeviceFormFactorType.Tablet;
case "Windows.Universal":
return DeviceFormFactorType.IoT;
case "Windows.Team":
return DeviceFormFactorType.SurfaceHub;
default:
return DeviceFormFactorType.Other;
}
}
}
public enum DeviceFormFactorType
{
Phone,
Desktop,
Tablet,
IoT,
SurfaceHub,
Other
}
https://gist.githubusercontent.com/wagonli/40d8a31bd0d6f0dd7a5d/raw/f6175de5fcad40cc257edc3748c0e349495d17f6/DeviceTypeHelper.cs
It's a workaround
//PC customization
if(ApiInformation.IsTypePresent("Windows.UI.ViewManagement.ApplicationView"))
{
}
//Mobile customization
if(ApiInformation.IsTypePresent("Windows.UI.ViewManagement.StatusBar"))
{
}

How to store string values in a Windows mobile application and retrieve it later

I am developing a Windows mobile 6.0 application using Visual Studio 2008 (.NET Framework 3.0) with C#, I want to save the selected value from a comboBox in Form2 for example and retrieve it later after I close and re-open the application in Form1.
There are a bunch of way that this can be made possible. I prefer saving this value (along wiht any other value you would like to save) inside of a .xml file. When you proess the "OK" button on your form, it will save the value to the value. Once you open the form, it will open and read the .xml file assinging the values as need be. Check out this link on how to read and write to .xml files.
First, there is NO Compact Framework version 3.0 for Windows Mobile. Are you talling about Windows Phone 7 or 8?
For Windows Mobile (Compact Framework 2.0 or 3.5):
If you want to store / retrieve only one value, you can simply use the registry to save and restore the value.
using System;
using System.Text;
using Microsoft.Win32;
namespace StoreString
{
class RegStoreClass:IDisposable
{
RegistryKey m_regKey = null;
String m_AppName="";
String m_Value = "";
public String sValue{
get{
readReg();
return m_Value;
}
set{
m_Value=value;
this.writeReg();
}
}
String AppName
{
get
{
if (m_AppName == "")
{
//assign AppName
string aname;
//get the executable name
m_AppName = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;
//remove extra infos
}
return m_AppName;
}
}
public RegStoreClass()
{
try
{
//open or create sub key for read/write
m_regKey = Registry.LocalMachine.CreateSubKey(AppName);
}
catch (Exception)
{
}
//try to read value from sub key
if (!readReg())
{
//something failed, write actual value to reg
writeReg();
}
}
public void Dispose(){
m_regKey.Flush();
m_regKey.Close();
}
bool readReg(){
bool bRet=false;
try
{
string s = (string)m_regKey.GetValue("Value", "n/a");
m_Value = s;
bRet=true;
}
catch (Exception)
{
}
return bRet;
}
bool writeReg(){
bool bRet = false;
try
{
m_regKey.SetValue("Value", m_Value, RegistryValueKind.String);
m_regKey.Flush();
bRet = true;
}
catch (Exception)
{
}
return bRet;
}
}
}
Use the above class (for example as regClass) in your Form2 code. Then, when you need to store or retrieve the stored value:
Save new value:
regClass.sValue = comboBox1.SelectedItem.ToString();
Read saved value:
string s = regClass.sValue
The above class exmines the application name itself and uses that as subkey for storing the value in the registry.
==========================================
If you come across the need to store more and more values, it is better to use a class that will do that for you. The storage can be an external file or the registry. External files can be organized like ini files or have a structure as xml files.
Compact Framework implementation of app.settings: http://www.codeproject.com/Articles/6308/AppSettings-Implementation-for-Compact-Framework and http://www.codeproject.com/Articles/51848/Compact-Framework-Configuration-XML-File-Read-Writ
Ini or xml file location as program executable: Find INI File From application path and Read INI File in Compact framework C#
Read / write ini files http://www.codeproject.com/Articles/21896/INI-Reader-Writer-Class-for-C-VB-NET-and-VBScript
The easiest way is to use xmlserializer. This way you dont need to specify how to write nor read every values. Just pass them the stream object and the object to be serialized and xmlserializer will take care of writing of the values. Same with getting back the values, use deserialize and get the object and cast it to the target type.

Categories

Resources