【问题标题】:Bind collection to Treeview in WPF将集合绑定到 WPF 中的 Treeview
【发布时间】:2014-02-20 18:32:04
【问题描述】:

我正在尝试将集合绑定到树视图。到目前为止,我的尝试都失败了。 尽管我读过有关此事的文章,但我还是错过了一些东西。

到目前为止,我尝试了类似的东西,但是 Treeview 只是绘制了 A 类的 Id,仅此而已,没有可展开的按钮。

<Grid>
        <TreeView HorizontalAlignment="Left" Height="270" VerticalAlignment="Top" Width="292" ItemsSource="{Binding ManagerObjects}">
            <TreeView.Resources>
                <HierarchicalDataTemplate DataType="{x:Type local:ManagerObject}" ItemsSource="{Binding MyManager}">
                    <TextBlock Text="{Binding Id}"/>
                </HierarchicalDataTemplate>
                <HierarchicalDataTemplate DataType="{x:Type local:Manager}" ItemsSource="{Binding ManagerClientServerProperty}">

                    <TextBlock Text="{Binding ManagerClientServerProperty}"/>
                </HierarchicalDataTemplate>
                <HierarchicalDataTemplate DataType="{x:Type local1:ManagerClientServer}">

                    <TextBlock Text="TEST"/>
                </HierarchicalDataTemplate>
                <HierarchicalDataTemplate DataType="{x:Type local1:NetworkObject}" ItemsSource="{Binding Entities}">

                    <TextBlock Text="TEST"/>
                </HierarchicalDataTemplate>
                <HierarchicalDataTemplate DataType="{x:Type local1:RemoteEntity}" ItemsSource="{Binding Fields}">
                    <TextBlock Text="TEST"/>
                    <!-- how classD should look like -->
                </HierarchicalDataTemplate>
            </TreeView.Resources>

        </TreeView>

    </Grid>

编辑:添加真实代码

这是在我的模型中:

public class ManagerObject
{
    // PROPERTIES
    public int Id { get; private set; }
    public Manager MyManager { get; private set; }
}

public class Manager
    {
    // FIELDS
        private readonly ManagerClientServer managerClientServer;
    // PROPERTIES
        public ManagerClientServer ManagerClientServerProperty { get { return managerClientServer;} }

    /**** OTHER STUFF NON IMPORTANT ****/

    }

public class ManagerClientServer
{
    // FIELDS
    private readonly ObservableCollection<NetworkObject> Clients = new ObservableCollection<NetworkObject>();
    private readonly ObservableCollection<NetworkObject> Servers = new ObservableCollection<NetworkObject>();
    // PROPERTIES
    public ObservableCollection<NetworkObject> ClientsProperty
    {
        get { return Clients; }
    }

    public ObservableCollection<NetworkObject> ServersProperty
    {
        get { return Servers; }
    }
     /*** OTHER STUFF NON IMPORTANT HERE ***/
}
public class NetworkObject
{
    // FIELDS
    private readonly ObservableCollection<RemoteEntity> _entities=new ObservableCollection<RemoteEntity>();
    public uint NetworkId { get; private set; }
    // PROPERTIES
    public ObservableCollection<RemoteEntity> Entities
    {
        get { return _entities; }
    }
    // CONSTRUCTOR
    public NetworkObject(uint id)
    {
        NetworkId = id;
    }
}

    public class RemoteEntity
{
    // FIELDS
    private readonly ObservableCollection<int> _fields=new ObservableCollection<int>();
    // PROPERTIES

    public bool IsLost { get; set; }
    public bool NeedUpdate { get; set; }
    public uint SessionId { get; private set; }
    public ObservableCollection<int> Fields
    {
        get { return _fields; }
    }
    // CONSTRUCTOR
    public RemoteEntity(uint id)
    {
        SessionId = id;
    }
}

ViewModel 只是暴露了这个属性:

public ObservableCollection<ManagerObject> ManagerObjects
        {
            get { return managerObjects; }

            set
            {
                managerObjects = value;
                NotifyOfPropertyChange(()=>ManagerObjects);
            }
        }
private ObservableCollection<ManagerObject> managerObjects;

初始化只是 2 个 ManagerObject,之后它们在 Clients 和 Servers 集合中都包含随机数量的 NetworkObjects,并且每个都有随机数量的 Entities。

这里的所有集合都是可观察的,但是,它们实际上是另一种类型,但它们公开了一个可以使它们可观察的方法,所以让我们这样考虑。

非常感谢。

【问题讨论】:

  • 您的 ItemsSource 不应该是类的集合吗?这将是一个父子类,我所说的类是指您的实际实体类。我猜你的 collectionClassA 只有一个 1 的项目,其中有 classA。你能显示更多代码吗,比如你的模型和视图模型
  • collectionclassA 是一个 ObservableCollection ,其中包含两个项目。它是我的 ViewModel 的一个属性。
  • 您想创建一个 ObservableCollection,其中包括 ClassA、ClassD、ClassE,其子属性也是 Observable,其中包含相应的子属性。
  • 嗯,我想这已经完成了。当您查看我的模型时:ClassA 包含对 ClassB 的引用,其中包含对 ClassC 的引用,其中包含两个 classD 列表...我想像在调试器中看到的那样绘制 collectionClassA。
  • 有人想过吗?

标签: c# wpf treeview


【解决方案1】:

啊,我现在看到了你的问题,这很简单。你不能扩展任何东西,因为没有什么可以扩展的。您的TreeView.ItemsSource 绑定到ManagerObjects 集合,这没关系,因为它是一个集合。但是,在您的 HierarchicalDataTemplate ManagerObject 数据类型中,您有:

<HierarchicalDataTemplate DataType="{x:Type local:ManagerObject}" 
    ItemsSource="{Binding MyManager}"> <!-- Look here -->
    <TextBlock Text="{Binding Id}"/>
</HierarchicalDataTemplate>

您正在尝试将MyManager 属性数据绑定到HierarchicalDataTemplate.ItemsSource 属性,但您不能,因为它不是一个集合。相反,试试这个:

<DataTemplate DataType="{x:Type local:ManagerObject}"> 
    <StackPanel>
        <TextBlock Text="{Binding Id}" />
        <ContentControl Content="{Binding MyManager}" />
    </StackPanel>
</DataTemplate>

您还会遇到类似的其他问题,因此您必须调整一些模板。例如,这不起作用,因为ManagerClientServerProperty 属性不是集合

<HierarchicalDataTemplate DataType="{x:Type local:Manager}"
    ItemsSource="{Binding ManagerClientServerProperty}">
    ...
</HierarchicalDataTemplate>

可以这样做:

<HierarchicalDataTemplate DataType="{x:Type local:Manager}"
    ItemsSource="{Binding ManagerClientServerProperty.Clients}">
    ...
</HierarchicalDataTemplate>

...但那将只是其中一个集合。在编写 WPF 时,我了解到始终最好让您的数据具有适合您的 UI 的正确形状。通常,这只是意味着在这里和那里添加一些额外的属性,以使您的工作更容易显示。例如,您可以在您的 ManagerClientServer 类中添加一个额外的属性,而不是在 UI 中使用 CompositeCollection。也许是这样的:

public ObservableCollection<NetworkObject> NetworkObjects
{
    get
    {
        hhh networkObjects = new ObservableCollection<NetworkObject>(Clients);
        networkObjects.Add(Servers);
        return networkObjects;
    }
}

那么你可以这样做:

<HierarchicalDataTemplate DataType="{x:Type local:Manager}"
    ItemsSource="{Binding ManagerClientServerProperty.NetworkObjects}">
    ...
</HierarchicalDataTemplate>

不管怎样,我想你现在明白了,所以我相信你可以自己完成剩下的工作。哦,最后一件事......如果它不起作用,请不要感到惊讶,因为您的数据不是TreeView 期望的正确“形状”。它可能可以工作,但如果不行,请忘记HierarchicalDataTemplates,只需在DataTemplates 中定义ListBoxes 以绑定到内部集合。

【讨论】:

  • 好的,我们更接近了,通过您的解决方案,我可以看到 classB 中的元素,但不是展开/折叠方式,就像 ContentControl 只是在堆栈面板中映射另一个堆栈面板。所以我看到的是 classB 就在 classA 之下,但我不能让它出现/消失
  • 好的,非常感谢,非常感谢。我了解集合列表框的概念,但为什么我不能为第一个关系折叠/展开?
  • 这很简单......你不能因为它不是一个集合。您可以在数据正确形状的层次结构中开始TreeView。如果您有一个 ManagerClientServer 对象的集合,那么这将从那里开始工作,因为每个类都有一个用于下一级层次结构的集合属性。
猜你喜欢
  • 2020-12-29
  • 1970-01-01
  • 1970-01-01
  • 2012-07-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-31
相关资源
最近更新 更多