Laden...

Navigieren zwischen Usercontrols anhand eines dynamisch erstellten TreeViews

Erstellt von Jacyrio vor 8 Jahren Letzter Beitrag vor 8 Jahren 1.243 Views
J
Jacyrio Themenstarter:in
197 Beiträge seit 2006
vor 8 Jahren
Navigieren zwischen Usercontrols anhand eines dynamisch erstellten TreeViews

Hey zusammen..

ich habe in meinem Projekt ein TreeView. Die einzelnen Ebenen in dem Baum baue ich dynamisch anhand einer Datenbank zusammen. Jetzt möchte ich die einzelnen Punkte in dem Baum so konfigurieren, dass ich drauf klicke und sich in einem Content-Bereich das passende UserControl dazu öffnet..

Würde ich den TreeView feste im Code erstellen, wüsste ich wie ich das lösen kann: http://www.japf.fr/2009/03/thinking-with-mvvm-data-templates-contentcontrol/

Mein Problem ist aber die dynamische Erstellung der Knotenpunkte.. wie löst man sowas denn am elegantesten? Bzw. wie wäre eure Idee wie ich das lösen könnte? (Kein Programmcode, sondern ein paar Ideen wie ich da an die Lösung komme wäre schön 😃 )

Danke!

P
441 Beiträge seit 2014
vor 8 Jahren

Hi,

in WPF funktioniert das über HierarchicalDatatemplates, hier kannst du bestimmen wie bestimmte Objekte aussehen sollen und du kannst zu jedem Objekt wieder eine Subproperty via Binding angeben, diese Property wird zum bilden der nächsten Ebene genutzt.

Wenn ich mich nicht irre ist hat ein Treeview auch ein SelectedItem oder?
Darüber kannst du dann deinen Content Bereich binden.

5.299 Beiträge seit 2008
vor 8 Jahren

Der frühe Apfel fängt den Wurm.

J
Jacyrio Themenstarter:in
197 Beiträge seit 2006
vor 8 Jahren

Hey..

ich bin gedanklich immernoch nicht auf die Lösung gekommen wie ich das dynamisch hin bekomme.. vielleicht habt ihr noch eine andere Idee..

Ich habe in der Datenbank das ganze Tree-Menü abgebildet.. um das mal Beispiel haft zu erklären:

Datenbankstruktur: Path | Parent | OrderIndex | Caption | View

Und hier ein Beispiel wie das Ganze dann in der DB aussieht:

  • Allgemein | Root | 100 | Allgemein | -
    -- Allgemein.News | Allgemein | 100 | News | NewsViewModel
    -- Allgemein.Termine | Allgemein | 200 | Termine | TermineViewModel
  • Tools | Root | 200 | Tools | -
    -- Tools.Rechner | Tools | Rechner | RechnerViewModel

usw.

Es könnte auch noch ne weitere Ebenen geben..

Jetzt würde ich gerne über einen SQL-Aufruf die Struktur des Baums laden (ObervableCollection) und diese dann an das Control binden.. soweit ist das ja kein Problem.. aber wie bekomme ich nun während des dynamischen Ladens hin dem Programm zu sagen, dass der Punkt "News" auch an das NewsViewModel gebunden ist und der Punkt Rechner an das RechnerViewModel usw? Was wäre eine mögliche Lösung dafür?

Müsste ich dann wirklich so vorgehen?


if(reader["View"] == "NewsViewModel"){
     this.treeitems.Add(new NewsViewModel());
}else if(reader["View"] == "RechnerViewModel"){
     this.treeitems.Add(new RechnerViewModel());
}else if....
......
}

Oder gibt es vielleicht sogar die Möglichkeit den String "RechnerViewModel" oder "NewsViewModel" oder "ABCViewModel" direkt casten in eine existierende Klasse? So das ich gar nicht erst eine riesige IF-Anweisung aufbauen muss?

Hoffe ihr könnt mir noch folgen mit meinen Gedankengängen 😃

5.658 Beiträge seit 2006
vor 8 Jahren

Hi Jacyrio,

es gibt für diese Zwecke die Activator.CreateInstance-Methode.

Allerdings halte ich es für einen groben Verstoß gegen die Schichtentrennung , wenn der Name einer ViewModel-Klasse in der Datenbank steht. Da stimmt also etwas an deiner Software-Architektur nicht.

Wenn es sich hierbei (wie ich annehme) um ein benutzerverwaltetes Menüsystem handelt, würde ich mir erstmal anschauen, wie andere das gelöst haben. Es gibt ja sicherlich einige Open-Source-Projekte, bei denen ähnliche Anforderungen bestehen.

Christian

Weeks of programming can save you hours of planning

J
Jacyrio Themenstarter:in
197 Beiträge seit 2006
vor 8 Jahren

Hey,

ich hatte einfach nicht vor das Menü feste in den Code zu bauen und wollte mir mit den Informationen in der Datenbank die Möglichkeit offen lassen das Menü ohne viel in den XAML-Dateien oder im C#-Code zu verändern..

Das muss nicht unbedingt ein "benutzerverwaltetes Menü" sein, aber wäre natürlich eine Möglichkeit das einem Admin zur Verfügung zu stellen. Im Moment würde es für mich aber keinen Sinn machen die Benutzer das System verwalten zu lassen.

Aber deinen Aussagen zu entnehmen würdest du sagen: Wenn die Benutzer das Menü nicht verwalten müssen, dann ist es Unsinn das Menü dynamisch über eine Datenban aufzubauen, sondern sollte man im Code zusammenstellen?

Um mal kurz zu erklären wo meine Denkweise herkommt: In irgendeinem Post wurde ich mal als "VBA-Programmierer", der umgestiegen ist auf WPF & Co., entlarvt.. Das ERP-System in unserer Firma basiert genau auf diesem System und wird ebenfalls über eine solche Datenbank dynamisch zusammengestellt und mit Entry-Funktioen wird dann eine Funktion im Code aufgerufen.. z. B. ein Formular. An manchen Stellen ist es für mich noch schwierig diese denkweise abzulegen.. also kann es ja durchaus sein, dass meine Idee heute keinen Sinn mehr macht..

S
469 Beiträge seit 2007
vor 8 Jahren

Ich würde auf keinen Fall den VM Namen in der Datenbank speichern, sondern dafür eine Enumeration erstellen. Damit kannst du sicherstellen, dass nur erlaubte Werte eingetragen werden und bist auch vor Namensänderungen sicher! In der Datenbank steht nur die "ID" bzw. der Enumerationswert, diesen kannst du im C# Code auswerten und das entsprechende ViewModel erstellen.
Die ganze if/else Geschichte kannst du noch umgehen, wenn du dir im Code ein Dictionary hältst, welches die Enumerationswerte mit dem Ziel-ViewModel verknüpft (key = Enumeration, value = ViewModel-Type). Dann kannst du für jeden Eintrag der Datenbank nachschlagen welches ViewModel gebraucht wird und dieses ViewModel dynamisch instanziieren. Kommen neue Enumerationswerte (= ViewModels) dazu, musst du nur noch das Dictionary erweitern, die Verwendungsstelle bleibt gleich.
Ansonsten aber sehe ich an deiner Herangehensweise nichts falsches. Es gibt sicher auch andere Wege, aber da müsste man das Gesamtsystem kennen..

gruß
sth_Weird

++++++++++++++++++++~+
Fluchen ist die einzige Sprache, die jeder Programmierer perfekt beherrscht


Linux is for free...if your time is worth nothing
++++++++++++++++++++~+

J
641 Beiträge seit 2007
vor 8 Jahren

Ich finde das nutzen einer Enumeration eher sxhlecht! Wenn Ich später mal die Applikation modular aufbaue, will Ich ja nicht jedes mal den enum in der Main app anpassen wenn es einen neuen view in einem modul gibt...

cSharp Projekte : https://github.com/jogibear9988

F
10.010 Beiträge seit 2004
vor 8 Jahren

Dann hast du aber modularisierung bisher eher schlecht implementiert.

Da das alles per Interfaces und DI/IOC gemacht wird, hast du schon mindest eine gemeinsam benutzte DLL, die mit den Interfaces.
Und da gehören auch globale enums hinein.