本文介绍了如何让 INotifyPropertyChanged 从存储在 SQL 中的列表中更新绑定项目?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我仍在学习如何使用 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 中的列表中更新绑定项目?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

11-03 13:03