C#4.0 – Problematik bei Default Values

Golo Roden erwähnte es bereits in den Kommentaren, daher möchte ich noch mal genauer darauf eingehen.
Dazu erstelle ich eine Solution in Visual Studio 2010 mit einer Konsolenapplikation, welche ich „DefaultValues“ nenne. C#4.0 – Problematik bei Default Values weiterlesen

C# 4.0 – Default Values und Delegates

Mit C# 4.0 gibt es sogenannte Default Values. Das heißt, ich kann den Parametern bei einem Methodenaufruf bereits definierte Werte mitgeben.
Beispiel:

void Foobar(string valueWithoutDefaultValue, string valueWithDefaultValue = "Ich bin ein Default Value") {
   // ..
}

Ich kann den 2. Parameter nun mit geben oder es eben sein lassen. Mehr dazu findet ihr hier. Nun wollte ich dies bei einem Delegaten ausnutzen. Der Delegate feuert nur mit einem Parameter, die Methode hat aber zwei Parameter, wobei der zweite einen Defaultwert hat.

public delegate void DelegateFoobar(string text);
public event DelegateFoobar foobarEvent;

Dies funktioniert nicht, der Compiler spuckt folgende Fehlermeldung:

No overload for 'Foobar' matches delegate 'TestApp.Classes.Test.foobarEvent'

Schade eigentlich, denn meiner Interpretation nach sollte es funktionieren. Gelöst habe ich es mit eine Lambda Expression:

testclass.foobarEvent += str => this.Foobar(str);

Funktioniert ohne Probleme.

C# – PrintDialog.ShowDialog() funktioniert nicht

Bin gerade auf ein sehr merkwürdiges Problem gestoßen, dass doch locker eine Stunde wertvolle Lebenszeit gekostet hat.
Folgender Code:

PrintDialog pd = new PrintDialog();
if (pd.ShowDialog() == DialogResult.OK)
{
    // do nothing

}

Nichts großes, sollte einfach nur so ein Druckerfenster öffnen, wo der Drucker ausgewählt wird etc. Leider öffnete sich der erhoffte Dialog nicht. Der Debugger läuft dahin, aber er führt den ShowDialog() einfach nicht aus.

Wenn ich die Eigenschaft „UseEXDialog“ auf „true“ setze, funktioniert es.
Jedoch wollte ich nicht den XP-Dialog, sondern den anderen. Auch im Netz fand ich keine wirkliche Lösung.
Da diese Codezeilen aus einem bestehenden Projekt stammen, habe ich kurzerhand neue Projekte in den Frameworks 2.0, 3.5 und 4.0 angelegt. Jeweils mit dem Codeschnippsel oben. Und siehe da, es funktioniert problemlos, in jeder Frameworkversion. Nun die Unterschiede gesucht.

Fündig wurde ich den Projekteigenschaften unter „Build“ bzw. „Erstellen“.
Ich muss dazu sagen, dass die Applikation vorher auf einem anderen Rechner mit einem 32-bit Windows entwickelt wurde. So stand hier unter dem Punkt „Platform target:“ (auf Deutsch vermutlich Zielplattform) „Any CPU“.
Stellt die Anwendung hier auf 32-bit (x86) und der PrintDialog() wird hervorragend funktionieren. x64 oder Any CPU funktioniert nicht.
Auf so etwas muss man erstmal kommen, warum das so ist, keine Ahnung.

So habe ich noch mal in der MSDN nachgeschlagen:

This class may not work on AMD64 microprocessors unless you set the UseEXDialog property to true.

Ich bin zwar nun nicht der technisch versierte Mensch, aber für mich hört sich das nach einem Problem mit einem AMD Prozessor an, ich habe jedoch einen Intel (ich lasse es mir aber dennoch gerne erklären).

HowTo: Aero Glass in C# Forms nutzen

Mich hat mal interessiert, wie ich die Aero Glass Effekte unter Windows 7 in C# Windows Forms nutzen kann. Auf codeproject.com fand ich dazu einen Artikel. Der funktioniert soweit auch schon ganz gut. Der Artikel zeigt, wie man einen Rand um seine Arbeitsfläche zieht, der den Aero Glass Effekt nutzt. Möchte man nun aber den ganzen Hintergrund durchsichtig haben, so müssen die Margins auf -1 gesetzt werden:

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            if (DwmIsCompositionEnabled())
            {
                // Paint the glass effect.
                this.margins = new MARGINS {Top = -1, Left = -1, Bottom = -1, Right = -1};
                DwmExtendFrameIntoClientArea(this.Handle, ref margins);
            }
        }

Nun ist der ganze Arbeitsbereich durchsichtig. Doch sobald man GDI+-Controlls verwendet, ergibt sich folgender Grafikfehler:

Um dies zu umgehen, müsst ihr in der Main()-Methode folgendes einfügen (bzw. anpassen)

Application.SetCompatibleTextRenderingDefault(true);

Das Ergebnis sieht schon besser aus, leider immer noch nicht so wie gewünscht.

Leider liegt das aber am System bzw. den Controls im .NET-Framework. Unter WPF gibt es dieses Problem zum Beispiel nicht.
Wie ihr die Aero Glass Effekte in WPF nutzen könnt, findet ihr etwa bei Robert Mühsig.

Ach ja, falls ihr nun Bereiche haben wollt, die nicht durchsichtig sind, könnt ihr zum Beispiel ein Panel nutzen. Das Ergebnis sieht in etwa so aus:

Lokaler Pfad bei SQLite Datenbank und ASP.NET

Ich probiere mich gerade in ASP.NET und um nicht gleich einen SQL-Server aufsetzen zu müssen, nutze ich SQLite. Die Abfragen sind ähnlich und zum Rumspielen reicht das dicke hin. Zudem habe ich schon ein paar Erfahrungen mit einem anderen Tool gesammelt. Nun hatte ich folgendes Phänomen, ganz am Anfang hatte ich die Datenbank erstellt mit irgendwelchen Dummyeinträgen und ein bischen mit den Ajaxelementen von Visual Studio rumgespielt.
Das hat auch gut geklappt, das auslesen der Daten lief im Hintergrund per SQLiteConnection(). Dann habe ich mir ein reines HTML Formular gebastelt und wollte hier eine Art Login ausprobieren. Auf einmal kam jedes mal die Fehlermeldung, dass die Datenbank „Users“ nicht gefunden wurde (Users war die von mir erstellte).

System.Data.SQLite.SQLiteException: SQLite error
no such table: Users
   bei System.Data.SQLite.SQLite3.Prepare(SQLiteConnection cnn, String strSql, SQLiteStatement previous, UInt32 timeoutMS, String& strRemain)
   bei System.Data.SQLite.SQLiteCommand.BuildNextCommand()
   bei System.Data.SQLite.SQLiteCommand.GetStatement(Int32 index)
   bei System.Data.SQLite.SQLiteDataReader.NextResult()
   bei System.Data.SQLite.SQLiteDataReader..ctor(SQLiteCommand cmd, CommandBehavior behave)
   bei System.Data.SQLite.SQLiteCommand.ExecuteReader(CommandBehavior behavior)
   bei System.Data.SQLite.SQLiteCommand.ExecuteReader()
   bei ASPGuestbook.LoginForm.checkLogin() in ...\LoginForm.aspx.cs:Zeile 57.

Unter Visual Studio konnte ich die SQLite Datenbank ohne Probleme bearbeiten. Die Datei war auch im selben Verzeichnis. Ich hatte mir auch per AppDomain.CurrentDomain.BaseDirectory das Verzeichnis ausgeben lassen. Hat auch alles gepasst.
Mein Befehl zum Öffnen lautete so:

SQLiteConnection sqlCon = new SQLiteConnection("Data Source=datenbank.db3;Password=12345;");
sqlCon.Open();

Natürlich schön im try / catch Block verpackt, es kam aber keine Fehlermeldung. Hat einen Moment gedauert bis ich dahinter kam. Und zwar hat die SQLite Erweiterung die ich nutze die dumme Angewohnheit, wenn Data Source nicht existiert, dass er eine leere Datenbank anlegt. In dieser leeren Datenbank gibt es natürlich nicht die Tabellen und folglich der Fehler. Angelegt hat er diese leeren Datenbanken übrigends unter

C:\Programme\Microsoft Visual Studio 9.0\Common7\IDE

Darauf muss man erstmal kommen..
So funktioniert es dann, ob es die optimale Lösung ist, bezweifel ich.

SQLiteConnection sqlCon = new SQLiteConnection("Data Source=" + AppDomain.CurrentDomain.BaseDirectory + "bin\\datenbank.db3;Password=12345;");
sqlCon.Open();

Das Problem lässt sich sicherlich auch auf andere Sprachen adaptieren. Bei einem richtigen SQL Server fällt das ja sowieso weg, aber nervig wars trotzdem!