是否可以为“普通”定义TreeView分层视图模板。采集?

时间:2015-02-05 09:22:33

标签: c# wpf mvvm treeview datatemplate

我的模型类看起来像这样:

class Base 
{ 
    public string Name { get; set; }
}

class Item : Base { ... }

class Group : Base 
{
    public List<Base> GroupItems { get; private set; }
}

然后,我有一个带有Items集合的视图模型,我填写如下FillUp()方法中所示:

class ViewModel : INotifyPropertyChanged
{
    public ObservableCollection<Base> Items { get; set; }

    private void FillUp()
    {
        Item item1 = new Item { Name = "Item1" };
        Item item2 = new Item { Name = "Item2" };
        Group group = new Group { Name = "Group" };
        group.GroupItems.Add(item1);
        this.Items.Add(item1);
        this.Items.Add(item2);
        this.Items.Add(group);
    }
}

因此,我的Items集合现在包含2个类型为Item的对象和一个类型为Group的对象,其中包含对{{1}之一的“父子”引用对象。

我想要实现的目标:我想在Item中显示此模型,以便属于某些TreeView的所有Item都应显示为子元素Group,尽管它们属于“根”集合。

它应该是这样的:

Group

我可以使用- Item2 + Group - Item1 来显示父子元素,但这不允许我从根集合中过滤掉属于某些组的那些项目。

HierarchicalDataTemplate

有了这个观点,我得到<TreeView> <TreeView.Resources> <HierarchicalDataTemplate DataType = "{x:Type loc:Group}" ItemsSource = "{Binding GroupItems}"> <TextBlock Text="{Binding Name}"/> </HierarchicalDataTemplate> <DataTemplate DataType="{x:Type loc:Item}"> <TextBlock Text="{Binding Name}"/> </DataTemplate> </TreeView.Resources> <TreeViewItem ItemsSource="{Binding Items}"/> </TreeView> 两次:

"Item1"

有没有办法通过视图(XAML)标记获得所需的结果?否则,我应该更改我的视图模型,以便- Item1 - Item2 + Group - Item1 只会添加到Item中,而不会添加到“根”集合中(但这是我目前要避免的)

3 个答案:

答案 0 :(得分:0)

您可以在ViewModel中为所有项目定义两个集合,为树子定义一个集合,这似乎很简单。

class ViewModel
{
    public ObservableCollection<Base> AllItems { get; set; }
    public ObservableCollection<Base> RootLevelItems { get; set; }
}

如果您只有两个级别(例如没有嵌套组),则可以将ListView与GroupStyle一起使用。

答案 1 :(得分:0)

假设您有一些关于哪个项属于某个组的指示,对于此示例,我在组和项类中添加了一个Guid。

你可以通过两种方式解决这个问题:

1)创建一个复合包装类。    并创建一个Wrapper类的ItemsSource。如果有一个项目不属于某个组,则子项将保持为空。

public class Wrapper<T> where T : Base
{
    public List<T> Children { get; set; }
}

public class Base 
{ 
    public string Name { get; set; }
}

public class Item : Base
{
    public Guid GroupId { get; set; }
}

public class Group : Base 
{
    public Guid ID { get; set; }
    public List<Item> GroupItems { get; private set; }
}

您的第二个选择是使用CollectionView,并过滤掉属于某个组的项目。

private ICollectionView _baseView;
public ICollectionView BaseView
{

    get
    {
        if (_baseView == null)
        {
            _baseView = new ListCollectionView((IList) items);
            _baseView.Filter = o => o is Group || o is Item && (o as Item).GroupId != Guid.Empty;                   
        }
        return _baseView;
    }
}

答案 2 :(得分:0)

回应你的评论:

  

顺便说一句,集合中没有重复项,正如您在我的代码中看到的那样 - 它只是显示项目两次的视图。

你说你的代码没有重复,但显然有:

private void FillUp()
{
    Item item1 = new Item { Name = "Item1" };
    Item item2 = new Item { Name = "Item2" };
    Group group = new Group { Name = "Group" };
    group.GroupItems.Add(item1);  // Adding item1 into collection in Group 
    this.Items.Add(item1);  // Adding item1 into collection again
    this.Items.Add(item2);
    this.Items.Add(group);
}

因此,正如我所说,这是预期的行为TreeView只显示你告诉它的内容。因此,要删除重复的项目,只需将其添加到您的集合中即可:

private void FillUp()
{
    Item item1 = new Item { Name = "Item1" };
    Item item2 = new Item { Name = "Item2" };
    Group group = new Group { Name = "Group" };
    group.GroupItems.Add(item1);  // Adding item1 into collection in Group 
    // this.Items.Add(item1);  // Don't add item1 into collection again
    this.Items.Add(item2);
    this.Items.Add(group);
}