Søg på DotNyt:
Denne blog er flyttet til www.nielsbrinch.com


lørdag den 23. august 2008

Håndtering af data i Windows Mobile

skrevet af Niels Brinch

Jeg har skruet farten lidt ned efter lynprogrammeringen af en lille applikation til min telefon. Dog er jeg ikke gået væk fra at kode mens der er kylling i ovnen.

Jeg går nu lidt dybere ned og kigger på de forskellige detaljer som kan drille, når man som Windows- eller webudvikler kaster sig over at udvikle en Windows Mobile applikation. I dette tilfælde mangler jeg en "Settings"-mulighed i applikationens menu. Der plejer jeg at gemme simple indstillinger, såsom brugerens valg fra sidste gang, så brugeren ikke behøver ændre indstillinger, hvis brugeren bare vil have applikationen til at fungere ligesom sidst.

image

Men det menupunkt findes ikke i en applikation til Windows Mobile (Smart Device project). Derfor må jeg finde en anden måde at gemme brugerindstillinger på.

Efter en Google-søgning synes den mest oplagte løsning at være at lægge en database i forbindelse med mit projekt. Det kan hurtigt blive relevant i andre sammenhænge, at have en database knyttet til sin applikation, så øvelsen er fin.

OBS: Denne løsning er kun relevant for applikationer der skal køre .NET 3.5. Skal applikationen køre på .NET 2.0 anbefales det at anvende en løsning baseret på txt eller xml filer i stedet.

I Visual Studio, højreklik på projektet, add new item og vælg Data -> Database File.

image

Når nu der ikke følger en Settings-klasse med i projektet, må jeg lave en selv. Den skal indeholde gymnastik til at hente og gemme indstillinger i databasen og så skal den gøre det let at anvende indstillingerne fra applikationen.

I databasen opretter jeg en tabel, Settings, med to kolonner: Key og Value, som skal give mig mulighed for dynamisk at tilføje lige så mange indstillinger som jeg har lyst til. Dermed kan jeg også bruge denne klasse til senere projekter der skal anvende Windows Mobile.

For at skabe forbindelse til databasen anvendes en SqlCeConnection, hvor Ce formentlig henviser til det faktum, at tidligere versioner af Windows til mobilen hed Windows CE. Det gøres som vist herunder:

public static SqlCeConnection GetSqlCeConnection()
{
string connString = Assembly.GetExecutingAssembly().GetName().CodeBase;
connString = connString.Replace("Timer.exe", "TimerDB.sdf");
SqlCeConnection conn = new SqlCeConnection(String.Format("Data Source={0}", connString));
return conn;
}

Stien til databasen findes ret kreativt ved at anvende Reflection til at finde stien til applikationen selv og så udskifte applikationens navn i stien med databasefilens navn, som jo ligger samme sted. Jeg fandt tricket på nettet - tror det var i CodeProject et sted.


Koden til at hente en indstilling fra databasen er meget velkendt. Dog et lille kuriosum at jeg ikke kunne få parametre til at virke. Ellers ville jeg selvfølgelig have brugt @key i stedet for det noget mindre elegante: '"+ key + "'.


Man kan heller ikke uden videre bruge "reader.HasRows" på en reader, men kan selvfølgelig benytte "Read()".


private static string GetSetting(string key)
{
SqlCeConnection conn = GetSqlCeConnection();
conn.Open();

string query = "SELECT [value] " +
"from Settings " +
"where [key] = '"+key+"'";

SqlCeCommand cmd = new SqlCeCommand(query, conn);
cmd.CommandType = CommandType.Text;

SqlCeDataReader reader = cmd.ExecuteReader();

string value = null;

if (reader.Read())
{
value = reader.IsDBNull(0) ? null : reader.GetString(0);
}

reader.Close();

return value;
}

Jeg har selvfølgelig også den metode der modsvarer GetSetting, nemlig SetSetting. Denne tager af en eller anden grund gerne mod parametre - ved stadig ikke hvad jeg gjorde forkert i GetSetting, siden den ikke ville godtage dem. Pyt.


For komplethedens skyld er her koden til SetSetting.


private static void SetSetting(string key, string value)
{
SqlCeConnection conn = GetSqlCeConnection();

conn.Open();

string query = null;

if (GetSetting(key) == null)
{
query = "INSERT INTO Settings "+
"([key], [value]) " +
"VALUES " +
"(@key, @value)";
}
else
{
query = "UPDATE Settings " +
"SET [value] = @value " +
"WHERE " +
"[key] = @key";
}

SqlCeCommand cmd = new SqlCeCommand(query, conn);
cmd.CommandType = CommandType.Text;
cmd.Parameters.Add("@key", SqlDbType.NVarChar).Value = key;
cmd.Parameters.Add("@value", SqlDbType.NVarChar).Value = value;

cmd.ExecuteNonQuery();

conn.Close();
}

De tre metoder herover kan jeg benytte direkte fra min applikation ved at kalde GetSetting og SetSetting direkte, men som du kan se, har jeg gjort dem private. Jeg ønsker ikke de bliver kaldt direkte, da det ville opfordre til at skrive en masse strengværdier som keys under anvendelsen.


I stedet laver jeg en property for hver indstilling der skal kunne anvendes.


public static string SoundPath
{
get { return GetSetting("SoundPath"); }
set { SetSetting("SoundPath", value); }
}

Der er nu en komplet klasse som kan anvendes til at håndtere data, f.eks. brugerindstillinger, i en Windows Mobile applikation. Den er temmelig generel, så jeg kan anvende den igen og igen. Og det kan du også.


Nyd her til sidst metoden der tillader brugeren at vælge hvilken lyd applikationen skal afspille.



   1:  private void btnSound_Click(object sender, EventArgs e)
   2:  {
   3:      DialogResult result = openFileDialog1.ShowDialog();
   4:   
   5:      if (result == DialogResult.OK)
   6:      {
   7:          player.SoundLocation = openFileDialog1.FileName;
   8:          player.Load();
   9:   
  10:          Settings.SoundPath = player.SoundLocation;
  11:      }
  12:  }

Indstillingen sættes i linje 10, så applikationen kan huske den valgte lyd til næste gang applikationen starter.

0 kommentarer

0 Kommentarer:

Send en kommentar

<< Tilbage


 
Til forsiden

Niels Brinch