首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >是否可以为“普通”集合定义TreeView分层视图模板?

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

Stack Overflow用户
提问于 2015-02-05 09:22:32
回答 3查看 316关注 0票数 0

我的模型类如下所示:

代码语言:javascript
复制
class Base 
{ 
    public string Name { get; set; }
}

class Item : Base { ... }

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

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

代码语言:javascript
复制
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集合现在包含两个类型为Item的对象和一个类型为Group的对象,该对象具有对一个Item对象的“父-子”引用。

我想要实现的是:我想在TreeView中显示这个模型,这样属于某些Group的所有Item都应该显示为该Group的子元素,尽管它们在“根”集合中。

然后应该是这样的:

代码语言:javascript
复制
- Item2
+ Group
   - Item1

我可以使用HierarchicalDataTemplate来显示父-子元素,但这不允许我从根集合中筛选出属于某些组的那些项。

代码语言:javascript
复制
<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"

代码语言:javascript
复制
- Item1
- Item2
+ Group
    - Item1

是否有任何方法仅通过视图(XAML)标记获得所需的结果?否则,我应该更改我的视图模型,以便只将Item添加到Group中,而不是在“根”集合中(这是我目前试图避免的)。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-02-05 11:21:40

假设您对哪个项属于一个组有一些指示,那么在这个示例中,iv'e在group和Item类中添加了一个Guid。

你可以从两方面着手:

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

代码语言:javascript
复制
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,并筛选出属于组的项。

代码语言:javascript
复制
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;
    }
}
票数 0
EN

Stack Overflow用户

发布于 2015-02-05 10:56:22

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

代码语言:javascript
复制
class ViewModel
{
    public ObservableCollection<Base> AllItems { get; set; }
    public ObservableCollection<Base> RootLevelItems { get; set; }
}

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

票数 0
EN

Stack Overflow用户

发布于 2015-02-05 12:03:54

在回应你的评论时:

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

您说过您的代码中没有重复项,但显然有:

代码语言:javascript
复制
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只是向你展示你告诉你的。因此,要删除重复项,只需将其添加到您的集合中:

代码语言:javascript
复制
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);
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28340249

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档