Biggle's Blog

Web- und Software Development

by Mario Binder

Einführung C# – Videos

Auf Twitter habe ich ja schon erwähnt, dass Prof. Dr Jörn Loviscach jede Menge Informatik-Videos hochgeladen hat. Für die C# Entwickler hat der gute Prof. einen ganzen Batzen dieser Lehrfilmchen bereit gestellt. Vielen Dank dafür!

Informatik 2, Sommer 2011

14:30:33

Dran bleiben, da kommt bestimmt noch was!

Viel Spaß beim entwickeln : )

by Mario Binder

Prüfen ob ein String eine Guid ist

Es gibt jede Menge Ansätze, um zu prüfen ob ein String eine Guid ist. Zum einen ist es möglich, den String mit RegEx zu prüfen:

1
2
3
4
5
6
using System.Text.RegularExpressions;
...
private bool IsStringValidGuid(string s)
{
    return string.IsNullOrEmpty(s) ? false : new Regex(@"^(\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\}{0,1})$").IsMatch(s);
}

Als ExtensionMethod könnte das wie folgt aussehen:

1
2
3
4
5
6
using System.Text.RegularExpressions;
...
public static bool IsStringValidGuid(this string s)
{
    return string.IsNullOrEmpty(s) ? false : new Regex(@"^(\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\}{0,1})$").IsMatch(s);
}

Zum anderen kann man sich jeden Character in dem String anschauen und prüfen ob dieser im Hexadezimalsystem vorkommt.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/// <summary>
/// Prueft ob der uebergebene String eine Guid ist.
/// </summary>
/// <param name="s">string</param>
/// <returns>bool</returns>
public bool IsStringValidGuid(string s)
{
    int hexchars = 0;
    foreach (char c in s)
    {
        if (IsValidHexChar(c))
            hexchars++;
    }
    return hexchars == 32;
}
private bool IsValidHexChar(char hexChar)
{
    return (hexChar >= 0x30 && hexChar <= 0x39) //IsValidHexDigit
        || (hexChar >= 0x61 && hexChar <= 0x66) //IsValidLowerHexLetter
        || (hexChar >= 0x41 && hexChar <= 0x46); //IsValidUpperHexLetter
}

Als ExtensionMethod:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/// <summary>
/// Prueft ob der uebergebene String eine Guid ist.
/// </summary>
/// <param name="s">string</param>
/// <returns>bool</returns>
public static bool IsStringValidGuid(this string s)
{
    int hexchars = 0;
    foreach (char c in s)
    {
        if (IsValidHexChar(c))
            hexchars++;
    }
    return hexchars == 32;
}
private bool IsValidHexChar(char hexChar)
{
    return (hexChar >= 0x30 && hexChar <= 0x39) //IsValidHexDigit
        || (hexChar >= 0x61 && hexChar <= 0x66) //IsValidLowerHexLetter
        || (hexChar >= 0x41 && hexChar <= 0x46); //IsValidUpperHexLetter
}

Die RegEx-Version finde ich eleganter (da Einzeiler), jedoch die Zeichen einzeln zu prüfen, finde ich für das Verständnis besser.

Wie auch immer, funktionieren werden sicher noch mehr Wege…
In diesem Sinne, viel Spaß beim entwickeln : )

by Mario Binder

Bedingte Formatierung im Datagrid – WPF Quicky

Die Frage auf Codekicker lautete:

Wie kann ich in einem DataGrid eine Zelle je nach Inhalt formatieren? So wie die Bedingte Formatierung in Excel oder Access, also rot bei negativen Werten und grün bei positiven Werten. Hab schon mein Glück mit einem Converter versucht, aber das klappt irgendwie nicht.

Ich habe dazu einen Converter geschrieben, der den Wert entgegen nimmt, diesen auf kleiner 0 prüft und das Resultat als Brush für den Hintergrund zurück gibt. Ist der Wert kleiner 0 wird grün, ist der Wert größer 0 wir rot zurück gegeben.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
    if (value.ToString() == String.Empty)
        return null;
 
    decimal val = decimal.Parse(value.ToString());
 
    return (val < 0) ? Brushes.Red : Brushes.Green;
}
 
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
    return value;
}
}

Im XAML muss in der Windows Resource der Converter referenziert werden:

1
2
3
<Window.Resources>
    <Converters:SignedUnsignedConverter x:Key="SignedUnsigned" />
</Window.Resources>

Das DataGrid verwendet den Converter wie folgt:

1
2
3
4
5
6
7
8
9
10
11
12
<DataGrid Name="dataGrid" AutoGenerateColumns="False" MouseDoubleClick="dataGrid_MouseDoubleClick">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Name" Binding="{Binding Name}" />
        <DataGridTemplateColumn Header="Price">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Price}" Background="{Binding Price, Converter={StaticResource SignedUnsigned}}" />
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>

Auch in einer TextBox kann der Converter verwendet werden:

1
<TextBox Name="textBox" Background="{Binding ElementName=textBox, Path=Text, Converter={StaticResource SignedUnsigned}}"/>


Viel Spaß beim entwickeln : )

by Mario Binder

SQLite Datenbanken in C# Applikationen verwenden

System.Data.SQlite aus dem Hause phxsoftware bietet eine Schnittstelle zur Verwendung von portablen Datenbanken im SQLite Format. Im Folgenden möchte ich zeigen, wie man diese auf unterschiedlicher Weise, in C# Applikationen verwenden kann.

Um eine SQLite Datenbank zu erstellen, gibt es eine Menge von Managementapplikationen oder auch Browsererweiterungen, z.b für den Firefox. Ich verwende, um mir erstmalig eine Datenbank zu erstellen, den kostenlosen SQLiteBrowser. Die erstellte Datenbank speichere ich dann in meinem TestProjekt, mit welchem ich auf diese zugreifen möchte.

Als erstes holen wir uns die Installation oder die Binaries. Je nach Architektur wird dann im Projekt, auf die entsprechende dll referenziert. Ich verwende die System.Data.SQLite.dll für x86, welche sich im bin Ordner befindet.

SQLiteCommand

Im ersten Beispiel, verwende ich die SQLiteCommand-Klasse, um auf die Datenbank zugreifen.

Nach dem Einbinden des Namespace “using System.Data.SQLite;” stehen uns die Klassen SQLiteConnection und SQLiteCommand zur Verfügung. (Mehr benötigen wir erstmal in unserem Beispiel nicht.)

Den Pfad, zur zuvor angelegten Datenbank lege ich in der app.config fest, damit dieser konfigurierbar bleibt:

1
2
3
4
5
<configuration>
  <appSettings>
    <add key="DATASOURCE" value="../../DataBase/data" />
  </appSettings>
</configuration>

im Code dann (namens DataProvider.cs), holen wir uns den Pfad über den ConfigurationManager in eine KlassenVariable. Hier muss explizit auf System.Configuration referenziert werden

1
private string DataSource = ConfigurationManager.AppSettings.Get("DATASOURCE");

Das Speichern, Emitteln und Löschen erledigen wir über das SQLiteCommand. Zum Öffnen und Schließen der SQLiteConnection habe ich mir zwei Methoden geschrieben:

1
2
3
4
5
6
7
8
SQLiteConnection connection;
 
private void OpenConnection()
{
    connection = new SQLiteConnection();
    connection.ConnectionString = "Data Source=" + DataSource;
    connection.Open();
}
1
2
3
4
5
private void CloseConnection()
{
    connection.Close();
    connection.Dispose();
}

Speichern von Einträgen

1
2
3
4
5
6
7
8
9
10
11
OpenConnection();
 
using (var command = new SQLiteCommand(connection))
{
    command.CommandText = string.Format("INSERT INTO Entities (Beschreibung, HtmlName, Unicode, Zeichen) VALUES('{0}', '{1}', '{2}', '{3}')",
                    entity.Beschreibung, entity.HtmlName, entity.Unicode, entity.Zeichen);
 
    command.ExecuteNonQuery();
}
 
CloseConnection();

Ermitteln von Einträgen

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
OpenConnection();
 
List<HtmlEntity> entities = new List<HtmlEntity>();
using (var command = new SQLiteCommand(connection))
{
    command.CommandText = "SELECT * FROM Entities";
 
    using (SQLiteDataReader reader = command.ExecuteReader())
    {
        while (reader.Read())
        {
            entities.Add(new HtmlEntity
            {
                Beschreibung = reader[0].ToString(),
                HtmlName = reader[1].ToString(),
                Unicode = reader[2].ToString(),
                Zeichen = reader[3].ToString()
 
            });
        }
        reader.Close();
    }
}
 
CloseConnection();

Löschen von Einträgen

1
2
3
4
5
6
7
8
9
10
11
OpenConnection();
 
using (var command = new SQLiteCommand(connection))
{
    command.CommandText = string.Format("DELETE FROM Entities WHERE Beschreibung = '{0}' AND HtmlName = '{1}' AND Unicode = '{2}' AND Zeichen =  '{3}'",
        entity.Beschreibung, entity.HtmlName, entity.Unicode, entity.Zeichen);
 
    command.ExecuteNonQuery();
}
 
CloseConnection();

Achtung! Es ist möglich, das die SQLite Assembly sich nicht mit dem 4.0 .NET  kompilieren lässt. (Mixed mode assembly is built against version ‘v2.0.50727′ of the runtime and cannot be loaded in the 4.0 runtime without additional configuration information), hier kann man sich aber mit folgendem Eintrag, innerhalb des “configuration-Knoten” in der app.config behelfen

1
2
3
<startup useLegacyV2RuntimeActivationPolicy="true">
	<supportedRuntime version="v4.0"/>
</startup>

Tipp via: stackoverflow


SQLite & Entity Framework

Es ist auch möglich, eine SQLite Datenbank als Datensource für ein Entity-Framework-Model anzugeben. Das erstelle Entity FrameworkModel stellt uns nun den Kontext bereit, Einträge zu persistieren, zu ermitteln und zu löschen.

Eintrag speichern

1
2
3
4
5
6
7
8
public void  InsertData(HtmlEntity entity)
{
    using (var context = new HtmlEntityEntities())
    {
        context.AddToEntities(entity);
        context.SaveChanges();
    }
}

Einträge ermitteln

1
2
3
4
5
6
7
8
9
10
11
12
13
public List<HtmlEntity> GetAllHtmlEntities()
{
    List<HtmlEntity> entities;
 
    using (var context = new HtmlEntityEntities())
    {
        entities = (from e in context.Entities
                    select e).ToList();
 
    }         
 
    return entities;
}

Eintrag löschen

1
2
3
4
5
6
7
8
9
10
11
public void DeleteData(HtmlEntity entity)
{
    using (var context = new HtmlEntityEntities())
    {
        HtmlEntity obj = (HtmlEntity)context.GetObjectByKey(entity.EntityKey);
 
 
        context.DeleteObject(obj);
        context.SaveChanges();
    }
}

LINQ to SQLite

Wie wir an den EF Methoden gesehen haben, können wir nun einfach mit LINQ die Operationen ausführen.

Am Beispiel “Einträge ermitteln” wurde LINQ bereits verwendet, diese kann dann natürlich auch durch eine Where-Klausel erweitert werden:

1
2
3
4
5
6
using (var context = new HtmlEntityEntities())
{  
    return (from e in context.Entities                        
            where e.Beschreibung == keyword                      
            select e).FirstOrDefault();
}

Auch wenn es so scheint, dass die System.Data.SQLite.Linq.dll wichtig für den Zugriff mit LINQ ist, wir benötigen diese dll nicht, denn durch das generieren des EF Models, steht uns hier LINQ aus dem Framework zu Verfügung.

Fragen? Einfach in den Kommentaren damit. Viel Spaß beim entwickeln : )

by Mario Binder

Biggle ist kein Palindrom

Eine kleine Übungsaufgabe für mich, die es zu lösen gab. Es sollte heraus gefunden werden, ob es sich bei einem String um ein Palindrom handelt.

Mein Lösungsansatz lautet wie folgt:
Ich befreie zunächst die Buchstaben von Sonder- und Leerzeichen und konvertiere alle Zeichen zu Kleinbuchstaben. Dann durchlaufe ich eine for-Schleife mit eine Länge des Stringparameters.

Ich zerlege den String in ein CharArray und vergleiche innerhalb der Schleife, den vorderen mit den letzten Buchstaben. Sind diese gleich wird der nächste vordere und der nächste hintere Buchstabe verglichen. Das geht so lange bis diese sich in der Mitte treffen.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public static class ExtensionMethods
{
    public static bool IsPalindrome(this string value)
    {
        //von Leer- und Sonderzeichen befreien
        value = value.ToLower().RemoveSpecialCharacters();
 
        int minValue = 0;
        int maxValue = value.Length - 1;
 
        var charArray = value.ToCharArray();
 
        for (int i = 0; i < value.Length - 1; i++)
        {
            if (charArray[minValue] == charArray[maxValue])
            {
                minValue++;
                maxValue--;
                continue;
            }
            else
                return false;
        }
        return true;
    }
 
    public static string RemoveSpecialCharacters(this string value)
    {
        return Regex.Replace(value, @"[^a-zA-Z0-9]", string.Empty);
    }
}

Verwendung:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Program
{
    static void Main(string[] args)
    {
        PalindromFactory factory = new PalindromFactory();
        var palindrome = factory.GetPalindrome();
        string output = "{0} ist {1}ein Palindrom";
 
        foreach (var palindrom in palindrome)
        {
            Console.WriteLine(String.Format(output, palindrom, palindrom.IsPalindrome() ? "" : "k"));
        }
 
        var palindromSaetze = factory.GetPalindromSaetze();
        foreach (var palindrom in palindromSaetze)
        {
            Console.WriteLine(String.Format(output, palindrom, palindrom.IsPalindrome() ? "" : "k"));
        }
    }
}

Ich hoffe ich habe nichts vergessen, getestet jedoch habe ich diese Methode mit der Liste deutscher Palindrome aus Wikipedia. Nicht-Palindrome natürlich mit einbegriffen : )

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
/// Stellt eine Sammlung von Palindrome und Palindromsätze bereit
/// Quelle Wikipedia
/// http://de.wikipedia.org/wiki/Liste_deutscher_Palindrome
public class PalindromFactory
{
    private List<string> Palindrome { get; set; }
 
    public List<string> GetPalindrome()
    {
        Palindrome = new List<string>
        {
            "Aha",
            "Amokoma",
            "Amoralaroma",
            "Anina",
            "Anna",
            "Annasusanna",
            "Aua",
            "Bob",
            "Bub",
            "Burggrub",
            "Biggle", //kein Palindrom
            "Mario", //kein Palindrom
            "Mongognom",
            "Nebelleben",
            "neben",
            "Neffen",
            "nennen",
            "netten",
            "netzten",
            "Neozoen",
            "nun",
            "Omo",
            "Otto",
            "Priebe" //kein Palindrom
            };
 
        return Palindrome;
    }
 
    public List<string> GetPalindromSaetze()
    {
        Palindrome = new List<string>
        {
            "Die Liebe fleht: Helfe bei Leid!",
            "Die Liebe geht, hege Beileid!",
            "Die Liebe, ist sie Beileid?",
            "Die Liebe ist Sieger, rege ist sie bei Leid.",
            "Die Liebe ist Sieger, stets rege ist sie bei Leid.",
            "Die Niere bot Komik: nass sank im Oktober ein Eid.",
            "Die Rede — ist sie der Eid?",
            "Dreh Magiezettel um, Amulette zeig am Herd!",
            "Du, erfror Freud?",
            "Der Fred",
            "Eine güldne, gute Tugend: Lüge nie!",
            "Eine Horde bedrohe nie!",
            "Eine Hure ruhe nie.",
            "Eine Note betone nie.",
            "Eine so Kesse kose nie.",
            "Eine treue Familie bei Lima feuerte nie.",
            "Einhorn roh? Nie!",
            "Eins nutzt uns: Amore. Die Rederei da, die Rederei der Omas nutzt uns nie.",
            "Eis feil! Ei, wo Eis feil lief sie, o wie lief sie.",
            "Elietta hat Teile.",
            "Ella rüffelte Detlef für alle.",
            "Elly biss Sibylle.",
            "Emma, behend 'ne Hebamme!",
            "Emma, so litt Tilos Amme!",
            "Emmas Amme",
            "Er habe nie eine Bahre.",
            "Erhabene Bahre",
            "Erhöre nie eine Röhre.",
            "Erika feuert nur untreue Fakire.",
            "Erol, red nie in der Lore.",
            "Alles hat seine Zeit, nur die alten Weiber nicht.", //Kein Palindromsatz
            "Es eilt, immer ahnend Nebel, reger der Flegel Fred, reg' erlebend nen Harem mit Liese.",
        };
 
        return Palindrome;
 
    }
}

Für einen schnellen Verwendungszeck (weil man das auch so oft braucht oO)  habe ich das ganze als ExtensionMethod implementiert.

Wie schaut’s aus, hast du Verbesserungsvorschläge? Würdest du es anders machen, wenn ja wie? Du kannst im Kommentarfeld mit

<strong>var* </strong>deinCodeSnippet = 0;

posten.


Viel Spaß beim entwickeln : )


* = Var oder nicht var…

by Mario Binder

IsEven() – ExtensionMethod | C# Quicky

Um in einem Programm zu ermitteln, ob eine Zahl gerade oder ungerade ist, kann man den Modulo-Operator verwenden. Das Ganze in einer ExtensionMethod verpackt ist zudem auch noch benutzerfreundlich. Wie folgt könnte man das Ganze implementieren:

1
2
3
4
5
6
7
public static class ExtensionMethods
{
    public static bool IsEven(this int value)
    {
        return value % 2 == 0;
    }
}

Verwendung:

Console.WriteLine(12.IsEven().ToString());

Ausgabe: true

VIel Spaß beim entwickeln : )