WPF TreeView 'folder node' for each Collection of child items
I have a class that has a couple of collections that I want to display in a treeview with a 'folder node' for each collection. Pretty much like SQL Management Studio displays a database with a folder with 'Tables' wich has all the tables under it, a node for 'Views' etc.
Suppose my class looked like this
class DataBase{
public IEnumerable<Table> Tables {get;}
public IEnumerable<View> Views {get;}
public IEnumerable<StoredProc> Procedures {get;}
}
How would the XAML roughly look to get this in my treeview?
+ myDatabase
+ Tables
+ table1
+ Columns
- Column1
- Column2
+ Indexes
- table2
+ Views
- View1
- View2
+ Stored Procedures
- SP1
- SP2
I've looked around but I can't find a clean way to do this, this used to be trivial in winforms because you could just add that 开发者_开发知识库folder node and hold onto it. Can't make this fly in WPF so easily.
Edit: Made some progress (I just thought I could add the nodes through xaml and keep a hold on those)
<TreeView Name="tvModel" Width="200" DockPanel.Dock="Left">
<TreeViewItem Name="tnDatabase">
<TreeViewItem Name="tnTables" Header="Tables"/>
<TreeViewItem Name="tnViews" Header="Views" />
<TreeViewItem Name="tnProcs" Header="Stored Procedures" />
</TreeViewItem>
</TreeView>
then in code:
tnTables.ItemsSource = dataBase.Tables;
etc..
But now I'm stuck at the next stop: each Table class would look like this:
class Table {
IEnumerable<Column> Columns {get;}
IEnumerable<Index> Indexes {get;}
}
So now I want nodes 'columns' and 'indexes' that group those items, for each table node just like the database level. Now it's not so easy anymore because there's no longer just one time this needs to be done, it needs to be done for each table. I updated the tree example above to illustrate.
Edit2: Forget stuff above, doen;t nest well in the end, viewmodel works better. If anyone needs to do this, this worked for me in the end:
// folder class
class CollectionFolder {
public string Name { get; set; }
public IEnumerable Collection { get; set; }
}
class DataBase {
public IEnumerable<Table> Tables { get { for (int i = 0; i < 10; i++) yield return new Table() { Name = "Table " + i }; } }
public IEnumerable<View> Views { get { for (int i = 0; i < 10; i++) yield return new View() { Name = "View" + i }; } }
public IEnumerable<SProc> Sprocs { get { for (int i = 0; i < 10; i++) yield return new SProc() { Name = "Stored Procedure" + i }; } }
// wrap each collection in folder
public IEnumerable<CollectionFolder> Collection {
get {
yield return new CollectionFolder() { Name = "Tables", Collection = Tables };
yield return new CollectionFolder() { Name = "Views", Collection = Views };
yield return new CollectionFolder() { Name = "Stored Procedures", Collection = Sprocs };
}
}
}
class Table {
public string Name { get; set; }
public IEnumerable<CollectionFolder> Collection {
get {
yield return new CollectionFolder() { Name = "Columns", Collection = Columns };
yield return new CollectionFolder() { Name = "Indexes", Collection = Indexes };
}
}
public IEnumerable<Column> Columns { get { for (int i = 0; i < 10; i++) yield return new Column() { Name = "Column " + i }; } }
public IEnumerable<Index> Indexes { get { for (int i = 0; i < 10; i++) yield return new Index() { Name = "Index " + i }; } }
}
class Column { public string Name { get; set; } }
class Index { public string Name { get; set; } }
class View { public string Name { get; set; } }
class SProc { public string Name { get; set; } }
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Collection}">
<TextBlock Text="{Binding Name}"/>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate
>
Thanks GJ
I propose to make a ViewModel that wrapps the items of the main categories (Tables,Views,StoredProcedures). This wrapper contains one collection that the hierarchical data-template gets it's childs from.
It's then up to you, if you make also a ViewModel per type (Table,View,StoredProcedure), return only a generic ViewModel for these types or if you even return your base-objects. This decision depends heavily on how complex the usage o these items in the tree is. Most of times, a generic wrapper will do.
Here you will find an introduction on building trees with MVVM.
精彩评论