更新绑定子对象的ComboBox ItemSource

时间:2016-12-23 11:33:45

标签: wpf vb.net entity-framework-6

我有一个包含2个表的数据库; tblContacttblPersontblContacttblPerson之间存在一对多的关系 - 单个联系人可以拥有多个人。我使用VB 2013和Entity Framework来创建数据绑定。

我遇到的问题是绑定的ComboBox(cboPerson),在添加/删除/更改人员时不会更新,除非我移动到其他联系人然后返回。是否有方法刷新ComboBox ItemSource。

我可以看到我所做的更改会反映在基础对象和数据库中。

这是XAML。

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:TestBinding" mc:Ignorable="d" x:Class="MainWindow"
    Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <CollectionViewSource x:Key="ContactView" d:DesignSource="{d:DesignInstance {x:Type local:tblContact}, CreateList=True}"/>
        <CollectionViewSource x:Key="PersonView" Source="{Binding tblPersons, Source={StaticResource ContactView}}" />
    </Window.Resources>

    <Grid DataContext="{Binding Source={StaticResource ContactView}}">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <Label Grid.Row="0" Margin="3" Grid.Column="0" Content="Contact ID:"/>
        <TextBox Grid.Row="0" Margin="3" Grid.Column="1" Padding="3" x:Name="txtContactID" VerticalAlignment="Center" Text="{Binding Contact_ID, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}" />

        <Label Grid.Row="1" Grid.Column="0" Margin="3" Content="Person ID:" />
        <ComboBox Grid.Row="1" Grid.Column="1" Margin="3" Padding="3" x:Name="cboPerson" SelectedValue="{Binding Contact_Primary_Person}" ItemsSource="{Binding Source={StaticResource ContactView}, Path=tblPersons, Mode=TwoWay}" SelectedValuePath="Person_ID" DisplayMemberPath="Person_Salutation" />

        <StackPanel Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" Orientation="Horizontal" >
            <Button Margin="3" Padding="3" Name="btnAdd">Add</Button>
            <Button Margin="3" Padding="3" Name="btnPrev">Prev</Button>
            <Button Margin="3" Padding="3" Name="btnNext">Next</Button>
            <Button Margin="3" Padding="3" Name="btnDelete">Delete</Button>

        </StackPanel>
    </Grid>
</Window>

表格背后的代码。

    Imports System.Data.Entity
    Class MainWindow
        Dim _context As ct_dbContext
        Dim ContactView As System.Windows.Data.CollectionViewSource
        Private Sub Window_Loaded(sender As Object, e As RoutedEventArgs) Handles MyBase.Loaded

        _context = New ct_dbContext

        ContactView = CType(Me.FindResource("ContactView"), System.Windows.Data.CollectionViewSource)
        'Load data by setting the CollectionViewSource.Source property:
        'TblContactViewSource.Source = [generic data source]

        _context.tblContacts.Load()

        ContactView.Source = _context.tblContacts.Local

    End Sub

    Private Sub btnAdd_Click(sender As Object, e As RoutedEventArgs) Handles btnAdd.Click

        Dim newPerson As New tblPerson With {.Person_Created = Now, .Person_Email = "test@cambertown.com", .Person_Forename = "Joe", .Person_Mobile = "07", _
                                             .Person_Phone = "01", .Person_Salutation = "Mr Smith", .Person_Surname = "Smith", .Person_Title = "Mr", .Person_Updated = Now}

        Dim currentContact As tblContact = ContactView.View.CurrentItem

        currentContact.tblPersons.Add(newPerson)

        _context.SaveChanges()

    End Sub

    Private Sub btnNext_Click(sender As Object, e As RoutedEventArgs) Handles btnNext.Click

        ContactView.View.MoveCurrentToNext()

    End Sub

    Private Sub btnPrev_Click(sender As Object, e As RoutedEventArgs) Handles btnPrev.Click
        ContactView.View.MoveCurrentToPrevious()
    End Sub

    Private Sub btnDelete_Click(sender As Object, e As RoutedEventArgs) Handles btnDelete.Click

    End Sub

End Class

非常感谢任何建议或指示。

3 个答案:

答案 0 :(得分:0)

  

是否有方法刷新ComboBox ItemSource。

您可以通过在其View:

上调用Refresh方法来刷新CollectionViewSource
ContactView.View.Refresh()

另一个选项是将CollectionViewSource的Source设置为ObservableCollection(Of TblPerson)并记住在将新tblPerson对象添加到数据库之前将其添加到此集合中。

答案 1 :(得分:0)

如果您绑定到某个集合(例如您的组合框项目),则在您更改此集合中的单个项目时,此集合将不会更新。这是因为您绑定的集合对象仍然相同(即使集合中的项目可能已更改)。您的控件未被告知更改,因为永远不会引发属性更改通知。当您更改为其他联系人时,您实际上会更改整个对象,这会触发属性更改事件。这是一个相当普遍的&#34;陷阱&#34;当你开始使用绑定集合时。

如果您希望集合在其中的值发生更改时通知您,则最常见的解决方案是使用ObservableCollection。这有内置属性更改通知。

如果对象是EF对象并且是为您创建的,那么您可以考虑安装NuGet包&#34; propertychanged.fody&#34;。这使您能够通过简单地设置[ImplementPropertyChanged]属性将属性更改通知添加到任何类。

EF类是部分类,因此这允许您创建第二个文件,然后可以使用该文件将属性更改通知添加到。

结果(添加fody之后)将创建一个看起来像这样的文件(你需要添加名称空间等......);

[ImplementPropertyChanged]
public partial class tblContact
{
}

这就是你所要做的一切。 tblContact的所有属性现在都将具有属性更改通知。您可能需要为您的人员类型执行相同操作。

使用partial类是扩展设计器为您生成的EF类的行为的好方法。如果您不熟悉部分类,则可以将类定义拆分为两个或更多文件,因此虽然您不会编辑设计人员为您构建的部件,但您可以在文件中执行您喜欢的操作。 。部分类的名称显然需要相同,以便编译器知道它们实际上是同一个类。

答案 2 :(得分:0)

我找到了这个页面Entity Framework Databinding with WPF,我按照更新代码生成数据绑定标题下的说明进行操作。

我还必须添加

Imports System.Collections.ObjectModel

生成的类tblContact.vb。

当我添加,删除和更新tblPerson时,组合框现在会自动更新。