40

Sto sviluppando un'app Universal Windows Platform ma non ci sono modelli di impostazioni in Visual Studio.Aggiunta di una classe di impostazioni a un'app UWP

Come posso implementare una classe facile, fortemente dattilografata e osservabile che memorizza le mie impostazioni in LocalSettings o RoamingSettings?

+13

http://meta.stackoverflow.com/questions/317127/hidden-advertisement-as-spam –

risposta

51
  1. Creare una nuova classe ereditata da ObservableSettings.
  2. Chiamare al costruttore della classe base che indica se si desidera memorizzare le impostazioni in Impostazioni locali o in RoamingSettings.
  3. Aggiungi tutte le proprietà di chiamata ai membri della classe di base Set e Prendi nel getter e setter nel. Non è necessario passare il nome della proprietà o utilizzare l'operatore nameof()!
  4. Opzionalmente è possibile impostare un valore predefinito decorando la proprietà con l'attributo DefaultSettingValue.

Ecco un esempio di una classe impostazioni:

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); } 
     } 

    } 
} 

e qui come aggiungere un'istanza nella vostra 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> 

accedere e modificare i valori in modo MVVM :

<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> 

Tutto verrà memorizzato correttamente nella tua s repository di ettings.

Qui si ha l'attuazione di DefaultSettingValue e 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); 
    } 

è possibile scaricare una soluzione con un esempio funzionale dal repository che ho creato in GitHub.

+17

Bella auto-risposta! Grazie per aver contribuito a SO. Quando ti colleghi a un blog o a un tuo progetto (o alla tua azienda, ...), sei incoraggiato ad aggiungere una piccola dichiarazione di non responsabilità (nella parte superiore della risposta o vicino al link) specificando la tua relazione con detto progetto, come potrebbe influenzare la tua obiettività. –