分层代码首先EF绑定到WPF Treeview ......不可能

时间:2014-03-08 00:25:17

标签: wpf vb.net entity-framework xaml treeview

在过去,我不得不求助于使用DataSet和DataTables,因为使用Binding仍然无法实现...

顶级:我在VB 2012中创建了一系列类,对它们进行了注释,并使用Code First在EF6中创建了EF模型。这个想法是代表路由器配置,配置的子部分是主要部分的子部分。很简单的想法。

基本原理:使用简单的WPF树视图,说明路由器中(逻辑上)出现的配置部分和子部分。

我已经非常简单地开始使用这些类,后来打算使用双向绑定来更新每种方式,等等。这里是前2个顶级类(为了简洁起见):

enter image description here

这是标准的EF CodeFirst票价,DBContext由EF按照您的预期布局。这是前2级课程(Access_Group& Access_List)的布局:

enter image description here

......所有在EF-Land都很好......

因为它可能很重要,所以这是实际的Access_Group类:

Public Class Access_Group
    Inherits EntityTypeConfiguration(Of Access_Group)
    Implements IAccess_Group

    <Key>
    Public Property Access_GroupID As Integer Implements IAccess_Group.Access_GroupID
    Public Property Name As String Implements IAccess_Group.Name
    Public Property LastUpdated As Date Implements IAccess_Group.LastUpdated
    Public Property Active As Boolean Implements IAccess_Group.Active
    '------------------------------------------------------------------
    Public Property Access_Lists As ObservableCollection(Of Access_List) Implements IAccess_Group.Access_Lists
    Public Sub New()
        Me.Access_Lists = New ObservableCollection(Of Access_List)
    End Sub
End Class

我还没有添加许多基于事件的组件,因为我只想在添加铃声之前完成基本工作(在树视图中分层显示)。口哨...

所以这就是在代码中创建类的方式,它首先填充了数据库(SQL 2012):

[Window Class contd.]     
Private Sub AddData()
    Try
        ctx = New entitiesContext
        Dim d As Date = Now
        '--------------------------------
        Dim al As New Access_List
        ' lower classes not needed to be shown...
        With al
            .Active = True
            .Checked = True
            .LastUpdated = d
            .Name = "some access-list at " & d.ToLongTimeString
        End With
        '--------------------------------
        Dim ag As Access_Group = New Access_Group
        With ag
            .Access_Lists.Add(al)
            .Active = True
            .LastUpdated = d
            .Name = "some access-group at " & d.ToLongTimeString
        End With
        '
        ctx.Access_Groups.Add(ag)
        '
        Dim i As Integer = ctx.SaveChanges()
        Console.WriteLine("Seed complete! -> " & i)
    Catch ex As Exception
        Dim exText As String = "Seed Failed "
        Console.WriteLine(exText & "(Message): " & ex.Message)
        Console.WriteLine(exText & "(ToString): " & ex.ToString)
        Console.WriteLine(exText & "(StackTrace): " & ex.StackTrace)
        Console.WriteLine("EntityValidationErrors: ")
        For Each eve As System.Data.Entity.Validation.DbEntityValidationResult In ctx.GetValidationErrors()
            Console.WriteLine("eve: OK? " & eve.IsValid & " - " & eve.Entry.ToString)
            For Each devr As System.Data.Entity.Validation.DbValidationError In eve.ValidationErrors
                Console.WriteLine("devr invalid property: " & devr.PropertyName)
                Console.WriteLine("devr error message : " & devr.ErrorMessage)
            Next
        Next
    End Try
End Sub

你看到Access_List在上面被称为第二级,这就是那个类:

Public Class Access_List
    Inherits EntityTypeConfiguration(Of Access_Group)
    Implements toag.entities.IAccess_List

    <Key>
    Public Property Access_ListID As Integer Implements IAccess_List.Access_ListID
    Public Property Name As String Implements IAccess_List.Name
    Public Property LastUpdated As Date Implements IAccess_List.LastUpdated
    Public Property Active As Boolean Implements IAccess_List.Active
    Public Property Checked As Boolean Implements IAccess_List.Checked
    Public Property Object_Groups As ObservableCollection(Of Object_Group) Implements IAccess_List.Object_Groups
    Public Sub New()
        Me.Object_Groups = New ObservableCollection(Of Object_Group)
    End Sub
End Class

如果我能弄清楚如何使这两个类表现出来,我可以模板和&amp;其余的也要这样做......

我已尝试过几百万代码&amp; XAML组合,所以我会安排一个至少在Treeview上显示某些东西的那个:

<TreeView Grid.Column="0" 
    x:Name="ACLTreeView" 
    HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" 
    ItemsSource="{Binding Access_Group}">
</TreeView>

当此XAML与此代码隐藏相结合时:

Public Class ConfigWindow

    Property ctx As entitiesContext
    Public Access_Group_List As IEnumerable(Of Access_Group)

    Sub New()
        ' This call is required by the designer.
        InitializeComponent()
       Startup()
    End Sub

    Public Sub Startup()
        Try
            ctx = New vASAContext
            Me.Access_Group_List = From ag In ctx.Access_Groups Select ag
            Me.ACLTreeView.ItemsSource = Access_Group_List.ToList
        Catch ex As Exception
            Debug.Print("ex: " & ex.Message)
        End Try
    End Sub

End Class

将产生以下结果:

enter image description here

抱歉不得不混淆命名空间...... )这很好,因为XAML中没有HierarchicalTemplate甚至TreeViewItem。

这是修改过的XAML:

                                       

...将显示Access_Group实体的Name属性而不是它的类名[在编辑帖子时无法添加它的屏幕截图,所以你可能要相信我这个! :)]

但是Window类中还有另一个子指向可能无法识别的层次结构的问题。可能是我一直在尝试正确的例子,而且我的EF课程没有正确设置?该子应显示所有元素及其子元素:

Public Sub PrintDebug(TheList As IEnumerable(Of Access_Group))
    For Each ag As Access_Group In TheList
        Console.WriteLine("=======================================")
        Console.WriteLine("ag: " & ag.Name & " has " & ag.Access_Lists.Count & " Access_List entries")
        For Each al As Access_List In ag.Access_Lists
            Console.WriteLine("ag -> al: " & al.Name & " has " & al.Object_Groups.Count & " Object_Group entries")
            For Each og As Object_Group In al.Object_Groups
                Console.WriteLine("ag -> al -> og: " & og.Name & " has " & og.Network_Objects.Count & " Network_Object entries")
                '...
            Next
        Next
        Console.WriteLine("=======================================")
    Next
End Sub

但这是调试类推出的内容:

=======================================
ag: some access-group at 5:00:49 PM has 0 Access_List entries
=======================================
=======================================
ag: some access-group at 5:08:56 PM has 0 Access_List entries
=======================================
=======================================
ag: some access-group at 5:09:14 PM has 0 Access_List entries
=======================================
=======================================
ag: some access-group at 5:12:31 PM has 0 Access_List entries
=======================================
[...]

?这是否意味着我的Treeview没有机会?但是,但......数据在DB中是正确的:

enter image description here

当我使用上面的代码时,所有这些键都由EF填充(仅在填充ObservableCollections后保存顶级类(Access_Group)...)

???

我已尝试过HierarchicalTemplate的每个组合,在网格/窗口资源中,嵌套等等。而且我在3天后回到了1 ... ...是的,各种LINQ查询也是......现在我正在考虑在LINQ / SQL中使用SQL( GASP )或JOIN,但是我也可以一直回到DataSets&amp; DataTables如果我准备好真的放弃......

任何帮助表示赞赏......我无法继续前进,直到我能让这些实体正确绑定...

1 个答案:

答案 0 :(得分:2)

我已经创建了实体的示例对象模型(AccessGroup,AccessList和ObjectGroup),这段代码可能对您有所帮助:

<强>代码隐藏

Imports System.Collections.ObjectModel

Class MainWindow

    Property AccessGroups As New ObservableCollection(Of AccessGroup)

    Public Sub New()

        ' This call is required by the designer.
        InitializeComponent()

       ' Add any initialization after the InitializeComponent() call.
        Me.DataContext = Me

        Dim ag1 = New AccessGroup With {.Name = "AG1"}
        Dim ag2 = New AccessGroup With {.Name = "AG2"}

        Dim al1 = New AccessList With {.Name = "AL1"}
        Dim al2 = New AccessList With {.Name = "AL2"}
        Dim al3 = New AccessList With {.Name = "AL3"}

        Dim og1 = New ObjectGroup With {.Name = "OG1"}
        Dim og2 = New ObjectGroup With {.Name = "OG2"}

        al1.ObjectGroups = New List(Of ObjectGroup) From {og1}
        al2.ObjectGroups = New List(Of ObjectGroup) From {og2}

        ag1.AccessList = New List(Of AccessList) From {al1, al2}
        ag2.AccessList = New List(Of AccessList) From {al3}

        AccessGroups.Add(ag1)
        AccessGroups.Add(ag2)
    End Sub
End Class

Public Class AccessGroup
    Property Name As String
    Property AccessList As IEnumerable(Of AccessList)
End Class

Public Class AccessList
    Property Name As String
    Property ObjectGroups As IEnumerable(Of ObjectGroup)
End Class

Public Class ObjectGroup
    Property Name As String
End Class

<强> XAML

<TreeView ItemsSource="{Binding AccessGroups}">
    <!-- AccessGroup template -->
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource="{Binding AccessList}">
            <TextBlock Text="{Binding Name}" />

            <!-- AccessList template -->
            <HierarchicalDataTemplate.ItemTemplate>
                <HierarchicalDataTemplate ItemsSource="{Binding ObjectGroups}">
                    <TextBlock Text="{Binding Name}" />

                    <!-- ObjectGroup template -->
                    <HierarchicalDataTemplate.ItemTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding Name}" />
                        </DataTemplate>
                    </HierarchicalDataTemplate.ItemTemplate>

                </HierarchicalDataTemplate>
            </HierarchicalDataTemplate.ItemTemplate>

        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>

在下面的图片中,您可以看到结果

enter image description here