ASP.NET Core Blazor:
This example describes how to use a tree list control to show hierarchical data in an XAF ASP.NET Core Blazor applications. The example uses the DxTreeListEditor
.
If you implement the ITreeNode interface in a business object class, the DxTreeListEditor
automatically displays the hierarchical data.
Windows Forms
This example describes how to use a tree list control to show hierarchical data in an XAF Windows Forms applications. For this purpose, the example uses the TreeListEditor
and CategorizedListEditor
supplied with the TreeListEditorsWindowsFormsModule.
Implementation Details
The example uses the following techniques:
- A List View that defines objects of a type that implements the ITreeNode interface. XAF uses the TreeListEditor to display this View.
Files to review:- The Category class.
- The
Category
class' descendants: ProjectGroup, Project, and ProjectArea
For more information, refer to the following help topics: TreeList Editors Module and Display a Tree List using the ITreeNode interface.
NOTE
Windows Forms only — In ASP.NET Core Blazor, XAF uses
DxTreeListEditor
whenITreeNode
is implemented. You do not need to add a separate module to your project.
- A List View that defines objects of a type that implements the ICategorizedItem interface. XAF uses the CategorizedListEditor to display this View.
NOTE
This is valid only for XAF Windows Forms applications. XAF ASP.NET Core Blazor does not support the
CategorizedListEditor
.
Files to review:
- The Issue class
- The CategoryWithIssues class that is related to the previous class by a One-to-Many relationship.
For details, refer to the following topic: Categorized List.
3. A List View that defines objects of the HCategory
type supplied with the Business Class Library. XAF uses the TreeListEditor
to display this View. To add the HCategory
class to the application's business model, use the following technique: Ways to Add a Business class.
For more information, refer to the following topic: Display a Tree List using the HCategory class.
Files to Review
Documentation
- Layout - There are circumstances that cause the "Error creating window handle" error to occur when you alter the MasterDeailMode option.
- TreeList Editors Module
- Display a Tree List using the ITreeNode interface
Does this example address your development requirements/objectives?
(you will be redirected to DevExpress.com to submit your response)
Example Code
C#using System;
using DevExpress.ExpressApp;
using DevExpress.Persistent.Base;
using DevExpress.Persistent.BaseImpl;
using DevExpress.Persistent.Validation;
using DevExpress.Persistent.Base.General;
using System.ComponentModel;
using DevExpress.Persistent.BaseImpl.EF;
namespace HowToUseTreeListEditor.Module {
[NavigationItem]
public abstract class Category : BaseObject, ITreeNode {
protected abstract ITreeNode Parent {
get;
}
protected abstract IBindingList Children {
get;
}
public virtual string Name { get; set; }
#region ITreeNode
IBindingList ITreeNode.Children {
get {
return Children;
}
}
string ITreeNode.Name {
get {
return Name;
}
}
ITreeNode ITreeNode.Parent {
get {
return Parent;
}
}
#endregion
}
}
C#using System;
using DevExpress.ExpressApp;
using DevExpress.Persistent.Base;
using DevExpress.Persistent.BaseImpl;
using DevExpress.Persistent.Validation;
using DevExpress.Persistent.Base.General;
using System.ComponentModel;
using System.Collections.ObjectModel;
namespace HowToUseTreeListEditor.Module {
public class ProjectGroup : Category {
protected override ITreeNode Parent {
get {
return null;
}
}
BindingList<Project> children;
protected override IBindingList Children {
get {
if (children == null) {
children = new BindingList<Project>(Projects);
}
return children;
}
}
public virtual IList<Project> Projects { get; set; }= new ObservableCollection<Project>();
}
}
C#using System;
using DevExpress.ExpressApp;
using DevExpress.Persistent.Base;
using DevExpress.Persistent.BaseImpl;
using DevExpress.Persistent.Validation;
using DevExpress.Persistent.Base.General;
using System.ComponentModel;
using System.Collections.ObjectModel;
namespace HowToUseTreeListEditor.Module {
public class Project : Category {
protected override ITreeNode Parent {
get {
return ProjectGroup;
}
}
BindingList<ProjectArea> children;
protected override IBindingList Children {
get {
if (children == null) {
children = new BindingList<ProjectArea>(ProjectAreas);
}
return children;
}
}
public virtual ProjectGroup ProjectGroup { get; set; }
public virtual IList<ProjectArea> ProjectAreas { get; set; } = new ObservableCollection<ProjectArea>();
}
}
C#using System;
using DevExpress.ExpressApp;
using DevExpress.Persistent.Base;
using DevExpress.Persistent.BaseImpl;
using DevExpress.Persistent.Validation;
using DevExpress.Persistent.Base.General;
using System.ComponentModel;
namespace HowToUseTreeListEditor.Module {
public class ProjectArea : Category {
protected override ITreeNode Parent {
get {
return Project;
}
}
protected override IBindingList Children {
get {
return new BindingList<object>();
}
}
public virtual Project Project { get; set; }
}
}
C#using System;
using DevExpress.ExpressApp;
using DevExpress.Persistent.Base;
using DevExpress.Persistent.BaseImpl;
using DevExpress.Persistent.Validation;
using DevExpress.Persistent.Base.General;
using DevExpress.Persistent.BaseImpl.EF;
namespace HowToUseTreeListEditor.Module {
[DefaultClassOptions]
public class Issue : BaseObject, ICategorizedItem {
public virtual CategoryWithIssues Category { get; set; }
public virtual string Subject { get; set; }
public virtual string Description { get; set; }
ITreeNode ICategorizedItem.Category {
get {
return Category;
}
set {
Category = (CategoryWithIssues)value;
}
}
}
}
C#using System;
using DevExpress.ExpressApp;
using DevExpress.Persistent.Base;
using DevExpress.Persistent.BaseImpl;
using DevExpress.Persistent.Validation;
using DevExpress.Persistent.Base.General;
using System.ComponentModel;
using DevExpress.Persistent.BaseImpl.EF;
using System.Collections.ObjectModel;
using Castle.Components.DictionaryAdapter;
using System.ComponentModel.DataAnnotations.Schema;
namespace HowToUseTreeListEditor.Module {
[NavigationItem]
public abstract class CategoryWithIssues : BaseObject, ITreeNode {
public virtual IList<Issue> Issues { get; set; } = new ObservableCollection<Issue>();
private List<Issue> allIssues;
[NotMapped]
public IList<Issue> AllIssues {
get {
if (allIssues == null) {
allIssues = new List<Issue>();
CollectIssuesRecursive(this, allIssues);
}
return allIssues;
}
}
private void CollectIssuesRecursive(CategoryWithIssues issueCategory, List<Issue> target) {
target.AddRange(issueCategory.Issues);
foreach (CategoryWithIssues childCategory in issueCategory.Children) {
CollectIssuesRecursive(childCategory, target);
}
}
protected abstract ITreeNode Parent {
get;
}
protected abstract IBindingList Children {
get;
}
public virtual string Name { get; set; }
#region ITreeNode
IBindingList ITreeNode.Children {
get {
return Children;
}
}
string ITreeNode.Name {
get {
return Name;
}
}
ITreeNode ITreeNode.Parent {
get {
return Parent;
}
}
#endregion
}
}