Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding settings class to a UWP app

I'm developing a Universal Windows Platform app but there is no Settings template in Visual Studio.

How can I implement an easy, strongly typed and observable class that stores my settings in LocalSettings or RoamingSettings?

like image 708
joseangelmt Avatar asked Feb 18 '16 00:02

joseangelmt


People also ask

Where are UWP settings stored?

Settings stored here are kept on the device. Windows. Storage. ApplicationData.

Is UWP deprecated?

Microsoft continues to baby-step around the obvious, but it has officially deprecated the Universal Windows Platform (UWP) as it pushes the desktop-focused Windows App SDK (formerly called Project Reunion) and WinUI 3 as the future of Windows application development.


1 Answers

  1. Create a new class inheriting from ObservableSettings.
  2. Call to the base class constructor indicating if you want to store the settings in LocalSettings or in RoamingSettings.
  3. Add all your properties calling the base class members Set and Get in the getter and in the setter. No need to pass the name of the property or use nameof() operator!
  4. Optionally you can set a default value decorating the property with DefaultSettingValue attribute.

Here an example of a settings class:

namespace Test {     public class Settings : ObservableSettings     {         private static Settings settings = new Settings();         public static Settings Default         {             get { return settings; }         }          public Settings()             : base(ApplicationData.Current.LocalSettings)         {         }          [DefaultSettingValue(Value = 115200)]         public int Bauds         {             get { return Get<int>(); }             set { Set(value); }         }          [DefaultSettingValue(Value = "Jose")]         public string Name         {             get { return Get<string>(); }             set { Set(value); }         }      } } 

and here how to add an instance in your app.xaml:

<Application     x:Class="Test.App"     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"     xmlns:local="using:Test"     RequestedTheme="Light">     <Application.Resources>         <local:Settings x:Key="settings"/>     </Application.Resources> </Application> 

Access and modify the values in a MVVM fashion:

<Page     x:Class="Test.MainPage"     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"     xmlns:local="using:Test"     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"     mc:Ignorable="d"     DataContext="{StaticResource settings}">      <StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">         <TextBlock Text="Bauds"/>         <TextBox Text="{Binding Default.Bauds, Mode=TwoWay}"/>         <TextBlock Text="Name"/>         <TextBox Text="{Binding Default.Name, Mode=TwoWay}"/>     </StackPanel> </Page> 

Everything will be stored properly in your settings repository.

Here you have the implementation of DefaultSettingValue and ObservableSettings:

using System.Collections.Generic; using System.Linq; using System.Runtime.CompilerServices; using System.Reflection; using System.ComponentModel; using Windows.Storage;   [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public sealed class DefaultSettingValueAttribute : Attribute {     public DefaultSettingValueAttribute()     {     }      public DefaultSettingValueAttribute(object value)     {         Value = value;     }      public object Value { get; set; } }  public class ObservableSettings : INotifyPropertyChanged {     private readonly ApplicationDataContainer settings;      public ObservableSettings(ApplicationDataContainer settings)     {         this.settings = settings;     }      public event PropertyChangedEventHandler PropertyChanged;      protected bool Set<T>(T value, [CallerMemberName] string propertyName = null)     {         if (settings.Values.ContainsKey(propertyName))         {             var currentValue = (T)settings.Values[propertyName];             if (EqualityComparer<T>.Default.Equals(currentValue, value))                 return false;         }          settings.Values[propertyName] = value;         PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));         return true;     }      protected T Get<T>([CallerMemberName] string propertyName = null)     {         if (settings.Values.ContainsKey(propertyName))             return (T)settings.Values[propertyName];          var attributes = GetType().GetTypeInfo().GetDeclaredProperty(propertyName).CustomAttributes.Where(ca => ca.AttributeType == typeof(DefaultSettingValueAttribute)).ToList();         if (attributes.Count == 1)             return (T)attributes[0].NamedArguments[0].TypedValue.Value;          return default(T);     } 

You can download a solution with a functional example from the repository I created in GitHub.

like image 108
joseangelmt Avatar answered Sep 21 '22 17:09

joseangelmt