我有一个包含2个表的数据库; tblContact
和tblPerson
。 tblContact
和tblPerson
之间存在一对多的关系 - 单个联系人可以拥有多个人。我使用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
非常感谢任何建议或指示。
答案 0 :(得分:0)
是否有方法刷新ComboBox ItemSource。
您可以通过在其View:
上调用Refresh方法来刷新CollectionViewSourceContactView.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时,组合框现在会自动更新。