【问题标题】:How do I use a WPF TreeView HierarchicalDataTemplate with LINQ to Entities?如何将 WPF TreeView HierarchicalDataTemplate 与 LINQ to Entities 一起使用?
【发布时间】:2010-09-21 03:16:15
【问题描述】:

我的 .edmx ADO.NET 实体数据模型文件中有一个 Page 类,带有 Parent 和 Children 属性。它用于页面的层次结构。

删除了无效的 ImageShack 链接 - ADO.NET 实体框架分层页面类

这是在我的 SQL 数据库中处理的,Page 表中的 ParentId 外键绑定到同一个 Page 表的 Id 主键。

如何在 WPF TreeView 中显示此层次结构?

【问题讨论】:

  • 您的图片链接似乎已损坏。如果您仍有原始图像,请将其重新上传到 stack.imgur,或者只是编辑您的问题以使其在没有图像的情况下工作。谢谢。

标签: wpf linq entity-framework data-binding xaml


【解决方案1】:

我在Abe Heidebrecht 的帮助下完成了这项工作。非常感谢他。

这是我的 XAML...

<Window x:Class="Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:PageManager"
    Title="Window1" Height="300" Width="300" Name="Window1">
    <Grid>
        <TreeView Margin="12" Name="TreeViewPages" ItemsSource="{Binding}" TreeViewItem.Expanded="TreeViewPages_Expanded">
            <TreeView.Resources>
                <HierarchicalDataTemplate DataType="{x:Type local:Page}" ItemsSource="{Binding Children}">
                    <TextBlock Text="{Binding Path=ShortTitle}" />
                </HierarchicalDataTemplate>
            </TreeView.Resources>
        </TreeView>
    </Grid>
</Window>

这是我的 Visual Basic 代码...

Class Window1

    Private Sub Window1_Loaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded
        Dim db As New PageEntities
        Dim RootPage = From p In db.Page.Include("Children") _
                       Where (p.Parent Is Nothing) _
                       Select p
        TreeViewPages.ItemsSource = RootPage
    End Sub

    Private Sub TreeViewPages_Expanded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
        Dim ExpandedTreeViewItem As TreeViewItem = DirectCast(e.OriginalSource, TreeViewItem)
        Dim PageId As Guid = DirectCast(ExpandedTreeViewItem.DataContext, Page).Id
        Dim db As New PageEntities
        Dim ChildPages = From p In db.Page.Include("Children") _
                         Where p.Parent.Id = PageId _
                         Select p
        ExpandedTreeViewItem.ItemsSource = ChildPages
    End Sub
End Class

当窗口加载时,从数据库中查询根节点及其子节点并插入到树中。

每次展开节点时,都会从数据库中查询该节点的子节点和孙节点并将其插入树中。

【讨论】:

  • 有了这样的代码隐藏你可以使用DataTemplate而不是&lt;HierarchicalDataTemplate DataType="{x:Type local:Page}" ItemsSource="{Binding Children}"&gt;
【解决方案2】:

另一种方式:(嗯,非常相似,但略有不同)

在您的窗口加载功能中:

PageEntities db = new PageEntities();
TreeViewPages.ItemsSource = db.Page.Where(u=>u.Parent==null);

新建文件Page.cs

public partial class Page {
    public ObjectQuery<Page> LoadedChildren {
        get {
            var ret = Children;
            if(ret.IsLoaded==false) ret.Load();
            return ret;
        }
    }
}

在您的 XAML 中:

<TreeView Name="TreeViewPages">
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate ItemSource="{Binding LoadedChildren}">
            <TextBlock Text="{Binding ShortTitle}" />
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>

它没有经过测试,但您应该了解大致的概念。

【讨论】:

  • 此方法一次加载整个层次结构。之前接受的答案是按需加载子节点。
【解决方案3】:

第二种解决方案最适合我。我有一个递归对象列表,所以这是我使用的 XAML:

<TreeView Height="Auto" HorizontalAlignment="Stretch" Name="trvVaults" VerticalAlignment="Stretch" Width="Auto" Grid.Column="0" Margin="5">
    <!--  Treeview ItemsSource is loaded programmatically  -->
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource="{Binding Vaults}">
            <TextBlock Text="{Binding Name}" />
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>

每个“保险库”对象都有几个属性(名称、位置等)和一个通用的“保险库”列表。

【讨论】:

    猜你喜欢
    • 2010-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多