Должны ли свойства ViewModels, которые реализуют INotifyPropertyChanged, автоматически обновлять данные в элементе управления DataGrid при их обновлении? - PullRequest
1 голос
/ 23 июля 2010

Я не могу понять цель, стоящую за INotifyPropertyChanged и Silverlight ...

У меня есть XAML, созданный в конструкторе:

<UserControl.Resources>
    <CollectionViewSource x:Key="theViewSource" d:DesignSource="{d:DesignInstance my:transferObject, CreateList=True}" />
</UserControl.Resources>

, а также

            <Canvas DataContext="{StaticResource theViewSource}">
                <sdk:DataGrid ItemsSource="{Binding}" Name="theDataGrid">
                    <sdk:DataGrid.Columns>
                     <!-- columns omitted from post -->
                    </sdk:DataGrid.Columns>
                </sdk:DataGrid>
            </Canvas>

И у меня также есть некоторый код:

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

И ViewModel, который выглядит примерно так:

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

В результате Silverlight отображает сетку данных без результатовпотому что TheObservableCollection еще не был заполнен обработчиком событий.Этого следовало ожидать.Я надеялся, что после асинхронного вызова веб-службы будет вызван метод Setter для TheObservableCollection, а затем и RaisePropertyChanged.

Я ожидал, что Silverlight справится с этим, связав dataGrid со свойством ... Не является ли целью использование INotifyPropertyChanged, чтобы сделать так, чтобы мне не приходилось перепривязывать сетку программно илиЯ смущен по этому поводу?

1 Ответ

1 голос
/ 23 июля 2010

В Silverlight (в отличие от WPF) вы не назначаете ObservableCollection в своем обработчике ответа службы. Это сломает привязку.

Вместо этого очистите уже привязанную коллекцию и заново заполните ее элементами из вашего сервисного ответа. Обновление коллекции будет правильно вызывать события уведомлений. Если вы повторно назначите ссылку на коллекцию, привязка к элементу пользовательского интерфейса будет нарушена.

Целью INotifyPropertyChanged является информирование любых связанных членов об изменении значения свойства. В случае коллекций повторное назначение ссылки не считается изменением значения. Обновление количества членов коллекции делает. Аналогичным образом, изменение отдельных свойств будет вызывать события уведомления, пока вы вызываете событие PropertyChanged. Цель интерфейса - предоставить контракт для View для прослушивания ViewModel.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...