I am still learning how to use INotifyPropertyChanged. I was able to see it work with a non-persisted list in this post. I am now trying to use an SQL persisted list.
XAML. Some of the unused grid space was for comparisons to the non-persisted list, but not relevant to this post's question.
<StackPanel Grid.Column="0">
<Button Margin="25" Content="Insert an item" Click="InsertAnItem_Click"/>
</StackPanel>
<StackPanel Grid.Column="1">
<Button Margin="25" Content="Clear stored list" Click="ClearStoredList_Click"/>
<Label Content="{}{Binding MyList2}"/>
<ListBox Name="listBox3" ItemsSource="{Binding MyList2}" DisplayMemberPath="Name" Height="100">
</ListBox>
<Label Content="updated with MyList2 using code behind"/>
<ListBox Name="listBox4" DisplayMemberPath="Name" Height="100">
</ListBox>
</StackPanel>
CodeBehind
Partial Class MainWindow
Private vm = New ViewModel
Sub New()
InitializeComponent()
DataContext = vm
For Each item In vm.MyList2
listBox4.Items.Add(item)
Next
End Sub
Private Sub InsertAnItem_Click(sender As Object, e As RoutedEventArgs)
vm.InsertAnItem()
listBox4.Items.Clear()
For Each item In vm.MyList2
listBox4.Items.Add(item)
Next
End Sub
Private Sub ClearStoredList_Click(sender As Object, e As RoutedEventArgs)
vm.ClearStoredList()
End Sub
End Class
ViewModel
Public Class ViewModel
Implements INotifyPropertyChanged
Public Property dbList As New Mvvm2DbContext
Public Property MyList2 As New List(Of MyListItem)
Public Sub New()
MyList2 = dbList.SqlStoredList.ToList()
End Sub
Public Sub InsertAnItem()
Dim anItem As New MyListItem
anItem.Name = "Item " & MyList2.Count()
MyList2.Add(anItem)
dbList.SqlStoredList.Add(anItem)
dbList.SaveChanges()
NotifyPropertyChanged("MyList2")
End Sub
Public Sub ClearStoredList()
Using db = New Mvvm2DbContext
Dim allItems = db.SqlStoredList
Try
db.SqlStoredList.RemoveRange(allItems)
Catch ex As Exception
Dim s = ex.Message
MessageBox.Show(s)
End Try
db.SaveChanges()
End Using
End Sub
Public Event PropertyChanged As PropertyChangedEventHandler _
Implements INotifyPropertyChanged.PropertyChanged
Public Sub NotifyPropertyChanged(ByVal propertyName As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
End Sub
End Class
Model
Public Class MyListItem
Public Property MyListItemID() As Integer
Get
Return _MyListItemID
End Get
Set(ByVal value As Integer)
_MyListItemID = value
End Set
End Property
Private _MyListItemID As Integer
Public Property Name() As String
Get
Return _Name
End Get
Set(ByVal value As String)
_Name = value
End Set
End Property
Private _Name As String
Public Property Desc() As String
Get
Return _Desc
End Get
Set(ByVal value As String)
_Desc = value
End Set
End Property
Private _Desc As String
End Class
dbContext
Public Class Mvvm2DbContext
Inherits DbContext
Public Sub New()
MyBase.New("name=MVVM2DbConnection")
End Sub
Public Property SqlStoredList As DbSet(Of MyListItem)
End Class
My line NotifyPropertyChanged("MyList2")
in the ViewModel doesn't cause the bound list to update.
I think the MyList2 definition in the ViewModel must be incorrect, but I don't understand how to make it different if that's the problem.
What is the proper code to get changes to percolate to the display? As always, if there are best practices I'm missing, please advise.
Updated after initial post but questions still remain:
The following changes appear to cause INotifyPropertyChanged to now work in this code. I'm guessing INotifyPropertyChanged doesn't work unless a property is defined with specific get/set declarations.
ViewModel. The MyList2 definition is changed and New() is changed.
Public Property MyList2() As ObservableCollection(Of MyListItem)
Get
Return _MyList2
End Get
Set(ByVal value As ObservableCollection(Of MyListItem))
_MyList2 = value
End Set
End Property
Private _MyList2 As New ObservableCollection(Of MyListItem)
Public Sub New()
For Each item In dbList.SqlStoredList
MyList2.Add(item)
Next
End Sub
The reason I previously defined MyList2 as:
Public Property MyList2 As New List(Of MyListItem)
Was because in New() initializing MyList2 with this line wouldn't compile:
MyList2 = dbList.SqlStoredList.ToList()
Even if I tried a DirectCast, List(Of T) can't be converted to an ObservableCollection(Of T). I'm guessing that's because of all the 'plumbing' behind the scenes?
Anyway, INotifyPropertyChanged seems to work fine now. But, I would appreciate any instruction regarding mistakes I'm making implementing this simple persisted list with INotifyPropertyChanged.
However, the persisted list is not fully bound. MyList2 doesn't clear when the SQL database is cleared. It seems to me that there must be more to this because changes to the SQL database could be made by other processes, and I don't see how this code would know that.
What do I do to ensure all updates get reflected in the UI?