2016-12-23 5 views
0

У меня есть база данных с 2 таблицами; tblContact и tblPerson. Существует соотношение 1-ко-многим между tblContact и tblPerson - у одного контакта может быть много людей. Я использую VB 2013 и Entity Framework для создания привязки данных.Обновление ComboBox ItemSource для связанных дочерних объектов

Проблема, с которой я столкнулся, связана с 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 = "[email protected]", .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

Это поможет, если вы разместите меньше кода. Только код, относящийся к проблеме, заставил бы это намного проще ответить, чем тралить через целые классы. – David

ответ

0

Есть ли способ обновления ComboBox ItemSource.

Вы можете обновить CollectionViewSource, вызвав метод Refresh на его Вид:

ContactView.View.Refresh() 

Другой вариант, чтобы установить источник в CollectionViewSource к ObservableCollection (Of tblPerson) и не забудьте добавить новый объект tblPerson для этой коллекции, а также перед добавлением его в базу данных.

+0

Благодарим за ответ. Я добавил это сразу после _context.SaveChanges(), но не обновил содержимое комбобокса. Я собираюсь исследовать изменение в ObservableCollection. –

+0

Локальная копия коллекций tblContacts не изменяется при добавлении нового элемента в базу данных. Вам нужно снова извлечь записи, чтобы обновить CollectionViewSource: ContactView.Source = _context.tblContacts.ToList(); Вот почему вы должны использовать ObservableCollection в качестве источника и не забудьте добавлять к нему новые элементы, а также при обновлении базы данных. – mm8

0

Если вы привязываетесь к коллекции (например, к элементам списков со списком), эта коллекция не будет обновляться, если вы измените отдельный элемент в этой коллекции. Это связано с тем, что объект коллекции, к которому вы привязаны, все тот же (хотя элементы в коллекции могут быть изменены). Ваш контроль не сообщается об изменениях, поскольку уведомление об изменении свойств никогда не возникает. Когда вы переходите на другой Контакт, вы фактически меняете весь объект, и это вызывает событие изменения свойства. Это довольно распространенная «gotcha», когда вы начинаете использовать привязку для коллекций.

Если вы хотите, чтобы сборник уведомлял вас, когда значение внутри него изменяется, наиболее распространенным решением является использование ObservableCollection. У этого встроенного свойства изменилось уведомление.

Если объекты являются объектами EF, и они были созданы для вас, вы можете рассмотреть возможность установки пакета NuGet «propertychanged.fody». Это дает вам возможность добавлять уведомление об изменении свойства в любой класс, просто устанавливая атрибут [ImplementPropertyChanged].

Классы EF являются частичными классами, поэтому это позволяет создать второй файл, который затем можно использовать для добавления уведомления об изменении свойства.

В результате (после добавления файла) будет создан файл, который выглядит примерно так (вам нужно добавить пространства имен и т. Д.);

[ImplementPropertyChanged] 
public partial class tblContact 
{ 
} 

Это буквально все, что вам нужно. Все свойства tblContact теперь будут иметь уведомление об изменении свойства. Возможно, вам придется сделать то же самое для своего типа.

Использование частичных классов - хороший способ расширить поведение классов EF, которые были созданы для вас дизайнером. Если вы новичок в частичных классах, это способ разбить определение класса на два или более файлов, поэтому, хотя вы не будете редактировать часть, созданную для вас дизайнером, вы можете делать то, что вам нравится в файле. Названия частичных классов, очевидно, должны быть одинаковыми, чтобы компилятор знал, что они на самом деле являются одним и тем же классом.

+0

Благодарим вас за ответ. Я думал об этом, но поскольку Entity Framework создал для меня объекты, я не знаю, что мне нужно изменить, чтобы сделать коллекцию ObervableCollection. У меня есть несколько дней, поэтому я посмотрю на объекты, созданные EF. –

+0

Спасибо за обновление, я собираюсь изучить это сегодня. –

0

Я нашел эту страницу Entity Framework Databinding with WPF и выполнил инструкции в рубрике Обновление кода для привязки данных.

Я также должен был добавить

Imports System.Collections.ObjectModel 

сгенерированного класс tblContact.vb.

Теперь, когда я добавляю, удаляю и обновляю tblPerson, сводка теперь обновляется автоматически.

Смежные вопросы