Forum: PC-Programmierung C# Eigenert TreeView sehr langsam


von Peter (Gast)


Lesenswert?

Hallo NG,

ich hätte da mal eine Frage an die C# Profis unter euch.

Ich bin gerade dabei mich in C# (WPF) einzuarbeiten. Ich habe einen 
TreeView geschrieben, der mal grob gesagt so aussieht:

Ein Node selbst ist ein Stackpanel Horizontal, um den Öffner ([+]/[-]) 
und ein NodeIcon und den NodeText anzuzeigen. Darunter liegen ggf. 
weitere ChildrenNodes (auch in einem Stackpanel (vertikal)) um diese 
anzuzeigen (visible) oder nicht anzuzeigen (collapsed). Nachdem das 
alles fertig war habe ich testweise mal einen Node generiert, der 10.000 
Children hat. Die befüllung dauert ungefähr 5 Sek. Das Aufklappen 
(lediglich auf visible schalten) auch nochmal so 5 Sek. Das schmeckt mir 
ehrlich gesagt gar nicht. Mein Ziel wäre es, einen sehr schnellen 
TreeView zu haben, der auch mit max 300.000 Datensätzen schnell zurecht 
kommt. Habt Ihr ´ne Idee, wie man sowas in C# machen kann, oder wird das 
grundsätzlich nicht funktionieren?

PS.: Den vorhandenen TreeView wollte ich eigentlich nicht benützen. 
Primär die Frage, warum das Visible-Schalten des bereits befüllten 
Stackpanels so lange dauert.

Bin schon gespannt auf Eure Ideen.

MfG
Peter

von Hellseher (Gast)


Lesenswert?

Peter schrieb:
> Ich habe einen TreeView geschrieben

Ganz klar, du machst nach jedem Insert einen Bubble sort aller childs in 
Zeile 132.

von Peter (Gast)


Lesenswert?

Hallo,

Naja, ich weiß schon... Ich wollte ja nur mal Fragen, ob das mit der 
Geschwindigkeit nicht schneller geht. Vor allem das Anzeigen, der 
bereits befüllten Stackpanels.
1
<UserControl x:Class="XXX.DataTreeItem"
2
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
5
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
6
             mc:Ignorable="d" 
7
             d:DesignHeight="500" d:DesignWidth="300">
8
    <Grid SnapsToDevicePixels="True">
9
        <StackPanel HorizontalAlignment="Left" Name="stackPanel1" VerticalAlignment="Top">
10
            <StackPanel Name="stackPanel2" Orientation="Horizontal" VerticalAlignment="Top">
11
                <Image Height="9" Name="nodeOpener" Stretch="Fill" Source="/XXX;component/Images/Tree/empty.png" SnapsToDevicePixels="True" Width="6" Margin="3,0,2,2" MouseUp="nodeOpener_MouseUp" />
12
                <Image Height="16" Name="nodeIcon" Stretch="Fill" Width="16" Source="/XXX;component/Images/Tree/Icons/folder.PNG" Margin="3,0,3,2" />
13
                <TextBlock Name="nodeText" Text="BTex_gt" SnapsToDevicePixels="True" Foreground="#FF3B3B3B" Height="16"></TextBlock>
14
            </StackPanel>
15
            <StackPanel Margin="11,0,0,0" Name="stackPanel3" Visibility="Collapsed" ManipulationCompleted="stackPanel3_ManipulationCompleted" />
16
        </StackPanel>
17
    </Grid>
18
</UserControl>

von Arc N. (arc)


Lesenswert?

Stichwort wäre Virtualized TreeView
Generell ist es, vor allem bei großen Datenmengen, günstiger nicht alle 
UI-Elemente vollständig anzulegen, sondern wiederzuverwenden...
http://msdn.microsoft.com/en-us/library/cc716882.aspx (beim TreeView 
geht dies erst ab .NET 3.5)
http://msdn.microsoft.com/en-us/library/cc716879.aspx (Optimierungstips)

Ansonsten kann man z.B. sowas 
http://www.codeproject.com/KB/tree/VTreeView.aspx machen.

von Peter (Gast)


Lesenswert?

Hallo,

was mich aber jetzt trotzdem noch verwundert: wenn ich das (bereits 
befüllte) Stackpanel für die ChildrenNodes das erste Mal öffne, dauert 
es sehr lange es anzuzeigen. Wenn ich es dann wieder schließe und danch 
wieder öffne geht alles ganz schnell...

Das man jede Menge optimieren kann, indem man z.B. nur immer die Nodes 
darstellt, die sich an der jeweiligen Scrollbarposition befinden ist mir 
schon klar. Ich verstehe jedoch nicht, warum das Teil "von Haus aus" so 
zäh ist.

In der Arbeit programmiere ich eigentlich vorwiegend mit PHP 
irgendwelche Browser-Anwendungen. Von C# als "lokaler" Anwendung hätte 
ich mir da ein bisschen so eine Art "Kick" erwartet...

@Arc Net: Sind die Techniken in den Links dafür geschaffen, z.B. einen 
Baum mit 300.000 Datensätzen schnell anzuzeigen. Was ich halt nicht 
möchte ist das irgendwas an irgendeiner Stelle sich "zäh" anfühlt... 
gerade der Tree, der einen schnellen Zugriff auf die Daten gewähren 
soll, sollte absolut flott funktionieren.

mfg
Peter

von Arc N. (arc)


Lesenswert?

Peter schrieb:
> Hallo,
>
> was mich aber jetzt trotzdem noch verwundert: wenn ich das (bereits
> befüllte) Stackpanel für die ChildrenNodes das erste Mal öffne, dauert
> es sehr lange es anzuzeigen. Wenn ich es dann wieder schließe und danch
> wieder öffne geht alles ganz schnell...
>
> Das man jede Menge optimieren kann, indem man z.B. nur immer die Nodes
> darstellt, die sich an der jeweiligen Scrollbarposition befinden ist mir
> schon klar. Ich verstehe jedoch nicht, warum das Teil "von Haus aus" so
> zäh ist.

Sagen wir's mal andersrum: Mir ist auch kein natives UI-Toolkit/Control 
bekannt, welches ohne "Virtualisierung" bei solchen Datenmengen noch 
akzeptabel reagieren würde...
Der Grund ist ganz einfach, dass diese Standard-Controls nicht für 
solche Datenmengen ausgelegt sind. D.h. da wird's immer auf ein eigenes 
Control hinauslaufen, was alles selber macht (Zeichnen, 
Datenverwaltung/Caching etc.)

> In der Arbeit programmiere ich eigentlich vorwiegend mit PHP
> irgendwelche Browser-Anwendungen. Von C# als "lokaler" Anwendung hätte
> ich mir da ein bisschen so eine Art "Kick" erwartet...

s.o.

> @Arc Net: Sind die Techniken in den Links dafür geschaffen, z.B. einen
> Baum mit 300.000 Datensätzen schnell anzuzeigen. Was ich halt nicht
> möchte ist das irgendwas an irgendeiner Stelle sich "zäh" anfühlt...

Probier's aus! Mit 1000 Elementen auf der ersten Ebene und jeweils 1000 
auf der zweiten, läuft's hier akzeptabel.
(Beispiel von oben http://msdn.microsoft.com/en-us/library/cc716882.aspx 
und 10 bzw. 100 durch 1000 ersetzt).

> gerade der Tree, der einen schnellen Zugriff auf die Daten gewähren
> soll, sollte absolut flott funktionieren.

s.o.


>
> mfg
> Peter

von Peter (Gast)


Lesenswert?

Hallo Arc Net,

ich wollte das Beispiel auch eben mal ausprobieren. Leider bekomme ich 
diese beiden Fehlermeldungen beim Compilieren:

Fehler  1  "'src' ist ein nicht deklariertes Präfix. Zeile 8, Position 
18."- XML ist nicht gültig.  C:\Users\Karin\AppData\Local\Temporary 
Projects\WpfApplication1\MainWindow.xaml  8  18  WpfApplication1

Fehler  2  Der src:TreeViewData-Typ wurde nicht gefunden. Alle 
Assemblyverweise müssen vorhanden sein, und alle Assemblys, auf die 
verwiesen wird, müssen erstellt worden sein. 
C:\Users\Karin\AppData\Local\Temporary 
Projects\WpfApplication1\MainWindow.xaml  8  18  WpfApplication1

Hättest Du mir da bitte einen kleinen Tip, was das sein könnte? Ich habe 
in VS C# Express ein neues WPF Projekt angelegt. Im MainWindow.xaml.cs 
habe ich using System.Collections.ObjectModel; und nach dem Namespace 
WpfApplication1 habe ich in einem neuen namespace src den Code für die 
beiden Klassen von der Seite (dein Link) eingefügt. In der xaml Datei 
habe ich den xaml-Code von der Seite zwischen dem Grid eingefügt...

MfG
Peter

von Arc N. (arc)


Lesenswert?

src ist nur ein Prefix, der deklariert werden muss.
Ist der Namensraum bspw. MyNamespace (in C#) sieht das z.B. so aus
1
<Window x:Class="MyNamespace.MainWindow"
2
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4
        xmlns:src="clr-namespace:MyNamespace"
5
       ...
6
>
Soll der Namensraum src bleiben, wäre das in dem Bespiel 
xmlns:src="clr-namespace:src"

von Peter (Gast)


Lesenswert?

Hallo Arc Net,

hab´s dank Deiner Beschreibung hinbekommen :-) Aber ich muss echt sagen, 
dass mir das Ergebnis überhaupt nicht gefällt (MAC mini Core 2 Duo 2GHz 
3GB RAM Win7 ohne OSX)... Hab nur einen Knoten auf Level1 mit 300000 
Unterknoten. Aufklappen dauert so 2 Sek.  Scrollverhalten über die 
300000 Knoten ist absolut inakzeptabel.

Hmm, ich hätte schon viele Ideen, wie man das umsetzen könnte. Aber mal 
was anderes:

Ist das verkehrt, sich am Anfang darüber Gedanken zu machen, wie dieser 
Tree perfekt arbeitet, oder fällt das unter "premature optimization is 
the root of all evil"? Nachdem der Baum M.E. eine zentrale Rolle bei mir 
spielt, wäre mir schon sehr daran gelegen, dass sich alles so verhält, 
wie ich es mit von moderner Software wünschen würde...

MfG
Peter

von __tom (Gast)


Lesenswert?

Peter schrieb:
> Ist das verkehrt, sich am Anfang darüber Gedanken zu machen, wie dieser
> Tree perfekt arbeitet, oder fällt das unter "premature optimization is
> the root of all evil"? Nachdem der Baum M.E. eine zentrale Rolle bei mir
> spielt, wäre mir schon sehr daran gelegen, dass sich alles so verhält,
> wie ich es mit von moderner Software wünschen würde...

mit WPF gehts nur mit "virtualisierten" wiederverwendeten elementen (das 
erzeugen von visuals ist gelinde gesagt: etwas träge), von daher ists 
nicht verkehrt sich vorher darüber gedanken zu machen. der "premature 
optimization" spruch bezieht sich darauf das man vorher den code 
funktionierend hat und danach die letzten millisekunden rauskitzelt.

von Sam .. (sam1994)


Lesenswert?

Ich würde den Treeview schon nehmen. Man muss halt ein bisschen 
tricksen, aber dann geht das auch.

Man kann ein Treeview irgendwie virtual laufen lassen. Dabei musst du 
sobald man scrollt die Datensätze nachladen. Bzw. du lädst sie in ein 
Array das als Cache fungiert, wenn nichts gemacht wird. Ich hab das mal 
ohne Cache gemacht. Die Geschwindigkeit passt dann wieder. Allerdings 
hab ich Probleme bekommen als ich die einzelnen Elementen sortieren 
wollte (und zwar nach versch. Vorgaben). Das Treeview Sort kann man ja 
sowieso bei >100k Elementen vergessen und meine Eigene konnte ich auch 
nur auf ca. 1-2 Sekunden optimieren (da muss man eigentlich vorsortieren 
dann klappt das auch).

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.