|
|
Compact Framework - Use XML Files to Replace The RegistryGetSetting and SaveSetting Registry Settings Replacement | | If your Compact Framework application has to save settings, you may want to go through the hassle of writing to the system Registry. When it comes to developing on the Compact Framework, accessing the Registry is just not worth the trouble if you can find a way around it. The VB GetSetting and SaveSetting functions are not available. If you are developing in C#, you never had those functions anyway; but using APIs is no fun, not to me at least. Why not use an XML file to save your settings?
This class provides overloaded methods of VBs GetSetting and SaveSetting functionality. I have written it so that no program changes have to be made, other than to instantiate an instance of the class and place the object instance name in front of all GetSetting and SaveSetting function calls. Actually, the class could have been written as a module (C# programmers, pretend I didn't use the word Module), and then it would not have to be instantiated. However, I wrote it as a class for several reasons. I program in both VB.NET and CSharp, so I am attempting to consider both languages as I write new code. C# does not support modules; rather it provides Shared Classes. You can do the same thing in VB.NET by making all methods and variables Shared. But, then I would have to place the name of the class as a prefix to all references to GetSetting or SaveSetting, just as if I were instantiating it as an object.
As you examine the code for the class, you will see that the SaveSetting and GetSetting methods support the calls exactly as if the user were using the built-in VB.NET functions. That was on purpose so the user does not have to change the respective calls. You will note that the constructor accepts a Boolean name "AllUsers". For this Compact Framework (CF) application, I do not support multiple user functionality, so the boolean is passed as True to instantiate the object. If this Boolean is True, an XML file will be named just using the passed AppTitle string. However, if the Boolean is False, the class will append the UserName from the Environment as part of the XML filename (not supported on CF), thus allowing multiple users to share a computer and your application, while maintaining their own settings. Finally, there is a Public property called "AlternatePath", which allows the user to supply the path where they want the settings saved.
Although I have only used one "Settings" paramater value in this application, the class will support any number of Settings, such as Settings, Registration, etc. The XML file will support a hierarchy of multiple key values within multiple settings.
Initially, your application will not have any XML setting file, so the class will return the default values that your application passes when calling GetSetting.
I have only provided three Overloaded metods for each of the respective functions, because Integer, String, and Boolean will normally cover most application settings. If you need another type of setting, simply add a pair of overloads for the needed type.
Figure 3 shows the VB.NET code for the class. I know that C# programmers don't normally have access to GetSetting and SaveSetting (which from a VB programmers perspective, are great functions), so I have taken the time to convert the class to C# Code. I hope it might be used by a C# programmer. You can get both the VB.NET and C# applications by download the code for this article.
The class is straight-forward, nothing fancy, so I won't bore you with further verbage on how it works. The form shown in Figure 1 was designed to test the class in VB.NET. Figure 2 shows the code behind the form. This code sets up the object and the button event handlers call GetSetting and SaveSetting to read and write the XML file.
Figure 1 - Test Form for CSettings.VB.

Figure 2 - Form1 Code for Calling CSetting Object.
Private oSettings As CSettings
Const AppTitle = "TestSettings"
Const Settings = "Settings"
Const TextTest = "TEXTSETTING"
Const CkTest = "CKSETTING"
Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
' for the cf, allusers must be true
oSettings = New CSettings(True)
End Sub
Private Sub btnSaveSettings_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnSaveSettings.Click
With oSettings
.SaveSetting(AppTitle, Settings, TextTest, MetxtTestTextSetting.Text)
.SaveSetting(AppTitle, Settings, CkTest, MeCheckBox1.Checked)
End With
End Sub
Private Sub btnGetSettings_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnGetSettings.Click
With oSettings
Me.txtTestTextSetting.Text = .GetSetting(AppTitle, _
Settings, TextTest, "Not Set")
Me.CheckBox1.Checked = .GetSetting(AppTitle, Settings, CkTest, False)
End With
End Sub
Private Sub btnClearSettings_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnClearSettings.Click
With Me
.txtTestTextSetting.Text = String.Empty
.CheckBox1.Checked = False
End With
End Sub
|
Figure 3 - VB.NET Code for CSettings Class.
The following code is C# event handlers for setting up and calling the class.
private CSharp2003WindowsApplication1.CSettings oSettings;
const string AppTitle = "TestSettings";
const string Settings = "Settings";
const string TextTest = "TEXTSETTING";
const string CkTest = "CKSETTING";
public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
//
// TODO: Add any constructor code after InitializeComponent call
//
// for the cf, allusers must be true;
oSettings = new CSharp2003WindowsApplication1.CSettings(true);
}
private void btnClearSettings_Click(object sender, System.EventArgs e)
{
this.txtTestTextSetting.Text = String.Empty;
this.CheckBox1.Checked = false;
}
private void btnGetSettings_Click(object sender, System.EventArgs e)
{
this.txtTestTextSetting.Text = oSettings.GetSetting(AppTitle, Settings, TextTest, "Not Set");
this.CheckBox1.Checked = oSettings.GetSetting(AppTitle, Settings, CkTest, false);
}
private void btnSaveSettings_Click(object sender, System.EventArgs e)
{
oSettings.SaveSetting(AppTitle, Settings, TextTest, thistxtTestTextSetting.Text);
oSettings.SaveSetting(AppTitle, Settings, CkTest, thisCheckBox1.Checked);
}
|
This code is the C# code for CSettings.
Option Strict On
Imports System
Public Class CSettings
#Region " Class Variables "
Private ds As DataSet
Private xmlFile As String = String.Empty
Dim _AllUsers As Boolean
Const XML As String = ".xml"
Private _AlternatePath As String = String.Empty
#End Region
#Region " Public SaveSetting Overloaded Methods "
Public Overloads Sub SaveSetting(ByVal AppTitle As String, _
ByVal Settings As String, _
ByVal Key As String, _
ByVal Value As Boolean)
SaveSetting(AppTitle, Settings, Key, CStr(Value))
End Sub
Public Overloads Sub SaveSetting(ByVal AppTitle As String, _
ByVal Settings As String, _
ByVal Key As String, _
ByVal Value As Integer)
SaveSetting(AppTitle, Settings, Key, CStr(Value))
End Sub
Public Overloads Sub SaveSetting(ByVal AppTitle As String, _
ByVal Settings As String, _
ByVal Key As String, _
ByVal Value As String)
' this method sets or adds the value row for the passed key
Try
If xmlFile.Length = 0 Then SetupXMLFileName(AppTitle)
If ds Is Nothing Then
ds = New DataSet
Dim dt As DataTable = CreateDT(Settings, Key, Value)
ds.Tables.Add(dt)
Else
Dim dt As DataTable = ds.Tables(Settings)
If dt Is Nothing Then
' create new datatable named Settings
dt = CreateDT(Settings, Key, Value)
ds.Tables.Add(dt)
Else
Dim i As Integer
Dim b As Boolean
For i = 0 To dt.Rows.Count - 1
If CStr(dt.Rows(i).Item("key")) = Key Then
dt.Rows(i).Item("value") = Value
b = True
Exit For
End If
Next
If Not b Then
AddRow(dt, Key, Value)
End If
End If
End If
ds.WriteXml(xmlFile)
Catch ex As System.Exception
StructuredErrorHandler(ex)
End Try
End Sub
#End Region
#Region " Public Overloaded GetSetting Methods "
Public Overloads Function GetSetting(ByVal AppTitle As String, _
ByVal Settings As String, _
ByVal key As String, _
ByVal keyvalue As Integer) _
As Integer
Dim o As Object = GetSetting(AppTitle, Settings, key, CStr(keyvalue))
If o Is Nothing Then
Return keyvalue
Else
Return CType(o, Integer)
End If
End Function
Public Overloads Function GetSetting(ByVal AppTitle As String, _
ByVal Settings As String, _
ByVal key As String, _
ByVal keyvalue As Boolean) _
As Boolean
Dim o As Object = GetSetting(AppTitle, Settings, key, CStr(keyvalue))
If o Is Nothing Then
Return keyvalue
Else
Return CType(o, Boolean)
End If
End Function
Public Overloads Function GetSetting(ByVal AppTitle As String, _
ByVal Settings As String, _
ByVal key As String, _
ByVal keyvalue As String) _
As Object
Dim i As Integer
Dim dr As DataRow
Dim dt As DataTable
Try
If xmlFile.Length = 0 Then SetupXMLFileName(AppTitle)
' this method returns the value specified by the key
If ds Is Nothing Then
dt = GetXml(Settings)
If dt Is Nothing Then Return keyvalue
Else
dt = ds.Tables(Settings)
End If
For i = 0 To dt.Rows.Count - 1
dr = dt.Rows(i)
If CStr(dr("Key")) = key Then
Return dr("Value")
End If
Next
Return keyvalue
Catch ex As System.Exception
StructuredErrorHandler(ex)
End Try
End Function
#End Region
#Region " Private Methods "
Private Function CreateDT(ByVal Settings As String, ByVal key As String, _
ByVal value As Object) As DataTable
Dim dt As DataTable
dt = New DataTable(Settings)
dt.Columns.Add("Key", Type.GetType("System.String"))
dt.Columns.Add("Value", Type.GetType("System.String"))
AddRow(dt, key, value)
Return dt
End Function
Private Sub AddRow(ByRef dt As DataTable, ByVal key As String, _
ByVal value As Object)
Dim newRow As DataRow = dt.NewRow
newRow(0) = key
newRow(1) = value
dt.Rows.Add(newRow)
End Sub
Private Function GetXml(ByVal tablename As String) As DataTable
If Not IO.File.Exists(xmlFile) Then
Return Nothing
End If
ds = New DataSet
ds.ReadXml(xmlFile)
Dim dt As DataTable = ds.Tables(tablename)
Return dt
End Function
Private Sub SetupXMLFileName(ByVal fn As String)
' Returns filename for xmlfile, generated by using
' AppTitle suppliied to the two public methods and then
' boolean supplied to the constructor.
' install directory may be locked so check to see if
' caller supplied an alternate directory.
Dim s As String
If _AlternatePath.Length = 0 Then
s = IO.Path.GetDirectoryName(Reflection.Assembly. _
GetExecutingAssembly.GetModules(0).FullyQualifiedName)
Else
s = IO.Path.GetDirectoryName(_AlternatePath)
End If
' compact framework does not support user logon, so
' we don't support multiple app files on the cf
' If _AllUsers Then
xmlFile = s & "\" & fn & XML
' Else
' xmlFile = s & "\" & fn & "_" & Environ("UserName") & XML
' End If
End Sub
#End Region
#Region " Constructor "
Public Sub New(ByVal AllUsers As Boolean)
Me._AllUsers = AllUsers
End Sub
#End Region
#Region " Property Methods "
Public Property AlternatePath() As String
Get
Return _AlternatePath
End Get
Set(ByVal Value As String)
_AlternatePath = Value
End Set
End Property
#End Region
End Class
|
Top of Page
Figure 4 - C# Code for CSetting Class
using System;
using System.Reflection;
using System.Data;
namespace CSharp2003WindowsApplication1
{
/// <summary>
/// Summary description for CSettings.
///
public class CSettings
{
#region " Class Variables "
private DataSet ds;
private string xmlFile = String.Empty;
private bool m_AllUsers;
const string XML = ".xml";
private string m_AlternatePath = String.Empty;
#endregion
#region " SaveSetting Methods "
public void SaveSetting(string AppTitle,
string Settings, string Key, bool Value)
{
SaveSetting(AppTitle, Settings, Key, Value.ToString());
}
public void SaveSetting(string AppTitle,
string Settings, string Key, int Value)
{
SaveSetting(AppTitle, Settings, Key, Value.ToString());
}
public void SaveSetting(string AppTitle,
string Settings, string Key, string Value)
{
if (xmlFile.Length==0)
SetupXMLFileName(AppTitle);
if (ds == null)
{
ds = new DataSet();
DataTable dt = CreateDT(Settings,Key,Value);
ds.Tables.Add(dt);
}
else
{
DataTable dt = ds.Tables[Settings];
if (dt == null)
{
// create new datatable
dt = CreateDT(Settings,Key,Value);
ds.Tables.Add(dt);
}
else
{
bool b=false;
for (int i = 0; i < (int) dt.Rows.Count;i++)
{
if((string)dt.Rows[i].ItemArray[0] == Key)
{
dt.Rows[i].ItemArray[1] = Value;
b = true;
break;
}
}
if (b != true)
AddRow(ref dt, Key, Value);
}
}
ds.WriteXml(xmlFile);
}
#endregion
#region " GetSetting Methods "
public int GetSetting(string AppTitle, string Settings,
string Key, int KeyValue)
{
string o = GetSetting(AppTitle,Settings,Key,KeyValue.ToString().ToLower());
if (o == null)
return KeyValue;
else
return int.Parse(o);
}
public bool GetSetting(string AppTitle, string Settings,
string Key, bool KeyValue)
{
string o = GetSetting(AppTitle,Settings,Key,KeyValue.ToString().ToLower());
if (o == null)
return KeyValue;
else
return bool.Parse(o);
}
public string GetSetting(string AppTitle, string Settings,
string Key, string KeyValue)
{
DataRow dr;
DataTable dt;
if (xmlFile.Length == 0)
SetupXMLFileName(AppTitle);
if (ds == null)
{
dt = GetXml(Settings);
if (dt == null)
return KeyValue;
}
else
|
|