BigBasti's Blog About Me & my Digital Lifestyle

13Sep/104

.NET Objekte zwischen Formularen verfuegbar machen

Immer häufiger sehe ich in Foren die Frage, wie man Informationen (Objekte) zwischen Formularen zugänglich machen kann. Dies ist eigentlich kein großes Unterfangen, wenn man erstmal verstanden hat wie es funktioniert.

Die VB-Programmierer werden hier wohl schon das Wort "Global" auf der Zunge liegen haben, aber wer diesen Artikel von mir gelesen hat, weis, dass ich das nicht gerne mag und deswegen euch hier andere Wege aufweisen werde.

Das Problem

Unser Problem ist, dass wir beispielsweise zwei Formulare haben, bei denen Form2 auf Informationen von Form1 zugreifen will. Da Objekte in .NET isoliert von einander laufen kann ein Objekt nicht einfach auf das andere zugreifen. Man muss diese Beiden Objekte mit einander bekannt machen bzw. diese mit einander verknüpfen.

Dieses Verknüpfen erreicht man mit Objektreferenzen. Dabei muss die Form die die andere Form aufruft eine Referenz auf das Objekt hinterlegen, dass dem anderen Formular bekannt sein soll und dieses an das fremde Form übergeben.

Die Lösung

Das beschriebene Vorhaben kann man auf verschiedenen Wegen erreichen, die sich aber relativ ähnlich sind. Ich möchte hier zwei recht ähnliche Methode zeigen, und eine die sich etwas unter scheidet.

Methode 1

Die Form die Informationen aus einer anderen Form benötigt erhält einen neuen Konstruktor der als Parameter die gewünschte Variable bekommt:


string wertAusForm1 = "";
public Form2(string info) {
    InitializeComponent(); //Wichtig!

    wertAusForm1 = info;
}

Hierbei ist "info" die Variable die wir aus der Form1 übergeben bekommen, diese ist vom Typ String, aber natürlich könnt ihr diese nach eurem Bedarf anpassen. Und auch in der menge seid ihr nicht begrenzt, ihr könnt den Konstruktor um beliebig viele Parameter erweitern. Wichtig ist, dass die "InitializeComponent()" Methode aufgerufen wird, falls ihr das Formular mit dem Visual Studio Designer gemacht habt, damit auch alle Komponenten initialisiert werden.

Aufruf aus Form1:


private void button1_Click(object sender, EventArgs e) {
    Form2 frm2 = new Form2(textBox1.Text);
    frm2.Show();
}

Der im Parameter übergebene Wert wird dann in der Klassen-variable "wertAusForm1" gespeichert und ist nun für das ganze Formular verfügbar.

Diese Methode ist sehr simpel und schnell implementiert, doch wird es zum Problem, wenn man viele Variablen übergeben möchte, so schwellen die Konstruktoren schnell mal auf mehrere Zeilen an. An diesem Problem setzt methode 2 an.

Methode 2

Diese Methode unterscheidet sich kaum von der vorherigen, doch diesmal wollen wir viele Variablen übergeben, unseren Konstruktor aber nicht unnötig aufblasen. Hier bietet es sich an das ganze Formular als Parameter zu übergeben um auf alle Objekte des Formulars Zugriff zu erhalten. So haben wir nur einen Parameter aber Zugriff auf alle variablen.

Form3 Konstruktor:


//METHODE 2
public Form3(Form1 form) {
    InitializeComponent();

    aufrufendeForm = form;

    this.label2.Text = aufrufendeForm.textBox2.Text + " - " +
                aufrufendeForm.textBox3.Text + " - " +
                aufrufendeForm.textBox4.Text + " - " +
                aufrufendeForm.textBox5.Text + " - " +
                aufrufendeForm.textBox6.Text;
}

Aufrufcode in Form1:


private void button2_Click(object sender, EventArgs e) {
    Form3 frm3 = new Form3(this);
    frm3.Show();
}

Wie man sieht, übergibt man hier als Parameter "this" sprich, sich selbst und in dem neuen Formular hat man dann bequem Zugriff auf alle TextBoxen von Form1. Bei dieser Methode muss man allerdings aufpassen dass die Objekte auf die man zugreifen will auch sichtbar, also public sind.

Dazu muss man den Form.Designer öffnen und ganz unten bei der Deklaration der Objekte die Sichtbarkeit auf Public ändern:

Bild1: Sichtbarkeitsänderung der Steuerelemente

Leider bringt auch diese Variante ein paar Unannehmlichkeiten mit sich, so muss die Klasse die die Informationen benötigt (hier Form3) genau wissen, von welcher Form diese aufgerufen werden kann und es im Konstruktor definieren. So kann man nicht ohne Aufwand Form3 aus einer weiteren Form aufrufen, da diese bereits Streng Typisiert auf Form1 eingestellt ist.

Methode 3

Die wohl sauberste Methode ist es wohl ein eigenes Objekt als Parameter zu übergeben. Dies hat den Vorteil, dass es für den ganzen Namensraum verfügbar ist und alle Klassen es definieren können und auch wieder verwenden können.

Dazu legen wir uns eine neue Klasse an in der wir Properties zu allen Informationen erstellen, die wir weiter geben möchten:


public class Informationen {

    public string info1 { get; set; }
    public string info2 { get; set; }
    public string info3 { get; set; }
    public string info4 { get; set; }
    public string info5 { get; set; }

}

Ich arbeite hier nur mit String Variablen, aber natürlich kann hier jeder beliebige Typ stehen. Vor dem Aufruf eines neuen Formulars können wir nun eine Instanz dieser Klasse bilden und mit unseren Werten befüllen um es anschließend als Parameter an die neue Form zu übergeben.

Form3 Konstruktor:


//METHODE 3
public Form3(Informationen infos) {
    InitializeComponent();

    this.infos = infos;

    this.label2.Text = infos.info1 + " - " +
                        infos.info2 + " - " +
                        infos.info3 + " - " +
                        infos.info4 + " - " +
                        infos.info5;
}

Und der Aufruf aus dem Aufrufer Formular (Form1):


private void button3_Click(object sender, EventArgs e) {
    Informationen infos = new Informationen();
    infos.info1 = textBox2.Text;
    infos.info2 = textBox3.Text;
    infos.info3 = textBox4.Text;
    infos.info4 = textBox5.Text;
    infos.info5 = textBox6.Text;

    Form3 frm3 = new Form3(infos);
    frm3.Show();
}

Auf diese Weise kann jedes beliebige Formular Informationen an Form3 übergeben ohne weitere Änderungen in Form3 vornehmen zu müssen. Die Klasse Informationen ist hier natürlich sehr leicht und schnell erweiterbar, sodass alle gewünschten Informationen schnell weiter gegeben werden können.

Alles wirklich nicht kompliziert, aber da ich es immer öfter antreffe dachte ich der Artikel könnt nützlich sein.

Hier habe ich noch das Demo Projekt zum Download:

Demoprojekt: Download [VS 2010]

8Sep/102

.NET: Ein Transparentes Label erstellen

Immer häufiger fragen Leute in Foren nach, wie man das Label dazu bringen kann den Hintergrund transparent darzustellen. Es wird vieles versucht, doch am Ende müssen alle feststellen, dass es mit dem "normalen" Label aus dem Framework nicht möglich ist eine transparente Darstellung zu erreichen.

Bild1: So wie es ist und wie es sein sollte

Das verwirrende hierbei ist, dass das Label es erlaubt die Hintergrundfarbe auf "Transparent" zu stellen, doch das macht den Hintergrund nicht wirklich transparent, sondern setzt den Hintergrund des Labels auf das des Containers in dem sich das Label befindet. Also wenn man das Label auf der Form Platziert und die Form Blau als Hintergrundfarbe hat wird das Label ebenfalls Blau als Hintergrund bekommen, wenn es auf Transparent gestellt ist.

Dies erweckt den Eindruck von Transparenz, doch was wenn man andere Steuerelemente oder Farbverläufe mit dem Label überdeckt? - Das führt zu einem unschönem Ergebnis (siehe Bild oben). Um diesen Fall ordentlich darzustellen muss man das Control selber zeichnen.

Ich habe hier für euch eine kleine Klasse namens TransparentLabel erstellt, dass nach einem Compile-Vorgang in eurer Werkzeugleiste als Steuerelement auftauchen wird. Hierbei mache ich nichts anderes, als den Text des Controls selbst zu zeichnen und dafür zu sorgen dass der Hintergrund nicht gezeichnet wird in dem man die Methode überschreibt und leer lässt.

Hier der Code:


//Unser Transparent Label erbt alles vom "nemalen" Control
class TransparentLabel : Control {

    //Wenn sich der Text ändert soll das Steuerelement
    //neugezeichnet werden
    protected override void OnTextChanged(EventArgs e) {
        base.OnTextChanged(e);
        Invalidate();
    }

    //Das Zeichnen des Elements übernehmen wir selbst:
    protected override void OnPaint(PaintEventArgs e) {
        //base.OnPaint(e);

        //Erst erstellen wir einen Pinsel mit der Farbe
        //Die der Benutzer für das Control eingestellt hat
        Brush myBrush = new SolidBrush(ForeColor);

        //Den Text zeichnen
        e.Graphics.DrawString(Text, Font, myBrush, new PointF(-1, 0));
    }

    //Den Hintergrund nicht zeichnen
    protected override void OnPaintBackground(PaintEventArgs pevent) {
        //base.OnPaintBackground(pevent);
    }

    //Mit dem Überschreiben der CreateParams
    //Können wir den Hintergrund "wirklich"
    //tranzparent machen.
    protected override CreateParams CreateParams {
        get {
            CreateParams cp = base.CreateParams;
            cp.ExStyle |= 0x20;
            return cp;
        }
    }
}

Und für VB.NET Nutzer:


Class TransparentLabel
	Inherits Control

	'Wenn sich der Text ändert soll das Steuerelement
	'neugezeichnet werden
	Protected Overrides Sub OnTextChanged(e As EventArgs)
		MyBase.OnTextChanged(e)
		Invalidate()
	End Sub

	'Das Zeichnen des Elements übernehmen wir selbst:
	Protected Overrides Sub OnPaint(e As PaintEventArgs)
		'base.OnPaint(e);

		'Erst erstellen wir einen Pinsel mit der Farbe
		'Die der Benutzer für das Control eingestellt hat
		Dim myBrush As Brush = New SolidBrush(ForeColor)

		'Den Text zeichnen
		e.Graphics.DrawString(Text, Font, myBrush, New PointF(-1, 0))
	End Sub

	'Den Hintergrund nicht zeichnen
	Protected Overrides Sub OnPaintBackground(pevent As PaintEventArgs)
		'base.OnPaintBackground(pevent);
	End Sub

	'Mit dem Überschreiben der CreateParams
	'Können wir den Hintergrund "wirklich"
	'tranzparent machen.
	Protected Overrides ReadOnly Property CreateParams() As CreateParams
		Get
			Dim cp As CreateParams = MyBase.CreateParams
			cp.ExStyle = cp.ExStyle Or &H20
			Return cp
		End Get
	End Property
End Class

Wie man sieht ist es wirklich nicht viel (Ergebnis seht ihr ja im Bild oben). Ich habe hier zwar nur die Grundfunktionen implementiert, diese reichen aber schon völlig aus, um es als ein transparentes Label zu benutzen. Nach Bedarf könnt ihr diese Klasse ja schnell und einfach erweitern.

6Sep/104

Java und C# – Die feinen Unterschiede

Immer wieder begegnen mir Leute, die Java und C# in die selbe Schupp-lade stecken. Man hört dann meist Sätze wie "C# ist Java von Microsoft", "Dann lerne ich doch gleich lieber Java statt Microsofts Kopie". Jeder der sich mit der .NET Plattform beschäftigt wird natürlich wissen, wie falsch diese Aussagen sind, die meist nur auf alten Vorurteilen und Unwissenheit basieren.

Die Anfänge

Natürlich haben diese Vorurteile irgendwo etwas wahres dran, so ist es nicht von der Hand zu weisen, dass sich die Syntax der beiden Sprachen sehr sehr ähnlich ist, und auch die Ausführung des Codes in einer VM kann man auch zu den Gemeinsamkeiten zählen. So ist C# ja auch entstanden, als eine Mischung aus Java und C++. Dies sollte es den Leuten erleichtern auf die neue Plattform zu wechseln und schnell einen Einstieg zu finden, desweiteren hat es sich in der Technischen Welt bewährt gute und erfolgreiche Konzepte zu kopieren und zu perfektionieren/verbessern. So würde ich auch C# mehr als eine Weiterentwicklung von Java betrachten.

Wo liegen die Unterschiede?

Natürlich fragt man sich dann, wo die Unterschiede sind und wenn man sich etwas damit befasst, wird man feststellen, dass es doch ziemlich viele Unterschiede und (meiner Meinung nach sehr nützliche) Weiterentwicklungen gibt.

Hier ein paar Beispiele:

  • Properties - Saubere Model-Klassen ohne einen riesen GetBla & SetBla Gestrüppe
  • Delegates (Funktionszeiger) - Übergabe von Funktionen als Parameter uvm.
  • LINQ (Language Integrated Queries)  - Objektorientierte SQL/XML-Abfragen
  • Events - Erleichtert strickte Trennung von Schichten und Informationsweitergabe
  • Lambda Ausdrücke - Viel Arbeit auf wenig Platz (Wird eventuell im JDK 1.7 Einzug halten)
  • Enums und Colections

Desweiteren gibt es auch wichtige Unterschiede, die unter der Haube ablaufen:

  • Assembly-Konzept - Einfache und schnelle Interaktion zwischen den .NET Sprachen wie C#, Visual C++.Net, Visual Basic.Net oder Delphi.Net
  • Namespaces - Auf den ersten Blick sehr ähnlich zu Packages , aber nicht auf den zweiten ;-)

Natürlich gibt es noch vieles mehr was an Unterschieden zu entdecken gibt. Wer da interessiert ist kann dich mal diese Seite anschauen mit vielen Beispielen und Vergleichen.

Einsatzbereiche

Sogar in den Einsatzgebieten ähneln sich die Plattformen sehr, denn wie mit Java kann man auch in .NET sowohl für Desktop, für Web und für mobile Plattformen entwickeln, wobei die mobilen Plattformen noch auf Windows Mobile beschränkt ist. (Aber Mono für Android ist ist ja auch schon unterwegs)

Dank Mono kann man viele .NET Programme auch sehr einfach auf Unix Systeme portieren, womit man teilweise auch die Plattformunabhängigkeit von Java erreicht. (Mono unterstützt zur Zeit das komplette .NET Framework 2.0)

Die Zukunft

Microsoft entwickelt die .NET Plattform sehr aktiv. Vor Kurzem ist die 4te Version des Frameworks inklusive einer neuen Visual Studio Version erschienen. Weitere Releases und Weiterentwicklungen dürften somit auch bald folgen.

Bei Java schaut man momentan noch in eine ungewisse Zukunft, da Sun vor einer Weile von Oracle aufgekauft wurde, weis man nun nicht mit Sicherheit was aus den Produkten wird. So musste die Community bereits den Verlust von Open Solaris hinnehmen und es hagelte auch schon die ersten Patentklagen wegen dem Aufbau der Java VM auf verschiedenen Plattformen. - Keine Rosigen Aussichten für Java Fans.

So scheinen nun sich die Feindbilder zu ändern. Lange Zeit war Microsoft wohl der Anführer der Bösewicht Nummer 1 - Liste, doch das Unternehmen hat sich gewandelt und stellt inzwischen sogar zu vielen Projekten sogar den Code zur Verfügung, so ist zum Beispiel ein großer Teil des .NET Frameworks einsehbar und auch das ASP.NET MVC Framework lässt sich komplett einsehen.

Die .NET Plattform ist inzwischen eine sehr mächtige geworden, und alle die es runterspielen oder ignorieren kann ich einfach nicht ernst nehmen. Und auch wenn man ein Open-Source-Junkie oder einfach nur ein Microsoft-Feind ist sollte man dennoch wissen, wovon man redet.

   
Get Adobe Flash playerPlugin by wpburn.com wordpress themes