Autor Beitrag
Gausi
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8548
Erhaltene Danke: 477

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: Mo 10.05.04 13:03 
Ich habe eine Treeview mit Knoten auf verschiedenen Leveln. Level 0 sind Termine, Level1 sind Personen, die diesen Terminen zugeordnet sind.
Die Termin-Objekte verwalte ich in einer TObjectlist. Es ist immer sichergestellt, dass der i-te Level-0-Knoten dem i-ten Termin in der Objectlist entspricht. Die Liste ist nach Datum sortiert, und wenn ich ein Datum eines Termins ändere, verschiebe ich auch den Knoten in der Treeview entsprechend:

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
Procedure TTermin.Datumchange;
[...]
    tmptermin:=terminliste[Form1.Treeview1.Selected.Index] as Ttermin;//dieses Objekt wird bearbeitet
    markierterKnoten:=Form1.TreeView1.Selected;

    [...] // diverse Zuweisungen an die Eigenschaften von tmptermin

    Terminlistesort; //Terminliste nach Datum sortieren

    //alten und neuen Index bestimmen...
    Alterindex:=markierterKnoten.Index;
    Neuerindex:=Terminliste.IndexOf(tmptermin);    
    tmpknoten:=markierterKnoten;
    if neuerindex<alterindex then
    begin
        //...den Knoten bestimmen, zu dem der markierte Knoten veschoben werden soll...
        for i:=neuerindex to alterindex-1 do tmpknoten:=tmpknoten.getPrevSibling;
        //...und dann verschieben
        markierterKnoten.MoveTo(tmpknoten,NaInsert);
    end;
    if alterindex<neuerindex then
    begin
        if neuerindex=gottesdienste.Count-1 then
            markierterKnoten.Moveto(NIL,naaddchild)
        else
        begin
            for i:=alterindex to neuerindex-1 do tmpknoten:=tmpknoten.getNextSibling;
            tmpknoten:=tmpknoten.getNextSibling;
            markierterKnoten.MoveTo(tmpknoten,NaInsert);
        end;
    end;

Bis dahin klappt alles wunderbar.

Ich möchte nun, dass der User einige Termine farblich in der Treeview hervorheben kann. Dazu hat das Objekt "Termin" die Eigenschaft "hervorheben" (True/False). Dazu reagiere ich auf das Event OnCustomDrawItem

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
procedure TForm1.TreeView1CustomDrawItem(Sender: TCustomTreeView;
  Node: TTreeNode; State: TCustomDrawState; var DefaultDraw: Boolean);
begin
    with Treeview1.Canvas do
    begin
        if (node.Level=0// Nur die Termine sollen hervorgehoben werden, die zugeteilten POersonen ersma nicht
            and
            (terminliste[node.Index] as Ttermin).hervorheben  //(*)und auch nur, wenn man das möchte!
            then
            begin
                if (cdsSelected in State) then
                begin
                    font.Color:=clHighLightText;
                    brush.Color:=clHighlight;
                end else
                begin
                    font.Color:=clWindowtext;
                    brush.Color:=clskyblue; // Den Termin mit einem schönen Himmelblau unterlegen
                end;
            end;
    end;
end;


Und hier hakt es. Zwar kann ich weitere Termine am Ende des Baumes einfügen, und die weredn auch entsprechend eingefärbt, aber wenn ich den Termin ändere, und der Knoten "gemovt" werden soll, bleibt das Programm hängen und frisst meine ganze CPU-Leistung.

Wenn ich die Zeile (*) auskommentiere, gehts wieder. Es geht auch, wenn ich vor dem Moven ein
ausblenden Delphi-Quelltext
1:
form1.treeview1.OnCustomDrawItem:=NIL;					
und danach einform1.treeview1.OnCustomDrawItem:=form1.TreeView1CustomDrawItem;
reinpacke. Aber das is natürlich eine unschöne Lösung.

Ich nehme an, dass ich, während ich einen Knoten Move, nicht wirklich auf den Index zugreifen {kann|sollte}, weil der sich {ständig ändert|nicht definiert ist}. Aber warum kommt dann keine Fehlermeldung, sondern eine (scheinbar)Endlosschleife?

_________________
We are, we were and will not be.
smiegel
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 992
Erhaltene Danke: 1

WIN 7
D7 Prof., C#, RAD XE Prof.
BeitragVerfasst: Mo 10.05.04 13:13 
Hallo,

was passiert, wenn Du vor dem moven Items.BeginUpdate und nach erfolgreicher verschieberei Items.EndUpdate aufrufst?

_________________
Gruß Smiegel
Ich weiß, daß ich nichts weiß, aber ich weiß mehr als die, die nicht wissen, daß sie nichts wissen. (Sokrates)
Gausi Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8548
Erhaltene Danke: 477

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: Mo 10.05.04 13:26 
naja, was soll ich sagen, dann klappts auch :-)

Aber ob ich jetzt vor jedem Moven meine OndrawItem Prozedur mit der NIL-Zuweisung "verstecke", oder ob ich das in ein Begin- EndUpdate packe, is ja vom Programmieraufwand dasselbe. So muss ich immer noch aufpassen, dass ich nicht einfach nur die Knoten move (passiert gelegentlich auch an anderen Stellen), sondern etwas mehr mache.

Ich würde nur gerne noch verstehen, warum sich das Progg so aufhängt...Danke aber trotzdem, der BeginUpdate Befehl gefällt mir um einiges besser, als das, was ich bisher hatte

_________________
We are, we were and will not be.