Entwickler-Ecke

WinForms - Controls in einer TabControl auf neuen Parent umhängen.


Delete - Mi 04.03.09 10:09
Titel: Controls in einer TabControl auf neuen Parent umhängen.
Guten Morgen.

(C# 2008 Express.)

Ich habe eine TabControl. Der Controls in dieser TabControl sollen beim Tab-Wechsel auf den neuen Tab referenziert werden. Das Referenzieren der Parent-Eigenschaft ist nicht das Problem, sondern ich komme nicht an die Referenz bzw. den Index der alten TabPage heran.


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
private void tabControl01_Selecting(object sender, TabControlCancelEventArgs e)
{
  // TabPages[0] ist natürlich nicht richtig
  foreach (Control C in ((TabControl) sender).TabPages[0].Controls)
  {
    C.Parent = e.TabPage;
  }
}


Wenn ich TabControl.Selected nehme, erhalte ich auch die neue TabPage. Muss ich mir jetzt eine Hilfsvariable einführen und diese in Deselecting setzen, oder gibt es eine Eigenschaft, die ich bisher partout nicht gefunden habe?

Danke.


JüTho - Mi 04.03.09 13:32

Hallo Christian,

Du hast ja schon festgestellt, dass es auch das Deselecting-Ereignis gibt. Was glaubst Du wohl, warum es so spezielle EventArgs gibt? Schau einfach in der SDK-Doku/MSDN nach, was die TabControlCancelEventArgs an Informationen liefern.

Jürgen


Nemag - Mi 04.03.09 14:04

Ich denke mal die EventArgs hat er schon gefunden gehabt, seine Frage zielt ehr daraufhin ab ob er direkt aus dem Selecting eine Eigenschaft irgendwoher auslesen kann die ihm die vorherige Page sagt.

Meines Erachtens gibt es diese nicht. Würde das dann halt so machen wie du schon geschrieben hast. AUs dem Deselecting eine KLassenvariable setzen und diese dann in Selecting benutzen.


Ralf Jansen - Mi 04.03.09 14:21

Zitat:
oder gibt es eine Eigenschaft, die ich bisher partout nicht gefunden habe?


Das TabControl merkt sich intern den Index der letzten Auswahl( lastSelection Variable - im Reflector nachgesehen) um bei einem Cancel im Selecting Event die letzte Page wieder auswählen zu können. Die Variable wird aber leider nicht veröffentlicht. Mußt dir also was über das Deselecting Event basteln.

Aber warum zeigst du alle Controls auf allen Tabpages an? Das hört sich für mich sinnfrei an. Wenn das gewollt ist würde ich für die Controls einfach nicht eine TabPage als Parent benutzen sondern als Parent der Controls die Form benutzen sie aber trotzdem vor dem TabPage anzeigen. Dann kannst du dir das Umhängen sparen.


Delete - Mi 04.03.09 14:51

user profile iconJüTho hat folgendes geschrieben Zum zitierten Posting springen:
Schau einfach in der SDK-Doku/MSDN nach, was die TabControlCancelEventArgs an Informationen liefern.

user profile iconNemag hat folgendes geschrieben Zum zitierten Posting springen:
Ich denke mal die EventArgs hat er schon gefunden gehabt, seine Frage zielt ehr daraufhin ab ob er direkt aus dem Selecting eine Eigenschaft irgendwoher auslesen kann die ihm die vorherige Page sagt.

Richtig.

user profile iconRalf Jansen hat folgendes geschrieben Zum zitierten Posting springen:
Das TabControl merkt sich intern den Index der letzten Auswahl( lastSelection Variable - im Reflector nachgesehen) um bei einem Cancel im Selecting Event die letzte Page wieder auswählen zu können. Die Variable wird aber leider nicht veröffentlicht. Mußt dir also was über das Deselecting Event basteln.

Also mehrere Möglichkeiten:

  1. Ableiten und lastIndex veröffentlichen.
  2. Ableiten und Eigenschaft als Hilfsvariable implementieren. Da ich dann aber schon beim Ableiten bin, dann doch gleich Variante 1. verwenden.
  3. Beim Ableiten am besten eine Methode implementieren, die Inhalte umhängt. Dann braucht man lastIndex nicht. Aber ich kann mir vorstellen, dass ich lastIndex irgendwann mal brauche. Bei Delphi öfters mit den TabReferenzen gearbeitet. Also beide, lastIndex und die neue Reallocate-Methode, veröffentlichen.
  4. Solange man die Eigenschaft Tag nicht anderweitig verwendet, einfach nachfolgenden Code verwenden.


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
private void tabControl01_Selecting(object sender, TabControlCancelEventArgs e)
{
  foreach (Control C in ((TabControl)sender).TabPages[(int)((TabControl)sender).Tag].Controls)
  {
    C.Parent = e.TabPage;
  }
}

private void tabControl01_Deselecting(object sender, TabControlCancelEventArgs e)
{
  ((TabControl)sender).Tag = ((TabControl)sender).TabPages.IndexOf(e.TabPage);
}


[edit]
Selecting-Event geändert
Grund: Mit foreach funktioniert es nicht. Wenn das erste Element umgehangen wird, dann verkürzt sich die Liste der Controls und der Index 1 auf die vorher erste Control zeigt nun auf die zweite Control. Daher jetzt eine dekrementelle For-Schleife verwendet.

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
private void tabControl01_Selecting(object sender, TabControlCancelEventArgs e)
{
  System.Windows.Forms.Control.ControlCollection clpControls = ((TabControl)sender).TabPages[(int)((TabControl)sender).Tag].Controls;
  for (int I = clpControls.Count - 1; I >= 0; I--)
  {
    clpControls[I].Parent = e.TabPage;
  }
}

[/edit]

user profile iconRalf Jansen hat folgendes geschrieben Zum zitierten Posting springen:
Aber warum zeigst du alle Controls auf allen Tabpages an? Das hört sich für mich sinnfrei an. Wenn das gewollt ist würde ich für die Controls einfach nicht eine TabPage als Parent benutzen sondern als Parent der Controls die Form benutzen sie aber trotzdem vor dem TabPage anzeigen. Dann kannst du dir das Umhängen sparen.


Dann kann ich z.B. auch mal die TabControl ausblenden, neu belegen, etc, ohne erst irgendwelche Elemente, die nicht auf dem Tab liegen im Form zu suchen und zu verarbeiten. Ich bin schon darauf aus, den logischen Kontext zu erhalten, also "was gehört wo rein und ist Parent von wem?".

In Delphi gab es ja Frames. Bei C# habe ich bisher noch keine ähnliche Control gefunden. Daher direkt über Controls, oder ich benutze in Tabs eine GroupBox für alle.

Danke. Problem gelöst. Evtl. gibt es noch paar interessante Vorschläge von Euch. Bin gespannt.

Edit: Achso. Frage des Unwissenden: Der Reflector ist was? Ich verwende i. d. R. F12 um in den Code einer Klasse zu gelangen.


Ralf Jansen - Mi 04.03.09 15:05

Das äquivalent zu Delphi Frames sind UserControls.

Reflector läßt sich wohl am ehesten als Decompiler bezeichnen. Absolut unentbehrlich.
http://www.red-gate.com/products/reflector/


Nemag - Mi 04.03.09 16:30

user profile iconRalf Jansen hat folgendes geschrieben Zum zitierten Posting springen:
Das äquivalent zu Delphi Frames sind UserControls.

Reflector läßt sich wohl am ehesten als Decompiler bezeichnen. Absolut unentbehrlich.
http://www.red-gate.com/products/reflector/


Konnte jetzt leider auf die Seite nicht zugreifen, da michd as aber auch interessieren würde ... muss hier mal spamen. ;-)

Stimmt die Seit nicht oder tötet meinen Zugriff unser Admin? ;-) ;-) ;-)


Delete - Mi 04.03.09 16:40

Jepp. BlankPage. 0 Bytes.


Kha - Mi 04.03.09 17:57

Entweder war der Server vorhin wirklich weg oder das Problem liegt leider auf eurer Seite ;) .
Versucht es mal direkt hier: http://reflector.red-gate.com/download.aspx


Delete - Mi 04.03.09 19:52

Der Server war weg. Ich konnte wenig später laden. Danke. ;)

Ich habe meinen Post oben [http://www.c-sharp-forum.de/viewtopic.php?p=552147#552147] noch einmal korrigiert. Die Variante mit foreach hatte ich nicht genug getestet. Da gab es einen Bug wegen des sich ändernden Index von "Controls".