added docs on generic treeview

This commit is contained in:
tznind
2021-01-22 22:04:14 +00:00
parent 4b6f3569ef
commit 518e58d90d
3 changed files with 202 additions and 5 deletions

View File

@@ -25,6 +25,8 @@ namespace UICatalog.Scenarios {
new MenuBarItem ("_Scenarios", new MenuItem [] {
new MenuItem ("_Simple Nodes", "", () => LoadSimpleNodes()),
new MenuItem ("_Rooms", "", () => LoadRooms()),
new MenuItem ("_Armies With Builder", "", () => LoadArmies(false)),
new MenuItem ("_Armies With Delegate", "", () => LoadArmies(true)),
}),
});
@@ -101,6 +103,88 @@ namespace UICatalog.Scenarios {
currentTree = tree;
}
private abstract class GameObject
{
}
private class Army : GameObject
{
public string Designation {get;set;}
public List<Unit> Units {get;set;}
public override string ToString ()
{
return Designation;
}
}
private class Unit : GameObject
{
public string Name {get;set;}
public override string ToString ()
{
return Name;
}
}
private class GameObjectTreeBuilder : ITreeBuilder<GameObject> {
public bool SupportsCanExpand => true;
public bool CanExpand (GameObject model)
{
return model is Army;
}
public IEnumerable<GameObject> GetChildren (GameObject model)
{
if(model is Army a)
return a.Units;
return Enumerable.Empty<GameObject>();
}
}
private void LoadArmies(bool useDelegate)
{
var army1 = new Army()
{
Designation = "3rd Infantry",
Units = new List<Unit>{
new Unit(){Name = "Orc"},
new Unit(){Name = "Troll"},
new Unit(){Name = "Goblin"},
}
};
if(currentTree != null)
Win.Remove(currentTree);
var tree = new TreeView<GameObject>()
{
X = 0,
Y = 0,
Width = 40,
Height = 20
};
if(useDelegate){
tree.TreeBuilder = new DelegateTreeBuilder<GameObject>((o)=>o is Army a ? a.Units : Enumerable.Empty<GameObject>());
}
else{
tree.TreeBuilder = new GameObjectTreeBuilder();
}
Win.Add(tree);
tree.AddObject(army1);
currentTree = tree;
}
private void Quit ()
{
Application.RequestStop ();

View File

@@ -26,6 +26,7 @@ namespace UICatalog.Scenarios {
private MenuItem miColoredSymbols;
private MenuItem miInvertSymbols;
private MenuItem miUnicodeSymbols;
private MenuItem miFullPaths;
private Terminal.Gui.Attribute green;
private Terminal.Gui.Attribute red;
@@ -52,6 +53,7 @@ namespace UICatalog.Scenarios {
null /*separator*/,
miColoredSymbols = new MenuItem ("_ColoredSymbols", "", () => ShowColoredExpandableSymbols()){Checked = false, CheckType = MenuItemCheckStyle.Checked},
miInvertSymbols = new MenuItem ("_InvertSymbols", "", () => InvertExpandableSymbols()){Checked = false, CheckType = MenuItemCheckStyle.Checked},
miFullPaths = new MenuItem ("_FullPaths", "", () => SetFullName()){Checked = false, CheckType = MenuItemCheckStyle.Checked},
}),
});
Top.Add (menu);
@@ -171,6 +173,16 @@ namespace UICatalog.Scenarios {
treeViewNodes.SetNeedsDisplay();
}
private void SetFullName()
{
miFullPaths.Checked = !miFullPaths.Checked;
if(miFullPaths.Checked)
treeViewFiles.AspectGetter = (f)=>f.FullName;
else
treeViewFiles.AspectGetter = (f)=>f.Name;
}
private ITreeNode CreateSimpleRoot ()
{

View File

@@ -96,10 +96,111 @@ tree.AddObject(myHouse);
```
Alternatively you can simply tell the tree how the objects relate to one another by implementing `ITreeBuilder`. This is a good option if you don't have control of the data objects you are working with:
```
TODO
```
Alternatively you can simply tell the tree how the objects relate to one another by implementing `ITreeBuilder<T>`. This is a good option if you don't have control of the data objects you are working with.
## TreeView<T>
The generic `Treeview<T>` allows you to store any object hierarchy where nodes implement Type T. For example if you are working with `DirectoryInfo` and `FileInfo` objects then you could create a `TreeView<FileSystemInfo>`. If you don't have a shared interface/base class for all nodes you can still declare a `TreeView<object>`.
In order to use `TreeView<T>` you need to tell the tree how objects relate to one another (who are children of who). To do this you must provide an `ITreeBuilder<T>`.
### Implementing ITreeBuilder<T>
Consider a simple data model that already exists in your program:
```csharp
private abstract class GameObject
{
}
private class Army : GameObject
{
public string Designation {get;set;}
public List<Unit> Units {get;set;}
public override string ToString ()
{
return Designation;
}
}
private class Unit : GameObject
{
public string Name {get;set;}
public override string ToString ()
{
return Name;
}
}
```
An `ITreeBuilder<T>` for these classes might look like:
```csharp
private class GameObjectTreeBuilder : ITreeBuilder<GameObject> {
public bool SupportsCanExpand => true;
public bool CanExpand (GameObject model)
{
return model is Army;
}
public IEnumerable<GameObject> GetChildren (GameObject model)
{
if(model is Army a)
return a.Units;
return Enumerable.Empty<GameObject>();
}
}
```
To use the builder in a tree you would use:
```
var army1 = new Army()
{
Designation = "3rd Infantry",
Units = new List<Unit>{
new Unit(){Name = "Orc"},
new Unit(){Name = "Troll"},
new Unit(){Name = "Goblin"},
}
};
var tree = new TreeView<GameObject>()
{
X = 0,
Y = 0,
Width = 40,
Height = 20,
TreeBuilder = new GameObjectTreeBuilder()
};
tree.AddObject(army1);
```
Alternatively you can use `DelegateTreeBuilder<T>` instead of implementing your own `ITreeBuilder<T>`. For example:
```
tree.TreeBuilder = new DelegateTreeBuilder<GameObject>(
(o)=>o is Army a ? a.Units
: Enumerable.Empty<GameObject>());
```
## Node Text and ToString
The default behaviour of TreeView is to use the `ToString` method on the objects for rendering. You can customise this by changing the `AspectGetter`. For example:
```
treeViewFiles.AspectGetter = (f)=>f.FullName;
```