PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : C#.Net UserControl mit Parameter im Konstruktor!?


dcAlge
2010-07-03, 00:26:05
Hey Leute,
folgende Situation:

-ich habe zwei Forms
-ein Instanz der Klasse WiimoteCollection (in der Main instanziert), die ich als Argument dem Konstruktor der Forms übergebe (das klappt auch ganz gut)
-jetzt möchte ich in eines der Forms eine UserControl einbauen, der diese Instanz dann weitergereicht wird (auch wieder als Argument im Konstruktor)

-dabei aber kommt es zu den Warnungen:

1: Warnung 1 Die Variable wc wurde nicht deklariert oder nicht zugeordnet.
2: Warnung 2 Die Variable wCollectionInfo1 wurde nicht deklariert oder nicht zugeordnet. C:\Users\Marco\Documents\Visual Studio 2010\Projects\enrich002\enrich002\FMoteInformationen.Designer.cs 58 0

bei der Ausführung gibt es eine NullReferenceException an der Stelle "wc.FindAllWiimotes();" beim Klicken des Button1 in der UCwCollectionInfo

Hier ein paar Codeschnipsel:

namespace enrich002
{
static class Program
{
/// <summary>
/// Der Haupteinstiegspunkt für die Anwendung.
/// </summary>
[STAThread]
static void Main()
{
WiimoteCollection wc = new WiimoteCollection();

Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new FMoteInformationen(wc));
Application.Run(new FKonfiguration(wc));
}
}
}


namespace enrich002
{
public partial class FMoteInformationen : Form
{
private WiimoteCollection wc;
public FMoteInformationen()
{
InitializeComponent();
}

public FMoteInformationen(WiimoteCollection arg)
{
InitializeComponent();
wc = arg;
}


}
}

partial class FMoteInformationen
{
/// <summary>
/// Erforderliche Designervariable.
/// </summary>
private System.ComponentModel.IContainer components = null;

/// <summary>
/// Verwendete Ressourcen bereinigen.
/// </summary>
/// <param name="disposing">True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}

#region Vom Windows Form-Designer generierter Code

/// <summary>
/// Erforderliche Methode für die Designerunterstützung.
/// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
/// </summary>
private void InitializeComponent()
{
this.button1 = new System.Windows.Forms.Button();
this.wCollectionInfo1 = new enrich002.UCwCollectionInfo(wc);
this.SuspendLayout();
//
// button1
//
this.button1.Location = new System.Drawing.Point(13, 13);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(75, 23);
this.button1.TabIndex = 0;
this.button1.Text = "button1";
this.button1.UseVisualStyleBackColor = true;
//
// wCollectionInfo1
//
this.wCollectionInfo1.Location = new System.Drawing.Point(13, 43);
this.wCollectionInfo1.Name = "wCollectionInfo1";
this.wCollectionInfo1.Size = new System.Drawing.Size(596, 515);
this.wCollectionInfo1.TabIndex = 1;
//
// MoteInformationen
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(645, 622);
this.Controls.Add(this.wCollectionInfo1);
this.Controls.Add(this.button1);
this.Name = "MoteInformationen";
this.Text = "Form1";
this.ResumeLayout(false);

}

#endregion

private System.Windows.Forms.Button button1;
private UCwCollectionInfo wCollectionInfo1;


}


namespace enrich002
{
public partial class UCwCollectionInfo : UserControl
{
private WiimoteCollection wc;

public UCwCollectionInfo()
{
InitializeComponent();
}

public UCwCollectionInfo(WiimoteCollection arg)
{
InitializeComponent();
wc = arg;
}

private void button1_Click(object sender, EventArgs e)
{
wc.FindAllWiimotes();
}


}
}

partial class UCwCollectionInfo
{
/// <summary>
/// Erforderliche Designervariable.
/// </summary>
private System.ComponentModel.IContainer components = null;

/// <summary>
/// Verwendete Ressourcen bereinigen.
/// </summary>
/// <param name="disposing">True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}

#region Vom Komponenten-Designer generierter Code

/// <summary>
/// Erforderliche Methode für die Designerunterstützung.
/// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
/// </summary>
private void InitializeComponent()
{
this.listBox1 = new System.Windows.Forms.ListBox();
this.button1 = new System.Windows.Forms.Button();
this.button2 = new System.Windows.Forms.Button();
this.tabControl1 = new System.Windows.Forms.TabControl();
this.tabPage1 = new System.Windows.Forms.TabPage();
this.tabPage2 = new System.Windows.Forms.TabPage();
this.tabControl1.SuspendLayout();
this.SuspendLayout();
//
// listBox1
//
this.listBox1.FormattingEnabled = true;
this.listBox1.Location = new System.Drawing.Point(4, 4);
this.listBox1.Name = "listBox1";
this.listBox1.Size = new System.Drawing.Size(458, 108);
this.listBox1.TabIndex = 0;
//
// button1
//
this.button1.Location = new System.Drawing.Point(469, 4);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(75, 23);
this.button1.TabIndex = 1;
this.button1.Text = "button1";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// button2
//
this.button2.Location = new System.Drawing.Point(469, 34);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(75, 23);
this.button2.TabIndex = 2;
this.button2.Text = "button2";
this.button2.UseVisualStyleBackColor = true;
//
// tabControl1
//
this.tabControl1.Controls.Add(this.tabPage1);
this.tabControl1.Controls.Add(this.tabPage2);
this.tabControl1.Location = new System.Drawing.Point(4, 119);
this.tabControl1.Name = "tabControl1";
this.tabControl1.SelectedIndex = 0;
this.tabControl1.Size = new System.Drawing.Size(458, 380);
this.tabControl1.TabIndex = 3;
//
// tabPage1
//
this.tabPage1.Location = new System.Drawing.Point(4, 22);
this.tabPage1.Name = "tabPage1";
this.tabPage1.Padding = new System.Windows.Forms.Padding(3);
this.tabPage1.Size = new System.Drawing.Size(450, 354);
this.tabPage1.TabIndex = 0;
this.tabPage1.Text = "tabPage1";
this.tabPage1.UseVisualStyleBackColor = true;
//
// tabPage2
//
this.tabPage2.Location = new System.Drawing.Point(4, 22);
this.tabPage2.Name = "tabPage2";
this.tabPage2.Padding = new System.Windows.Forms.Padding(3);
this.tabPage2.Size = new System.Drawing.Size(450, 354);
this.tabPage2.TabIndex = 1;
this.tabPage2.Text = "tabPage2";
this.tabPage2.UseVisualStyleBackColor = true;
//
// wCollectionInfo
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.tabControl1);
this.Controls.Add(this.button2);
this.Controls.Add(this.button1);
this.Controls.Add(this.listBox1);
this.Name = "wCollectionInfo";
this.Size = new System.Drawing.Size(596, 515);
this.tabControl1.ResumeLayout(false);
this.ResumeLayout(false);

}

#endregion

private System.Windows.Forms.ListBox listBox1;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Button button2;
private System.Windows.Forms.TabControl tabControl1;
private System.Windows.Forms.TabPage tabPage1;
private System.Windows.Forms.TabPage tabPage2;
}
}


Meine Idee war halt die Klasse WiimoteCollection einmal in Main() zu instanzieren und dann an die Forms weiterzureichen und damit zu arbeiten...
Mach ich grundsätzlich was falsch? Ist mein Aufbau eine Sackgasse?! Bin noch Frischling was Programmieren und speziell in C#.NET angeht...

Würde mich über jeden Tipp freuen! :)
Vielen Dank,
dcAlge

P.S.: Benutze übrigens VS 2010 Express, falls das irgendwie wichtig ist.

Monger
2010-07-03, 00:46:08
Ohje... hab selber leider keine Erfahrung mit Custom Controls.

Aber vergiss nicht, dass die Instanziierung des Window und der darin enthaltenen Controls auf einem anderen Thread passiert. Wenn du in deiner Main erst dein Custom Control instanziierst, läuft das logischerweise im selben Thread wie die Main. Wenn du dagegen "Run" aufrufst, wird ein neuer Thread instanziiert, in dem dann die Applikation läuft. Wenn du die Komponente im Konstruktor übergibst, hast du dann eine Applikation deren grafische Komponenten in zwei verschiedenen Threads sitzen - alleine das ist schonmal keine gute Idee.

Die Windows Forms sind sowieso in vielerlei Hinsicht ziemlich krumm. Möglich, dass du einen Standardkonstruktor zwingend liefern musst. Du solltest aber auf jeden Fall den Konstruktor der Oberklasse aufrufen.

dcAlge
2010-07-03, 00:51:42
Entschuldige, aber ich glaub du hast mich falsch verstanden:
Ich übergebe kein Control an die Forms (und dann an das UserControl), sondern ein ein Objekt der Klasse "WiimoteCollection". Dies ist kein Control sonder eine Klasse aus der freien WiimoteLib.dll, die die Kommunikation mit Wiimotes ermöglicht.
Und die Standardkonstruktoren hab ich schon drin gelassen, da ich rausgefunden habe, das sonst der VS-Designer Probleme macht.

Oder hab ich dich jetzt missverstanden?!

Edit:
Ohne die UserControl-Klasse, funktioniert das alles auch wunderprächtig. Ich kann aus beiden Forms auf die Informationen der WiimoteCollection zugreifen. Sobald ich aber ein Benutzersteuerelement(Usercontrol) dazwischen setze, wirft es diese Warnungen und mir ist nicht wirklich ersichtlich warum. :(

Gohan
2010-07-03, 09:27:28
Der Compiler gibt dir ja sogar die genaue Position des Fehlers an: this.wCollectionInfo1 = new enrich002.UCwCollectionInfo(wc);
Du musst im Code, also der FMoteInformationen.cs und nicht im Code des Designers (FMoteInformationen.Designer.cs) die Instanz erzeugen, z.B. im OnLoad Event.

private void Form1_Load(object sender, EventArgs e)
{
wCollectionInfo1 = new enrich002.UCwCollectionInfo(wc);
}

dcAlge
2010-07-03, 12:29:11
Soweit ich das überblicke wird dieser Fehler geworfen, da der Konstruktor von UCwCollectionInfo nicht korrekt ausgeführt wird. Dass es an falscher Stelle instanziert wird, kann ich mir schwer vorstellen.Es hat ja vor meiner Umstellung des Konstruktors auf Konstruktor mit Parameter auch funktioniert hat.

Gast
2010-07-03, 12:51:34
Funktioniert das überhaupt? Application.Run startet doch die Message Loop. D.h. ab da geht doch in der Main die Verarbeitung nur weiter, wenn die Loop beendet wird (z.B. durch WM_QUIT). D.h. "Application.Run(new FKonfiguration(wc));" sollte erst aufgerufen werden, wenn die Instanz von FMoteInformationen beendet wird.

dcAlge
2010-07-03, 13:25:15
Jap, Gast, so funktioniert es im Moment auch. Das zweite Fenster ist im Moment eigentlich unwichtig.
Es war halt nur dazu gedacht, die Instanz der WiimoteCollection nochmal einmal weiterzugeben und zu schauen ob der Zugriff korrekt funktioniert hat.
Im Unterschied zur FMoteInformationen (mit der UCwCollectionInfo), funktioniert die Weitergabe des Objekts "wc" in FKonfiguration nämlich korrekt. Ich könnte also einfach die zwischengelagerte UserControl rauswerfen und alles würde perfekt laufen, aber da ich die evtl. wiederverwenden will wär es schon schick sie zu haben.