web-dev-qa-db-fra.com

c # - approche pour enregistrer les paramètres utilisateur dans une application WPF?

Quelle approche recommandez-vous pour conserver les paramètres utilisateur dans une application Windows (bureau) WPF? Notez que l’idée est que l’utilisateur peut modifier ses paramètres au moment de l’exécution, puis peut fermer l’application. Lorsqu’il démarrera ultérieurement, l’application utilisera les paramètres actuels. Effectivement, il semblera que les paramètres de l'application ne changent pas. 

Q1 - Base de données ou autre approche? J'ai une base de données sqlite que je vais utiliser de toute façon, donc utiliser une table dans la base de données serait aussi bon que n'importe quelle approche?

Q2 - Si base de données: quelle conception de table de base de données? Une table avec des colonnes pour différents types de données que vous pourriez avoir (par exemple, string, long, DateTime etc.) OR juste une table avec une chaîne pour la valeur sur laquelle vous devez sérialiser et désérialiser les valeurs? Je pense que le premier serait plus facile, et s'il n'y a pas beaucoup de paramètres, les frais généraux ne sont pas importants? 

Q3 - Les paramètres de l'application peuvent-ils être utilisés à cette fin? Si tel est le cas, des tâches spéciales sont-elles requises pour activer la persistance ici? De plus, qu'adviendrait-il de l'utilisation de la valeur "par défaut" dans le concepteur de paramètres d'application dans ce cas? La valeur par défaut remplacerait-elle les paramètres enregistrés entre l'exécution de l'application? (ou auriez-vous besoin de NE PAS utiliser la valeur par défaut)

61
Greg

Vous pouvez utiliser Paramètres de l'application pour cela, utiliser une base de données n'est pas la meilleure option compte tenu du temps nécessaire pour lire et écrire les paramètres (spécialement si vous utilisez des services Web).

Voici quelques liens qui expliquent comment y parvenir et les utiliser dans WPF -

Paramètres utilisateur dans WPF

Astuce WPF rapide: comment lier les ressources et les paramètres de l’application WPF?

Une fenêtre configurable pour WPF

61
akjoshi

Vous pouvez stocker vos informations de paramètres sous la forme Strings de XML dans le Settings.Default. Créez des classes pour stocker vos données de configuration et assurez-vous qu'elles sont bien [Serializable]. Ensuite, avec les assistants suivants, vous pouvez sérialiser des instances de ces objets - ou List<T> (ou des tableaux T[], etc.) - en String. Stockez chacune de ces différentes chaînes dans son propre emplacement Settings.Default dans la variable Settings de votre application WPF.

Pour récupérer les objets au prochain démarrage de l'application, lisez les chaînes Settings d'intérêt et Deserialize dans le type attendu T (cette heure doit être explicitement spécifiée en tant qu'argument de type à Deserialize<T>).

public static String Serialize<T>(T t)
{
    using (StringWriter sw = new StringWriter())
    using (XmlWriter xw = XmlWriter.Create(sw))
    {
        new XmlSerializer(typeof(T)).Serialize(xw, t);
        return sw.GetStringBuilder().ToString();
    }
}

public static T Deserialize<T>(String s_xml)
{
    using (XmlReader xw = XmlReader.Create(new StringReader(s_xml)))
        return (T)new XmlSerializer(typeof(T)).Deserialize(xw);
}
11
Glenn Slayden

Je préfère aussi aller avec la sérialisation pour déposer. Les fichiers XML répondent à presque toutes les exigences. Vous pouvez utiliser la construction ApplicationSettings mais celles-ci ont des restrictions et un comportement défini mais (pour moi) très étrange où elles ont été stockées. Je les ai beaucoup utilisés et ils travaillent. Mais si vous voulez avoir un contrôle total sur comment et où ils ont stocké, j'utilise une autre approche.

  1. Faites une classe quelque part avec tous vos paramètres. Je l'ai nommé MySettings
  2. Implémenter Save and Read pour la persistance
  3. Utilisez-les dans votre code d'application

Avantages:

  • Approche très simple. 
  • Une classe pour les paramètres. Charge. Sauvegarder.
  • Tous vos paramètres sont sécurisés.
  • Vous pouvez simplifier ou étendre la logique à vos besoins (gestion des versions, plusieurs profils par utilisateur, etc.)
  • Cela fonctionne très bien dans tous les cas (base de données, WinForms, WPF, Service, etc ...)
  • Vous pouvez définir où stocker les fichiers XML. 
  • Vous pouvez les trouver et les manipuler par code ou manuellement 
  • Cela fonctionne pour n'importe quelle méthode de déploiement que je peux imaginer.

Désavantages: - Vous devez penser à l'emplacement de stockage de vos fichiers de paramètres. (Mais vous pouvez simplement utiliser votre dossier d'installation)

Voici un exemple simple (non testé) -

public class MySettings
{
    public string Setting1 { get; set; }
    public List<string> Setting2 { get; set; }

    public void Save(string filename)
    {
        using (StreamWriter sw = new StreamWriter(filename))
        {
            XmlSerializer xmls = new XmlSerializer(typeof(MySettings));
            xmls.Serialize(sw, this);
        }
    }
    public MySettings Read(string filename)
    {
        using (StreamReader sw = new StreamReader(filename))
        {
            XmlSerializer xmls = new XmlSerializer(typeof(MySettings));
            return xmls.Deserialize(sw) as MySettings;
        }
    }
}

Et voici comment l'utiliser. Il est possible de charger les valeurs par défaut ou de les remplacer par les paramètres de l'utilisateur en vérifiant simplement si les paramètres de l'utilisateur existent:

public class MyApplicationLogic
{
    public const string UserSettingsFilename = "settings.xml";
    public string _DefaultSettingspath = 
        Assembly.GetEntryAssembly().Location + 
        "\\Settings\\" + UserSettingsFilename;

    public string _UserSettingsPath = 
        Assembly.GetEntryAssembly().Location + 
        "\\Settings\\UserSettings\\" + 
        UserSettingsFilename;

    public MyApplicationLogic()
    {
        // if default settings exist
        if (File.Exists(_UserSettingsPath))
            this.Settings = Settings.Read(_UserSettingsPath);
        else
            this.Settings = Settings.Read(_DefaultSettingspath);
    }
    public MySettings Settings { get; private set; }

    public void SaveUserSettings()
    {
        Settings.Save(_UserSettingsPath);
    }
}

peut-être que quelqu'un s'inspire de cette approche. C'est comme ça que je le fais maintenant depuis de nombreuses années et j'en suis assez content.

9
Mat

L’approche la plus répandue depuis longtemps pour cette question est la suivante: Stockage isolé.

Sérialisez votre état de contrôle au format XML ou à un autre format (particulièrement si vous enregistrez des propriétés de dépendance avec WPF), puis enregistrez le fichier dans la mémoire de stockage isolée de l'utilisateur.

Si vous souhaitez suivre la procédure de configuration de l'application, j'ai moi-même essayé quelque chose de similaire ... bien que l'approche ci-dessous puisse facilement être adaptée pour utiliser le stockage isolé:

class SettingsManager
{
    public static void LoadSettings(FrameworkElement sender, Dictionary<FrameworkElement, DependencyProperty> savedElements)
    {
        EnsureProperties(sender, savedElements);
        foreach (FrameworkElement element in savedElements.Keys)
        {
            try
            {
                element.SetValue(savedElements[element], Properties.Settings.Default[sender.Name + "." + element.Name]);
            }
            catch (Exception ex) { }
        }
    }

    public static void SaveSettings(FrameworkElement sender, Dictionary<FrameworkElement, DependencyProperty> savedElements)
    {
        EnsureProperties(sender, savedElements);
        foreach (FrameworkElement element in savedElements.Keys)
        {
            Properties.Settings.Default[sender.Name + "." + element.Name] = element.GetValue(savedElements[element]);
        }
        Properties.Settings.Default.Save();
    }

    public static void EnsureProperties(FrameworkElement sender, Dictionary<FrameworkElement, DependencyProperty> savedElements)
    {
        foreach (FrameworkElement element in savedElements.Keys)
        {
            bool hasProperty =
                Properties.Settings.Default.Properties[sender.Name + "." + element.Name] != null;

            if (!hasProperty)
            {
                SettingsAttributeDictionary attributes = new SettingsAttributeDictionary();
                UserScopedSettingAttribute attribute = new UserScopedSettingAttribute();
                attributes.Add(attribute.GetType(), attribute);

                SettingsProperty property = new SettingsProperty(sender.Name + "." + element.Name,
                    savedElements[element].DefaultMetadata.DefaultValue.GetType(), Properties.Settings.Default.Providers["LocalFileSettingsProvider"], false, null, SettingsSerializeAs.String, attributes, true, true);
                Properties.Settings.Default.Properties.Add(property);
            }
        }
        Properties.Settings.Default.Reload();
    }
}

.....et....

  Dictionary<FrameworkElement, DependencyProperty> savedElements = new Dictionary<FrameworkElement, DependencyProperty>();

public Window_Load(object sender, EventArgs e) {
           savedElements.Add(firstNameText, TextBox.TextProperty);
                savedElements.Add(lastNameText, TextBox.TextProperty);

            SettingsManager.LoadSettings(this, savedElements);
}

private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            SettingsManager.SaveSettings(this, savedElements);
        }
6
Jeff

Outre une base de données, vous pouvez également disposer des options suivantes pour enregistrer les paramètres liés à l'utilisateur 

  1. registre sous HKEY_CURRENT_USER 

  2. dans un fichier dans le dossier AppData

  3. en utilisant le fichier Settings dans WPF et en définissant son étendue en tant qu'utilisateur

4
ajay_whiz

D'après mon expérience, stocker tous les paramètres dans une table de base de données est la meilleure solution. Ne vous inquiétez même pas de la performance. Les bases de données actuelles sont rapides et peuvent facilement stocker des milliers de colonnes dans une table. J'ai appris cela à la dure - avant de sérériser/désérialiser - un cauchemar. Le stockage dans un fichier local ou dans le registre pose un gros problème: si vous devez prendre en charge votre application et que votre ordinateur est éteint, l'utilisateur n'est pas devant, vous ne pouvez rien faire. Si les paramètres sont dans la base de données, vous pouvez le faire. changé les et alto pour ne pas mentionner que vous pouvez comparer les paramètres ....

3
Adam

Je fais généralement ce genre de chose en définissant une classe de paramètres [Serializable] personnalisée et en la sérialisant simplement sur le disque. Dans votre cas, vous pourriez tout aussi facilement le stocker en tant que blob de chaîne dans votre base de données SQLite. 

1
Doobi

Je voulais utiliser un fichier de contrôle XML basé sur une classe pour mon application WPF de bureau VB.net. Le code ci-dessus pour faire tout cela en un est excellent et me met dans la bonne direction. Au cas où quelqu'un chercherait une solution VB.net, voici la classe que j'ai construite:

Imports System.IO
Imports System.Xml.Serialization

Public Class XControl

Private _person_ID As Integer
Private _person_UID As Guid

'load from file
Public Function XCRead(filename As String) As XControl
    Using sr As StreamReader = New StreamReader(filename)
        Dim xmls As New XmlSerializer(GetType(XControl))
        Return CType(xmls.Deserialize(sr), XControl)
    End Using
End Function

'save to file
Public Sub XCSave(filename As String)
    Using sw As StreamWriter = New StreamWriter(filename)
        Dim xmls As New XmlSerializer(GetType(XControl))
        xmls.Serialize(sw, Me)
    End Using
End Sub

'all the get/set is below here

Public Property Person_ID() As Integer
    Get
        Return _person_ID
    End Get
    Set(value As Integer)
        _person_ID = value
    End Set
End Property

Public Property Person_UID As Guid
    Get
        Return _person_UID
    End Get
    Set(value As Guid)
        _person_UID = value
    End Set
End Property

End Class
0
Scott
  1. Dans tous les endroits où j'ai travaillé, la base de données est devenue obligatoire en raison de la prise en charge des applications. Comme Adam l'a dit, il se peut que l'utilisateur ne soit pas à son bureau ou que la machine soit éteinte, ou que vous souhaitiez modifier rapidement la configuration de quelqu'un ou attribuer à un nouveau participant une configuration par défaut (ou un membre de l'équipe).

  2. Si les paramètres sont susceptibles de croître au fur et à mesure de la publication des nouvelles versions de l'application, vous pouvez stocker les données sous forme de blobs, qui peuvent ensuite être désérialisés par l'application. Ceci est particulièrement utile si vous utilisez quelque chose comme Prism, qui détecte les modules, car vous ne pouvez pas savoir quels paramètres un module retournera . De cette façon, vous pouvez avoir différents réglages pour chaque machine.

  3. Je n'ai pas beaucoup utilisé la classe Settings intégrée, aussi je m'abstiendrai de tout commentaire. :)

0
Will_Piuvans