Bitmap in Zeile

22. Juli 2008 14:16

Hallo,

habe bei einer Präsentation einer 4.0 Version gesehen, dass Zeilen 'aufgeschlagen' werden können. Das heisst, durch ein Klick auf den blauen Pfeil (nach rechts) pro Zeile verwandelt sich dieser in Pfeil nach unten, weitere Datensätze werden in den fortfolgenden Zeilen angezeigt. Tolle Sache.

Ich frage mich, wie das funktioniert? Ok, ich kann in einer Tabellen-Form eine Picture-Box einbinden, mit BitmapList 16,4 und das ganze über ein Bool-Feld steuern. Aber ich habe KEIN OnPush-Trigger?

Könnt ihr mir sagen, wie das funktioniert :?:

PS: bräuchte sowas für Anwender, die Details für eine Zeile in einer Tabellen-Form auf- und zuschlagen wollen.

22. Juli 2008 14:42

Wenn es ein Boolsches Feld ist, kannst du auf dem Feld (auf der Form selbst) bei dem Validate Triger ein Case Of machen und entsprechend Filter. Das wäre jedenfalls meine erste Vorgehensweise!

22. Juli 2008 14:59

Hi Mathias,

hm, weisch, die SourceExpr dieser PictureBox ist klar ein Boolean-Feld. Aber schön ist die optische Änderung des Pfeils beim Klicken. Und das geht doch nur übern OnPush-Trigger, oder?

Wenn ich eine CheckBox nehme, da geht das wunderbar. Nur kann ich hier leider die 2 bitmaps für die Pfeile dynamisch hinterlegen..

22. Juli 2008 15:14

neee, setzt ma die Picturebox sowie das Boolsche Feld auf die selbe SourceExpr. und in der BitMapList der Picturebox setzte 2 Werte (z.B.) 1,2.
Klicke dann mal das Boolsche Feld an und schau dir die PictureBox dabei an.

22. Juli 2008 15:20

Ok, dann sieht man sehr schön die Änderung. Aber die Herausforderung ist, nicht das boolsche Feld, sondern die Pfeile anzuklicken.

Leider kann man in einer Tabellen-Form Spalten nicht übereinander schieben. Wie z.B. auf der Artikelform bei den Bemerkungen.

Aber es muss irgendwie gehen.

22. Juli 2008 16:01

Hallo,

in V 4.0 gibt es den OnPush Trigger in der Picturebox. und dann geht das auch.....

22. Juli 2008 16:09

da musst du dann halt nur

Code:

Compact := NOT Compact;

Modify;

23. Juli 2008 08:19

wieso machst du es nicht so: du nimmst zwei buttons, beide enthalten je ein bild, einer der buttons ist im vornherein unsichtbar, klickst du nun auf den sichtbaren, wird dieser unsichtbar, und der andere wieder sichtbar, ganz einfache geschichte ;)

23. Juli 2008 09:07

@Jörg
Schade, das ist es. Danke Jörg. Vermisse nämlich den OnPush-Trigger in der PictureBox. Anders lässt sich das nicht bewerkstelligen. Zwar kann ich die Bitmap-Steuerung über OnActivate programmieren, da wirst aber zum Hirsch, denn da reicht ja schon mit dem Cursor darüberfahren.

@Sebastian
In Tabellen-Forms ist das leider nicht möglich wie auf einer Kartenform. Man kann auch Spalten nicht 'übereinander' schieben.

Dann muss ich wohl doch ne Checkbox nehmen :( Sieht halt net so schön aus.

23. Juli 2008 09:50

Hallo,

wenn ich das was Du tun möchtest richtig verstanden habe, dann hab ich sowas schon mal gemacht :). Das ist allerdings nicht so einfach wie man es sich wünschen würde.

Ich habe das ganze über eine Form realisiert, die als SourceTable eine temporäre Table (SourceTableTemporary = Yes) verwendet, d.h. diese muss an der richtigen Stelle (im richtigen Trigger) aktualisiert werden. Die TableBox in der Form hat als erste Spalte eine PictureBox-Spalte. Diese bekommt als SourceExpression eine globale Variable mit einem OptionString (Has Children, Expanded, ChildNode, No Children). In den Eigenschaften der Spalte gibt es eine BitmapList, hier kann man für jede Option ein Bitmap einstellen. Ich habe 47,46,40 gewählt. Damit erhält Has Children = 47 ein +, Expanded = 46 ein -, ChildNode = 40 einen Pfeil nach unten und No Children = nix eben nix.

Wenn man die Form öffnet, muss die Table gefüllt werden. Ich rufe dazu eine Funktion InitTempTable auf. Von da aus befülle ich die temporäre Table aus einer globalen Record-Variable des gleichen Typs. Dabei wird die Spalte Level die ich in meine Table eingefügt habe überprüft. Ist Level = 0 gibt es keine ChildNodes, ist Level = 1 sind ChildNodes vorhanden:

InitTempTable
Code:
//Transfer actual Record to global Record-Variable
G_SoruceRec.RESET;
G_SoruceRec.COPYFILTERS(Rec);
G_SoruceRec.SETCURRENTKEY(ItemNo, Level, ArticleNo); //Hier wird ein Sortierkriterium benötigt. Bei mir zuerst nach der ItemNo, dann nach der Level und zuletzt nach ArticleNo sortiert. Sortiert man nur nach Level, kann das ganze logischerweise nicht klappen.

//Delete all actual Records and end the current write transaction
DELETEALL;
COMMIT;

//Insert Records from global Record-Variable
IF G_SoruceRec.FINDSET THEN BEGIN
  REPEAT
    IF (G_SoruceRec.Level = 0) THEN BEGIN
      TRANSFERFIELDS(G_SoruceRec);
      INSERT;
    END;
  UNTIL G_SoruceRec.NEXT = 0;
END;

SETCURRENTKEY(ItemNo, Level, ArticleNo);


Desweiteren verwende ich die Funktionen ToggleExpandCollapse zum Auf- und Zuklappen (anhand der Level):

ToggleExpandCollapse
Code:
//Transfer actual Record to global and local Record-Variable
G_SourceRec.RESET;
G_SourceRec.COPYFILTERS(Rec);
G_SourceRec.SETCURRENTKEY(ItemNo, Level, ArticleNo);
G_SourceRec.TRANSFERFIELDS(Rec);

//Es wird eine lokale Record-Variable benötigt, um sich zu merken, an welcher Stelle man sich vorher befunden hat.
L_Rec.COPYFILTERS(Rec);
L_Rec.SETCURRENTKEY(ItemNo, Level, ArticleNo);
L_Rec.TRANSFERFIELDS(Rec);

//Check actual expansion status to expand or collapse Table-Lines
IF G_ActualExpansionStatus = G_ActualExpansionStatus::"Has Children" THEN BEGIN
  IF G_SourceRec.NEXT <> 0 THEN BEGIN
    REPEAT
      IF G_SourceRec.Level > L_Rec.Level THEN BEGIN
        TRANSFERFIELDS(G_SourceRec);
        INSERT;
      END;
    UNTIL (G_SourceRec.NEXT = 0) OR (G_SourceRec.Level = L_Rec.Level);
  END;
END ELSE
IF G_ActualExpansionStatus = G_ActualExpansionStatus::Expanded THEN BEGIN
  WHILE (NEXT <> 0) AND (Level > L_Rec.Level) DO
    DELETE;
END;

//Transfer local Record to actual Record and update CurrentForm
TRANSFERFIELDS(L_Rec);
CurrForm.UPDATE;

Diese Funktion muss jedesmal aufgerufen werden, wenn sich etwas ändert. Das wäre also der bereits erwähnte OnPush-Trigger der PictureBox-Spalte.

Die Funktionen SetExpansionStatus, IsExpanded (Übergabeparameter der aktuell behandelte Record) und HasChildren (Übergabeparameter der aktuell behandelte Record) dienen der Verwaltung der aktuellen Level:

SetExpansionStatus
Code:
//Set expansion status on the basis of current Level
IF Level > 0 THEN BEGIN
  G_ActualExpansionStatus := G_ActualExpansionStatus::ChildNode;
END ELSE
  IF IsExpanded(Rec) THEN BEGIN
    G_ActualExpansionStatus := G_ActualExpansionStatus::Expanded;
END ELSE
  IF HasChildren(Rec) THEN
    G_ActualExpansionStatus := G_ActualExpansionStatus::"Has Children"
  ELSE
    G_ActualExpansionStatus := G_ActualExpansionStatus::"No Children";


IsExpanded(P_CurrentRec : Record SourceRec) : Boolean
Code:
//Transfer actual Record to local Record-Variable
L_Rec.COPYFILTERS(Rec);
L_Rec.SETCURRENTKEY(ItemNo, Level, ArticleNo);
L_Rec.TRANSFERFIELDS(Rec);

//Transfer fields from assigned Record to actual Record
TRANSFERFIELDS(P_CurrentRec);

//Find out expansion status
Found := (NEXT <> 0);

IF Found THEN
  Found := (Level > P_CurrentRec.Level);

//Transfer local Record to actual Record and exit Function
TRANSFERFIELDS(L_Rec);
EXIT(Found);


HasChildren(P_CurrentRec : Record SourceRec) : Boolean
Code:
//Transfer actual Record to global Record-Variable
G_SourceRec.RESET;
G_SourceRec.COPYFILTERS(Rec);
G_SourceRec.SETCURRENTKEY(ItemNo, Level, ArticleNo);
G_SourceRec.TRANSFERFIELDS(P_CurrentRec);

//Find out if current Record has Child-Records
IF G_SourceRec.NEXT = 0 THEN
  EXIT(FALSE)
ELSE
  EXIT(G_SourceRec.Level > P_CurrentRec.Level);


Das ganze hat mich wirklich Zeit und Nerven gekostet und da ich mir beim Erklären schwer tue, lass ich das mal so stehen, in der Hoffnung ein paar Anregungen gegeben zu haben. Falls das hilfreich war und es Fragen gibt, fällt es mir bestimmt leichter, diese gezielt zu beantworten :).

Den Code habe ich zwecks Verständlichkeit angepasst, er ist deshalb ungetestet.

Gruß,
Christian
Zuletzt geändert von Merlin am 23. Juli 2008 13:42, insgesamt 1-mal geändert.

23. Juli 2008 10:19

oh das mit der tabelle habe ich überlesen, dann wird das ganze schwer bis unlösbar, nun kannst du zwar noch einen optionbutton nehmen, leider ist es da aber nicht möglich die bitmap zu ändern

23. Juli 2008 10:26

LSmedcap hat geschrieben:@Jörg
... Vermisse nämlich den OnPush-Trigger in der PictureBox. ...


Da ich für meinen Post sehr lange gebraucht habe, hab ich das auch eben erst gelesen. Ohne OnPush würde das auch meinen Vorschlag disqualifizieren. In Dynamics NAV 4.xx habe ich einen OnPush für die PictureBox.

23. Juli 2008 11:15

Ich sitze heute vor einer 3.70 Version - dort gibt es in der Picturebox genau wie in 4.0 den OnPush Trigger.

Also sollte das Ganze doch zu realisieren sein.