问题描述
我仍在学习如何使用 INotifyPropertyChanged.我能够在这个 帖子中看到它与非持久列表一起工作.我现在正在尝试使用 SQL 持久化列表.
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.一些未使用的网格空间用于与非持久列表进行比较,但与本文的问题无关.
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>
代码隐藏
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
视图模型
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
型号
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
ViewModel 中的我的行 NotifyPropertyChanged("MyList2")
不会导致绑定列表更新.
My line NotifyPropertyChanged("MyList2")
in the ViewModel doesn't cause the bound list to update.
我认为 ViewModel 中的 MyList2 定义肯定是不正确的,但如果这是问题,我不明白如何使其有所不同.
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.
在初次发布后更新,但问题仍然存在:
以下更改似乎导致 INotifyPropertyChanged 现在可以在此代码中使用.我猜 INotifyPropertyChanged 不起作用,除非使用特定的 get/set 声明定义属性.
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.
视图模型.MyList2 定义已更改,New() 已更改.
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
我之前将 MyList2 定义为的原因:
The reason I previously defined MyList2 as:
Public Property MyList2 As New List(Of MyListItem)
是因为在 New() 中用这一行初始化 MyList2 不会编译:
Was because in New() initializing MyList2 with this line wouldn't compile:
MyList2 = dbList.SqlStoredList.ToList()
即使我尝试了 DirectCast,List(Of T) 也无法转换为 ObservableCollection(Of T).我猜这是因为幕后的所有管道"?
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?
无论如何,INotifyPropertyChanged 现在似乎工作正常.但是,对于我在使用 INotifyPropertyChanged 实现这个简单的持久化列表时所犯的错误,我很感激.
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.
然而,持久化列表并没有完全绑定.当 SQL 数据库被清除时,MyList2 不会清除.在我看来,这必须有更多内容,因为其他进程可以对 SQL 数据库进行更改,而我不知道这段代码是如何知道这一点的.
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.
我该怎么做才能确保所有更新都反映在 UI 中?
What do I do to ensure all updates get reflected in the UI?
推荐答案
您的代码的问题是属性 MyList2 没有改变...它的内容正在改变.所以这就是为什么 MyList2 上的属性通知什么都不做...MyList2 仍然是 MyList2.
The problem with your code is that the property MyList2 is not changing...its contents are changing. So that is why the property notification on MyList2 does nothing...MyList2 is still MyList2.
你需要的是一个实现通知的集合类.ObservableCollection 将满足这种需求.因此,如果您简单地将 List(Of MyListItem) 替换为 ObservableCollection(Of MyListItem),我认为事情会开始起作用.
What you need is a collection class that implements notification. ObservableCollection would fit this need. So if you simply replace List(Of MyListItem) with ObservableCollection(Of MyListItem) I think things will start working.
这篇关于如何让 INotifyPropertyChanged 从存储在 SQL 中的列表中更新绑定项目?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!