Wiedergabe von Ordnerstrukturen in WPF und C# mit MVVM

NewCommer

Neues Mitglied
Hallo zusammen ­čľľ,

ich arbeite derzeit an einer kleinen B├╝roverwaltungssoftware. Es soll eine M├Âglichkeit geben sich gewisse Ordnerstrukturen anzeigen zu lassen, ├Ąhnlich dem Windows Explorer. Mit SelectedItem soll es dann m├Âglich sein, sich die Dateien z.B. Word oder PDF in einem extra Feld anzeigen zu lassen. Bis jetzt habe ich es geschafft, mir bestimmte Dateien aus einer Ordnerstruktur in einer Listbox zur├╝ck geben zu lassen. Dies reicht mir allerdings noch nicht, meine Vorstellung geht eher in Richtung des Explorers, wobei mir die Funktionalit├Ąt in Ordner zu bl├Ąttern und Dateien aufzurufen f├╝r ein vordefiniertes Stammverzeichnis ausreichen w├╝rden. Leider komme ich mit der TreeView nicht wirklich zurecht, alle bisherigen recherchen im Netz f├╝hrten zu weniger hilfreichen ergebnissen. In den meisten Beispielen wird gezeigt wie man aus dem Codebehind Objecte abruft und diese dann mittels Binding anzeigen l├Ą├čt. Da ich das MVVM Pattern umsetze, sind diese Beispiele f├╝r mich schlicht weg unbrauchbar. Mein Favorit ist derzeit die Idee eines DataProviders, wobei mir die Strukturierung des TreeViews und das Abrufen der Daten noch etwas zu schaffen macht. Da ich eine hierarchische Darstellung haben m├Âchte, mit Images u.s.w., m├╝sste ich mir f├╝r die Aufbereitung der Daten eine extra Klasse schaffen. Zumindest habe ich das aus dem Internet erfahren k├Ânnen. Hat eventuell jemand von euch Erfahrungen mit der Materie und kann mir da einen Schubs in die richtige Richtung geben? Bisher lege ich mir damit total die Karten.
 
Hi,

Sie k├Ânnen dies tun, ohne zus├Ątzliche Komponenten zu verwenden. Dazu m├╝ssen Sie lediglich wissen, welche Datenstrukturen das TreeView-Element von WPF empfangen kann. Was wir daf├╝r brauchen, ist ein eingebautes NET-Objekt, mit dem Sie meiner Meinung nach Erfahrung haben. Das von mir verwendete MVVM-Muster ist MvvMLight, jetzt "CommunityToolkit" genannt. Die folgenden Beispielcodes k├Ânnen Sie nach Belieben automatisieren und f├╝r Ihre File Explorer Teil nach Belieben verwenden.

Dies ist ein DataView Objekt.

Nachfolgend sende ich Ihnen ein Beispiel aus einem alten Projekt von mir. Dieser Code befindet sich in meiner Klasse "Constants.cs".

C#:
#region New Project Menu Nodes
public
static DataView MenuNodes {
  get {
    DataTable table = new DataTable("MainTemplates");

    //[B]Ich definiere vorab die Parameter, die in der Tabelle enthalten sein sollen.[/B]
    table.PrimaryKey = new System.Data.DataColumn[]{table.Columns.Add("ID", typeof(int))};
    table.Columns.Add("parentID", typeof(int));
    table.Columns.Add("MainTypes", typeof(string));
    table.Columns.Add("Templates", typeof(string));
    table.Columns.Add("SolutionTypes", typeof(string));
    table.Columns.Add("ProjectTypes", typeof(string));

    table.Rows.Add(0, null, null, null, null, "Installed");
    [B] //Main tree 1[/B]
        table.Rows.Add(1, null, null, null, null, "Online");
    [B] //Main Tree 2[/B]

        table.Rows.Add(2, 0, null, null, null, "Templates");
    [B] //Child Tree[/B]

        table.Rows.Add(3, 2, null, null, null, "System Project Types");
    [B] //child Tree element[/B]
        table.Rows.Add(4, 3, null, null, null, "Batch Project");
    [B] //child Tree element (parameter 3 zeigt System Project Types!)[/B]
        table.Rows.Add(5, 3, null, null, null, "DLL Support Project");
    [B] //child Tree element..[/B]
        table.Rows.Add(6, 3, null, null, null, "WMI Project Types");
    [B] //child Tree element..[/B]

        table.Rows.Add(7, 2, null, null, null, "Component Project Types");
    [B] //child Tree Erstellung (parameter 2 zeigt Templates !)[/B]
        table.Rows.Add(8, 7, null, null, null, "XML Projects");
    table.Rows.Add(9, 7, null, null, null, "WCF Service Project");
    table.Rows.Add(10, 7, null, null, null, "Windows Service Project");
    table.Rows.Add(11, 7, null, null, null, "Windows Task Project");
    table.Rows.Add(15, 7, null, null, null, "NHibernate Project");

    table.Rows.Add(12, 2, null, null, null, "Solution");
    table.Rows.Add(13, 12, null, null, null, "Batch Studio Solution");
    table.Rows.Add(14, 12, null, null, null, "Setup and Deployment");

    DataSet dtSet = new DataSet();
    dtSet.Tables.Add(table);

    [COLOR = rgb(184, 49, 47)][B] dtSet.Relations.Add("NewProjectMenu", table.Columns["ID"], table.Columns["parentID"]);
    [/ B][/ COLOR]

        return new DataView(table);
  }
}
#endregion



Der folgende Code befindet sich in meiner Klasse mit dem Namen "XViewModel.cs".

C#:
DataView _menuNodes; //[B] --> Klasse basierte definition.[/B]

public
DataView[B] RootNodes[/ B] {
  get {
    _menuNodes.RowFilter = "[parentID] is NULL";
    return _menuNodes;
  }
}

private
RelayCommand<DataRowView> _selectedProjectType;
/// <summary>
/// Gets the selected project type from "Create New Project".
/// </summary>
public
RelayCommand<DataRowView> SelectedProjectType {
  get { return _selectedProjectType; }
}

Der folgende Code befindet sich in mein Xaml mit dem Namen "XViewWindow.xaml".

Code:
i definition >> xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"


<TreeView Name="NewProjectTree" ItemsSource="{Binding RootNodes}" Grid.ColumnSpan="1" Grid.RowSpan="2" BorderBrush="Transparent">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="SelectedItemChanged">
                    <i:InvokeCommandAction Command="{Binding Path=SelectedProjectType}" CommandParameter="{Binding ElementName=NewProjectTree, Path=SelectedItem}"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
            <TreeView.ItemTemplate>
                <HierarchicalDataTemplate ItemsSource="{Binding NewProjectMenu}">
                    <TextBlock Text="{Binding ProjectTypes}"/>
                </HierarchicalDataTemplate>
            </TreeView.ItemTemplate>
        </TreeView>


Unten finden Sie einen Beispiel-Screenshot.



1708983214205.png

Ich habe nur versucht, eine allgemeine Vorstellung zu vermitteln. Sie kennen diese Struktur wahrscheinlich.



MfG / Best Regards
 
Zuletzt bearbeitet von einem Moderator:
Guten Abend, danke f├╝r ihre Antwort.

Ich bin meinem Ziel schon ein gutes St├╝ck n├Ąher gekommen. Meine TreeView zeigt alle Ordner mit ihren enthaltenen Dateien an. Da ich allerdings Ordner und Dateien in meinem RootNode erwarte, habe ich in dieser Klasse 2 Collections implementiert. Wie bekommt man in der TreeView eine hierarchische Ordnerstruktur und die im RootNode enthaltenen Dateien angezeigt? Dazu m├╝sste ich ├╝ber ein Binding auf 2 verschiedene Collections in der RootNodeklasse zugreifen k├Ânnen.

Mein bisheriger Code ist bei Github hochgeladen -> https://github.com/Gewinde/OrdnerDurchlaufen
 
Hallo,

es tut mir leid, dass ich Ihnen sp├Ąt antworte. Dies h├Ąngt davon ab, wie Sie die Datei-Anzeigemodule anzeigen m├Âchten. Nehmen wir zum Beispiel an, wir wollen ein ordneranzeigesystem erstellen. Der wichtigste Punkt hierbei ist, dass Sie beim ├ľffnen des Programms nicht alle Ordner laden.

Wir haben eine TreeView-Struktur und wenn der Benutzer auf den gew├╝nschten Knoten klickt, beginnt der Auflistungsprozess. Wir werden sie also nicht alle vorher in ein Objekt laden. Auf diese Weise belasten wir unsere Tabellenstruktur im Hintergrund nicht zus├Ątzlich. Als ersten Schritt legen wir einen Startpunkt fest, denn wenn unsere Anwendung ge├Âffnet wird, wird dies der Hauptordner der Suchen sein und der Benutzer kann diesen Ordner nach Belieben durchsuchen. Oder es kann in seinen Unterordnern navigieren. Genau wie Windows/Linux usw. Systeme. Obwohl es in diesem Beispiel so aussieht, als ob keine Last auf ein Objekt belastet wird, k├Ânnen Sie tats├Ąchlich sehen, dass die Unterordner mit jedem Klick in einem Objekt gespeichert werden. Bei kleinen Prozess stellt dies m├Âglicherweise kein Problem dar. Beim Einsatz in Systemen mit Millionen von Ordnersystemen weist es jedoch eine sehr schlechte Struktur auf.

Sie k├Ânnen die Codes, die ich unten vorbereitet habe, ausprobieren, um Ihnen eine Vorstellung von einer Konsolenanwendung zu geben.
(Das sind Codes, die in gro├čer Eile geschrieben wurden. Bitte entschuldige mich ich, wenn die Code Fehler hat. Es gab bei mir keine Fehler, als ich es ein paar Mal ausf├╝hrte.)

C#:
private
static DataTable folderTable;

static void Main(string[] args) {
  //SearchOption.TopDirectoryOnly : Weil ich nicht alle Verzeichnisse auf einmal mit AllDirectories Option laden m├Âchte.
    foreach (string item in Directory.GetDirectories(@"C:\", "*", SearchOption.TopDirectoryOnly))
    {
    Console.WriteLine(item);
    }

    if (InitFolderStructure())
    {
    long id = 0;
    string mainPath = @"C:\"; string[] dirs = GetDeirectories(mainPath);
    folderTable.Rows.Add(id, id, Path.GetDirectoryName(mainPath), mainPath); //Wir sind in Zero, weil das Pfad C:\ ist oder haupt Node ist.

    if (dirs != null)
      ListDirectories(mainPath, 0);
    }

    Console.WriteLine();
    GetKey(0);

    Console.Read();
}

static void GetKey(long folderId) {
  long selectedIndex;
  bool exit = true;

  if (folderId != -1)
    Console.Write("Dr├╝cken Sie eine vorhandene Nummer, um die Verzeichnisse aufzulisten : ");
  else
    Console.Write("Bitte dr├╝cken Sie die existierte Nummer, um die Verzeichnisse aufzulisten : ");

  Console.WriteLine();

  while (exit)

  {
    selectedIndex = Convert.ToInt64(Console.ReadLine().Trim());

    if (folderTable.Rows.Contains(selectedIndex)) {
      string tmp = folderTable.Rows.Find(selectedIndex)[3].ToString(); //3 oder "folderPath"..
      ListDirectories(tmp, selectedIndex);
    } else {
      GetKey(-1);
    }
  }

  GetKey(folderId);
}

static void ListDirectories(string path, long folderId) {
  long ind = folderTable.Rows.Count;

  if (!string.IsNullOrEmpty(path)) {
    foreach (string item in Directory.GetDirectories(path, "*", SearchOption.TopDirectoryOnly)) {
      Console.WriteLine($ "{ind}  -) " + item);

      if (folderTable.Rows.Contains(ind + 1) == false)
        AddFolderToStructure(ind, folderId, Path.GetDirectoryName(item), item);

      ind++;
    }
    GetKey(folderId);
  } else
    GetKey(-1);
}

//Das Verzeichnislistensystem funktioniert hier durch die Aufzeichnung in DataTable.
//Nat├╝rlich h├Ątte besserer Code geschrieben werden k├Ânnen. Ohne eine DataTable kann die Laufzeit beispielsweise fortfahren, indem sie nur eine Adresse vom Typ String beh├Ąlt.
static bool AddFolderToStructure(long id, long parentId, string folderName, string folderPath) {
  try {
    folderTable.Rows.Add(id, parentId, folderName, folderPath);

    //usw..

    return true;
  } catch (Exception xErr) {
    Console.WriteLine($ "Fehler : \n{xErr.Message}");
  }
  return false;
}

//Es handelt sich um eine modifizierte Version der DataTable-Struktur im Xaml-Beispiel, das ich zuvor gegeben habe.
static bool InitFolderStructure() {
  folderTable = new DataTable("FolderTemplates");

  //Sie k├Ânnen den long Type Object durch GUID ersetzen. Dies variiert je nach Planung Ihres Projekts.
  folderTable.PrimaryKey = new System.Data.DataColumn[]{folderTable.Columns.Add("ID", typeof(long))};

  //Sie k├Ânnen den long Type Object durch GUID ersetzen. Dies variiert je nach Planung Ihres Projekts.
  folderTable.Columns.Add("parentID", typeof(long));
  folderTable.Columns.Add("folderName", typeof(string));
  folderTable.Columns.Add("folderPath", typeof(string));

  //..usw zur Initialisierung

  return true;
}

MfG / Best Regards
 
Zuletzt bearbeitet von einem Moderator:
Zur├╝ck
Oben Unten