WPFウィンドウ(デスクトップ)アプリケーションでユーザー設定を保持するには、どのようなアプローチをお勧めしますか?ユーザーが実行時に設定を変更し、アプリケーションを閉じることができ、その後アプリケーションを起動すると、アプリケーションは現在の設定を使用するという考え方に注意してください。事実上、アプリケーション設定が変更されていないかのように表示されます。
Q1-データベースまたは他のアプローチ?私はとにかく使用するsqliteデータベースを持っているので、データベース内のテーブルを使用することはあらゆるアプローチと同じくらい良いでしょうか?
Q2-If Database:データベーステーブルの設計持つ可能性のあるさまざまなデータ型の列を持つ1つのテーブル(たとえば、string
、long
、DateTime
など)OR値をシリアル化および非シリアル化する必要がある値の文字列?最初の方が簡単だと思いますし、設定が多くなければオーバーヘッドはそれほど多くありませんか?
Q3-これにはアプリケーション設定を使用できますか?その場合、ここで永続性を有効にするために必要な特別なタスクはありますか?また、この場合、アプリケーション設定デザイナで「デフォルト」値を使用するとどうなりますか?デフォルトは、アプリケーションの実行中に保存された設定を上書きしますか? (または、デフォルト値を使用しないでください)
アプリケーション設定 を使用できます。データベースの使用は、設定の読み取りと書き込みにかかる時間を考慮すると、最適なオプションではありません(特にWebサービスを使用する場合)。
これを実現し、WPFで使用する方法を説明するリンクがいくつかあります-
Settings.Default
にXMLのStrings
として設定情報を保存できます。構成データを保存するクラスをいくつか作成し、それらが[Serializable]
であることを確認します。次に、次のヘルパーを使用して、これらのオブジェクトのインスタンス、またはそれらのList<T>
(または配列T[]
など)をString
にシリアル化できます。これらのさまざまな文字列のそれぞれを、WPFアプリケーションのSettings
のそれぞれのSettings.Default
スロットに格納します。
次回アプリを起動したときにオブジェクトを復元するには、目的のSettings
文字列とDeserialize
を読み取り、期待されるタイプT
(今回は明示的にタイプとして指定する必要があります) 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);
}
更新:最近はJSONを使用します。
また、ファイルへのシリアル化を使用することを好みます。 XMLファイルは、ほとんどすべての要件に適合します。 ApplicationSettings
ビルドインを使用できますが、それらにはいくつかの制限があり、定義されていますが(私にとっては)非常に奇妙な動作が格納されています。私はそれらを頻繁に使用し、動作します。しかし、どのように、どこに保存したかを完全に制御したい場合は、別のアプローチを使用します。
MySettings
という名前を付けました利点:
欠点:-設定ファイルを保存する場所について考える必要があります。 (ただし、インストールフォルダーのみを使用できます)
これは簡単な例です(テストされていません)。
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;
}
}
}
そして、ここでそれを使用する方法です。ユーザー設定が存在するかどうかを確認するだけで、デフォルト値をロードしたり、ユーザーの設定でそれらを上書きしたりすることができます。
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);
}
}
多分誰かがこのアプローチに触発されます。これは私が今何年もやっている方法であり、私はそれで非常に満足しています。
この質問に対する最も一般的なアプローチは、分離ストレージです。
コントロール状態をXMLまたは他の形式にシリアル化し(特に、依存関係プロパティをWPFで保存している場合は簡単)、ファイルをユーザーの分離ストレージに保存します。
アプリの設定ルートに行きたい場合は、私はある時点で似たようなことを試しました...ただし、以下のアプローチは分離ストレージを使用するために簡単に適応できます:
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();
}
}
.....そして....
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);
}
データベースとは別に、ユーザー関連の設定を保存する次のオプションもあります
HKEY_CURRENT_USER
の下のレジストリ
AppData
フォルダー内のファイル内
wPFでSettings
ファイルを使用し、そのスコープをUserとして設定する
私の経験では、すべての設定をデータベーステーブルに保存することが最良のソリューションです。パフォーマンスについても心配しないでください。今日のデータベースは高速で、テーブルに数千の列を簡単に格納できます。私はこれを困難な方法で学びました-シリアライズ/デシリアライズする前に-悪夢。ローカルファイルまたはレジストリに保存することには、1つの大きな問題があります-アプリをサポートする必要があり、コンピューターがオフの場合-ユーザーが目の前にない-あなたができることは何もありません....設定がDBにある場合-あなたはできます設定を比較できることは言うまでもなく、それらとビオラを変更しました。..
通常、このようなことは、カスタム[Serializable
]設定クラスを定義し、単純にディスクにシリアル化することで行います。あなたの場合、SQLiteデータベースに文字列blobとして簡単に保存できます。
VB.netデスクトップWPFアプリケーションのクラスに基づくxml制御ファイルを使用したかった。これをすべて1つにまとめた上記のコードは優れており、正しい方向に導いてくれます。誰かがVB.netソリューションを探している場合は、ここに私が構築したクラスがあります:
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
私が働いたすべての場所で、データベースはアプリケーションのサポートのために必須でした。 Adamが言ったように、ユーザーは自分の机にいないか、マシンがオフになっている可能性があります。または、誰かの構成をすばやく変更するか、新しい参加者にデフォルト(またはチームメンバー)の構成を割り当てることができます。
アプリケーションの新しいバージョンがリリースされたときに設定が大きくなる可能性がある場合は、データをブロブとして保存し、アプリケーションでデシリアライズできます。これは、モジュールが返す設定がわからないため、モジュールを検出するPrismなどを使用する場合に特に便利です。ブロブは、ユーザー名/マシンの複合キーによってキー設定できます。これにより、マシンごとに異なる設定を使用できます。
組み込みのSettingsクラスをあまり使用していないので、コメントを控えます。 :)