我有一个从 WinRT.XamlToolKit 导入的 TreeView,我试图在通用应用程序中使用它。重要的是要注意,我知道有类似的问题,但有些问题因为它们早于通用应用程序而不起作用,或者它们不适应 MVVM 的使用。按照教程了解如何填充树,我遇到了这种递归方法:
private ObservableCollection<TreeViewItemModel> BuildTree(int depth, int branches)
{
var tree = new ObservableCollection<TreeViewItemModel>();
if (depth <= 0) return tree;
var depthIndices = Enumerable.Range(0, branches).Shuffle();
for (var i = 0; i < branches; i++)
{
var d = depthIndices[i] % depth;
var b = _rand.Next(branches / 2, branches);
tree.Add(
new TreeViewItemModel
{
Branch = b,
Depth = d,
Text = "Item " + _itemId++,
Children = BuildTree(d, b)
});
}
return tree;
}
它就是这样调用的,TreeItems = BuildTree(5,5);
然后我将我的 TreeView ItemSource 绑定到 TreeItems 并附加到 TreeViewItemModel 的 Text 属性。
这适用于预先确定的集合,然后如方法中所见,使用随机数来计算树将如何显示。(在什么深度,有多少分支等)
我不确定的是如何实现一个类似的递归函数来用不同的 ItemModel 填充树,其中的子节点数量不确定。在我的设置中,我有一个空间,它可以有子空间、设备和/或传感器。一个空间可以没有设备和传感器,但有一个或多个子空间,或者它可以没有子空间,但它可以有设备和/或传感器。在我的 Sensor 类中,它有一个与它绑定到的空间 ID 和它报告的设备相关的父 ID。
所以,简而言之,我需要ObservableCollection<TreeViewSpaceModel>
从一个空间列表中递归地填充我的空间。
树视图空间模型类:
public class TreeViewSpaceModel : NotifyObject
{
private string _name;
private Guid _iD;
private string _parentName;
private ObservableCollection<TreeViewSpaceModel> _children = new ObservableCollection<TreeViewSpaceModel>();
private ObservableCollection<TreeViewDeviceModel> _devices = new ObservableCollection<TreeViewDeviceModel>();
private ObservableCollection<TreeViewSensorModel> _sensors = new ObservableCollection<TreeViewSensorModel>();
public string Name
{
get { return _name; }
set { SetProperty(ref _name, value); }
}
public string ParentName
{
get { return _parentName; }
set { SetProperty(ref _parentName, value); }
}
public Guid Id
{
get { return _iD; }
set { SetProperty(ref _iD, value); }
}
public ObservableCollection<TreeViewSpaceModel> Children
{
get { return _children; }
set { SetProperty(ref _children, value); }
}
public ObservableCollection<TreeViewDeviceModel> Devices
{
get { return _devices; }
set { SetProperty(ref _devices, value); }
}
public ObservableCollection<TreeViewSensorModel> Sensors
{
get { return _sensors; }
set { SetProperty(ref _sensors, value); }
}
}
DeviceModel 没有子级,但它有传感器,并且 SensorModel 没有子级或设备或传感器,因为它是层次结构的末端。空间类:
public class Space
{
public Guid Id { get; set; }
public string Name { get; set; }
public int SpaceTypeId { get; set; }
public virtual Space Parent { get; set; }
public virtual ICollection<Sensor> Sensors { get; set; }
public virtual ICollection<Device> Devices { get; set; }
public virtual ICollection<Space> Children { get; set; }
}
理想情况下,最终结果看起来像这样:
Space1
---- ChildSpace1
--------Device1
-------------Sensor1
-------------Sensor2 (Sensors report for Spaces, but are bound to Devices)
--------SubChildSpace1
-------------Sensor1
-------------Sensor2
--------SubChildSpace2
-------------Sensor1
------------Sensor2
--------Device2
---- ChildSpace2
Space2
如果有一种更简单的方法而不是递归方法,我很乐意接受它。在研究通用应用程序的 TreeViews 时,我确实遇到过其他人说用户应该能够执行类似的操作items.Node(0).Add(stuffhere)
;但是,我无法弄清楚如何实现这一点,因为 ObservableCollection 没有提供 .Node 扩展。