问题
I'm writing a WpfCustomControlLibrary based on MVVM pattern. I have a View contains TreeView object which must handle quite expanded model.
Model:
public class TreeBranchesView
{
public ObservableCollection<DiscountGroup> DiscoutGroups { get; set; }
}
public class DiscountGroup : ViewModelBase
{
public int ID { get; set; }
public string GroupName { get; set; }
public decimal DefaultValue { get; set; }
private bool _isCheckedInMenu;
public bool IsCheckedInMenu
{
get { return _isCheckedInMenu; }
set
{
_isCheckedInMenu = value;
OnPropertyChanged("IsCheckedInMenu");
}
}
public ObservableCollection<SubGroup> SubGroups { get; set; }
public ObservableCollection<ArticleGroup> ArticleGroup { get; set; }
}
public class SubGroup : ViewModelBase
{
public int ID { get; set; }
public int SubGroupParent { get; set; }
public string Name { get; set; }
public decimal DefaultValue { get; set; }
public ObservableCollection<ArticleGroup> ArticleGroup { get; set; }
}
public class ArticleGroup
{
public int ArticleID { get; set; }
public int DiscountGroup { get; set; }
public int SubGroup { get; set; }
}
My main goal is to achieve below situation:
-DiscountGroup
--ArticleGroup
--ArticleGroup
-DiscountGroup
--ArticleGroup
--ArticleGroup
--SubGroup
--SubGroup
--SubGroup
---ArticleGroup
---ArticleGroup
-DiscountGroup
-DiscountGroup
--SubGroup
ArticleGroup and SubGroups can be located at the same level. Actualy my xaml looks like:
<GroupBox Grid.Column="0" Grid.Row="0" Header="MainTree">
<StackPanel Orientation="Horizontal">
<TreeView x:Name="MainTreeView" Grid.Column="0" Grid.Row="0" ItemTemplate="{StaticResource level1}"
ItemsSource="{Binding TreeBranches}" />
</StackPanel>
</GroupBox>
all templates are stored under windows.resources
<Window.Resources>
<HierarchicalDataTemplate x:Key="level2" ItemsSource="{Binding ArticleGroup}" >
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" />
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate x:Key="level1" ItemsSource="{Binding SubGroups}" ItemTemplate="{StaticResource level2}" >
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding GroupName}" />
</StackPanel.ContextMenu>
</StackPanel>
</HierarchicalDataTemplate>
</Window.Resources>
I have the following problem - TreeView must show two different collection at the same level and above code doesn't allow to do it , at this moment it handle only one. What is important, these collections don't have the same type.
回答1:
One solution is to create a base class, lets say TreeNode, for the items which will be placed in the tree. This base class has this interface:
public interface ITreeNode
{
ObservableCollection<ITreeNode> Children { get; set; }
string Name { get; set; }
ITreeNode Parent { get; set; }
void AddChild(ITreeNode child);
void RemoveChild(ITreeNode child);
}
Make the classes that need to appear on the tree to be inherited from the TreeNode class:
public class DiscountGroup: TreeNode{};
public class SubGroup: TreeNode {}
public class ArticleGroup: TreeNode{}
Then define a root for your tree like:
Root = new TreeNode() {Name="Root"};
Add some branches
var dg1 = new DiscountedGroup(){Name = "DG1"};
var dg1 = new DiscountedGroup(){Name = "DG1"};
Root.AddChild(dg1);
Root.AddChild(dg2};
Add some children to branches
dg1.AddChild(new ArticleGroup());
dg1.AddChild(new SubGroup());
dg2.AddChild(new ArticleGroup());
dg2.Add(new SubGroup());
You can add as many layers as you like. Then, In Xaml, bind root.Children to your TreeView.TreeViewItem.ItemsSource.
Make sure in Xaml=>TreeViewItem.Resources you have HierarchicalDataTemplate defined for Objects (or classes) which have children (otherwise just use DataTemplate) and use TreeViewItem.ItemTemplateSelector for detecting right data template for each class.
There are more details into it, I tried to explain generally.
来源:https://stackoverflow.com/questions/56703365/how-to-bind-two-different-collection-at-one-treeview-branch