在WPF中将集合绑定到Treeview

时间:2014-02-20 18:32:04

标签: c# wpf treeview

我正在尝试将集合绑定到树视图。到目前为止,我的尝试失败了。 尽管我读到了有关此事的文章,但我想念一些事情。

到目前为止,我尝试了类似的东西,但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,并且每个都包含随机数量的实体。

这里的所有集合都是Observable,但是,它们是真实的另一种类型,但它们暴露了一种可以使它们成为Observable的方法,所以我们可以这样考虑它。

非常感谢。

1 个答案:

答案 0 :(得分:2)

啊,我现在看到你的问题,这是一个非常简单的问题。你无法扩展任何东西,因为没有什么可以扩展。您的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。通常,这只是意味着在这里和那里添加一些额外的属性,使您的工作更容易显示。例如,您可以在您的CompositeCollection类中添加额外的属性,而不是在UI中使用ManagerClientServer。也许是这样的:

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期望的正确“形状”。 可能工作,但如果没有,请忘记HierarchicalDataTemplate,只需在ListBox中定义DataTemplate es以绑定到内部集合。