Should properties of ViewModels that implement INotifyPropertyChanged automatically update the data in DataGrid control when I update them?
I may be confused about the purpose behind INotifyPropertyChanged and Silverlight...
I have XAML that I created in the designer:
<UserControl.Resources>
<CollectionViewSource x:Key="theViewSource" d:DesignSource="{d:DesignInstance my:transferObject, CreateList=True}" />
</UserControl.Resources>
as well as this
<Canvas DataContext="{StaticResource theViewSource}">
<sdk:DataGrid ItemsSource="{Binding}" Name="theDataGrid">
<sdk:DataGrid.Columns>
<!-- columns omitted from post -->
</sdk:DataGrid.Columns>
</sdk:DataGrid>
</Canvas>
And I also have some codebehind:
Private Sub control_Loaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded
If Not (System.ComponentModel.DesignerProperties.GetIsInDesignMode(Me)) Then
Dim myCollectionViewSource As System.Windows.Data.CollectionViewSource =
CType(Me.Resources("theViewSource"), System.Windows.Data.CollectionViewSource)
Dim myViewModel As New ViewModels.ViewModelThatHasAnObservableCollectionProperty()
myCollectionViewSource.Source = myViewModel.TheObservableCollection()
End If
End Sub
And a ViewModel that looks somewhat like this:
Public Class ViewModelBase
Implements ComponentModel.INotifyPropertyChanged
Protected Sub RaisePropertyChanged(ByVal propertyName As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
End Sub
Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
End Class
Public Class ViewModelThatHasAnObservableCollectionProperty
Inherits ViewModelBase
Public Sub RetrieveCollectionCompletedHandler(ByVal sender As Object, ByVal e As SilverlightConsumableService.RetrieveMyCollectionCompletedEventArgs)
Dim unobservable As List(Of TransferObjects.TheTransferObject) = e.Result
'I was hoping for this next line of code to force a refresh of the DataGrid
TheObservableCollection = New ObservableCollection(Of TransferObjects.transferObject)(unobservable)
End Sub
Public Sub New()
Dim theClient As New SilverlightConsumableService.SilverlightConsumableSoapClient
AddHandler theClient.RetrieveMyCollectionCompleted, AddressOf RetrieveCollectionCompletedHandler
theClient.RetrieveMyCollectionAsync()
End Sub
Private _theObservableCollection As ObservableCollection(Of TransferObjects.transferObject)
Public Property TheObservableCollection() As ObservableCollection(Of TransferObjects.transferObject)
Get
Return _theObservableCollection
End Get
Set(ByVal value As ObservableCollection(Of TransferObjects.transferObject))
_theObservableCollection = value
RaisePropertyChanged("TheObservableCollection")
End Set
End Property
End Class
The result is that Silverlight renders the datagrid with no results because TheObservableCollection hasn't been populated by the event handler yet. That's to be expected. What I was hoping for was that after the asychronous call to the web service, the Setter for TheObservableCo开发者_开发百科llection gets called, and subsequently so does RaisePropertyChanged.
My expectation was that Silverlight would handle this by rebinding the dataGrid to the property... Isn't the purpose behind using INotifyPropertyChanged to make it so that I don't have to rebind the grid programmatically, or am I confused about that?
In Silverlight (unlike WPF), you don't assign the ObservableCollection in your service response handler. This will break the binding.
Instead, clear out the already bound collection and re-populate it with the items from your service response. Updating the collection will properly raise the notification events. If you re-assign the collection's reference, the binding to the UI element will be broken.
The purpose behind INotifyPropertyChanged is to inform any bound members that the value of the property changed. In the case of collections, re-assigning the reference does not count as a value change. Updating the number of collection members does. Likewise, changing individual properties will raise the notify events as long as you call the PropertyChanged event. The purpose of the interface is to provide a contract for the View to listen to the ViewModel.
精彩评论