How to bind two different collection at one TreeView branch

て烟熏妆下的殇ゞ 提交于 2020-02-07 05:21:05

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!