Vb.net Prism MVVM模式:视图在ViewModel中的属性更改上总是落后一步

Vb.net Prism MVVM模式:视图在ViewModel中的属性更改上总是落后一步,vb.net,mvvm,windows-store-apps,prism,inotifypropertychanged,Vb.net,Mvvm,Windows Store Apps,Prism,Inotifypropertychanged,在Prism、MVVM、Windows 8.1 StoreApp中,我希望ViewModel在ListView中捕获SelectItem。ListView包含对象的ObservableCollection。ViewModel需要查找选定对象的更多详细信息并通知视图。视图应依次显示对象的详细信息 我已经实现了这一点,但视图始终显示前一个对象(在选择新对象后) 当然,我要寻找的是在选择一个对象时,在视图中立即做出正确的反应。下面是我的代码片段,全部用VB代码编写 编辑:我用这种方法给出了另一个较小的

在Prism、MVVM、Windows 8.1 StoreApp中,我希望ViewModel在ListView中捕获SelectItem。ListView包含对象的ObservableCollection。ViewModel需要查找选定对象的更多详细信息并通知视图。视图应依次显示对象的详细信息

我已经实现了这一点,但视图始终显示前一个对象(在选择新对象后)

当然,我要寻找的是在选择一个对象时,在视图中立即做出正确的反应。下面是我的代码片段,全部用VB代码编写

编辑:我用这种方法给出了另一个较小的示例。我录制了一段过程请在进一步阅读之前先看一看

对象来自ViewModel,如下所示:

公共财产个人作为新的可观察集合(个人)

它们绑定到用户控件:

<Grid>
    <ListView 
                ItemsSource="{Binding Persons}" 
                ItemTemplate="{StaticResource BusinessCard}">
        <Interactivity:Interaction.Behaviors>
            <Core:EventTriggerBehavior EventName="SelectionChanged">
                <Behaviors:ListViewSelectionChangedAction/>
            </Core:EventTriggerBehavior>
        </Interactivity:Interaction.Behaviors>
    </ListView>
</Grid>
此事件由此例程处理

    Public Sub HandlePersonIsSelected(ByVal SelectedPerson As Person)
        ActualPerson = SelectedPerson
    End Sub
最后一部分是包含ActualPerson的属性,如下所示:

    Private Property _ActualPerson As Person
    Public Property ActualPerson As Person
        Get
            Return _ActualPerson
        End Get
        Set(value As Person)
            SetProperty(_ActualPerson, value)
        End Set
    End Property
编辑:这是应显示所选实际人员的XAML:

<StackPanel DataContext="{Binding ActualPerson}" >

       <Image Source="{Binding Photo}" Stretch="Fill" />

       <StackPanel Orientation="Horizontal">
           <TextBlock Text="{Binding FirstName}" />
           <TextBlock Text="{Binding FamilyName}" />
           <TextBlock Text="{Binding Gender}" />
       </StackPanel>

</StackPanel>

当我逐步浏览代码时,我可以看到SelectedItem事件在ViewModel中被捕获,所选人员的处理程序被调用,属性被更新。使用Prism还意味着将触发NotifyPropertyChanged事件。它确实发射了,否则前一个物体也不会显示

但是为什么视图不能立即用正确的(Person)对象更新呢

如果你有线索。。。。做我的贵宾


问候

让我试着理解你在“对观点没有反应”中所说的话。你是说即使调用了“ActualPerson=SelectedPerson”,用户界面也不会改变吗


控件有一个名为MODE的绑定属性,该属性决定数据流。显示人员信息的文本块的输入可以是单向的。可能是绑定是一次性的,这导致了问题。

您能确认您的存储库中有什么内容吗?我假设它不是一个可观察的集合。至少它不应该是,我认为它应该是一个可序列化的POCO对象。这意味着您需要将这些项添加到可观察的集合中。如果不使用CollectionView,我这样做的方式是使用一个类型为ObservableCollection的只读变量,该变量永远不会更改。然后,当您向邮件发出请求时,我会确保已清除集合,为新项目做好准备。消息返回后,循环遍历响应中的每个模型项(消息),并将其转换为MessageViewModels(一个包含可绑定属性和验证(数据注释)的新类)根据需要。创建每个ViewModel项时,都会将其添加到observablecollection中。向集合中添加项的操作将引发listview正在侦听的事件,因此将显示该项(只要MessageViewModel具有关联的数据模板)

private readonly _messages = new ObservableCollection<MessageViewModel>(); 

Public ObservableCollection<MessageViewModel> Messages {get { return _messages;}} 

这有意义吗?

一个不好的解决方案,但可能有帮助。您可以在PropertyChanged上调用“再次”。我之所以说“再次”,是因为假定SetProperty调用它,但我在VB.NET和SetProperty方面也有一些问题

Private Property _ActualPerson As Person Public Property ActualPerson As Person Get Return _ActualPerson End Get Set(value As Person) SetProperty(_ActualPerson, value) OnPropertyChanged("ActualPerson") End Set End Property 私人财产(作为个人的实际个人) 公共财产实际人 得到 返回实际用户 结束 设置(值为Person) SetProperty(_ActualPerson,value) OnPropertyChanged(“实际人员”) 端集 端属性 2015年2月4日编辑:好的解决方案是:


只需删除“属性”一词在私有声明中。这是因为它是由ref传递的,所以它不能是属性。

您没有显示“视图反过来应该显示对象的详细信息”的代码。如果XAML代码绑定到ActualPerson对象,它应该显示ActualPerson的详细信息。您可以尝试将TextBlock的文本属性绑定到ActualPe吗rson。然后检查您看到的内容。@Wonderfulworld感谢您的反应。我在原始帖子中进行了编辑。从listview中选择的对象是一个人。基于此,ActualPerson属性被刷新。问题不在于绑定本身,而在于时间:只有前一个对象被完全显示。绑定到其他适当的对象ties起作用,但反应迟滞:始终是上次单击时选择的对象。我认为您的代码正确。只要调用“ActualPerson=SelectedPerson”,UI就会更新。除非ActualPerson是前一个对象,否则您应该看到最近单击的人。在t的集合操作中放置一个断点他启动了person,查看是否调用了两次,是否有人将最新的对象设置为前一个对象。@wonderfulworld感谢您的回复。我完全同意您的说法,代码看起来不错,但这正是我的问题!!我不明白为什么它不能正常工作。我已经按照您的建议对setter进行了中断,并确保它正常工作ses一次通过那里。进一步,Prism库函数接管(通过SetProperty)我可以保证BindableBase类会引发PropertyChanged.Stil…对视图没有反应。你理解得没错!对视图没有反应。是的,调用了ActualPerson=SelectedPerson,是的,还调用了ActualPerson属性中的Set-SetProperty。这就是为什么我要拔掉头发并敲打它我不知道是什么错。据我所知,单向绑定是默认设置。我已改为单向绑定。行为没有差异。@wonderfulworld为了更容易看到发生了什么,我构建了另一个小示例。请参阅原始帖子中的第一次编辑。您可以
Messages.Clear; 
foreach(var message in await _messageRepository,GetMessagesAsync()) 
{ 
    Messages.Add(new MessageViewModel(){Name = message.Name, Text = message.Text}); 
} 
Private Property _ActualPerson As Person Public Property ActualPerson As Person Get Return _ActualPerson End Get Set(value As Person) SetProperty(_ActualPerson, value) OnPropertyChanged("ActualPerson") End Set End Property