Vb.net Prism MVVM模式:视图在ViewModel中的属性更改上总是落后一步
在Prism、MVVM、Windows 8.1 StoreApp中,我希望ViewModel在ListView中捕获SelectItem。ListView包含对象的ObservableCollection。ViewModel需要查找选定对象的更多详细信息并通知视图。视图应依次显示对象的详细信息 我已经实现了这一点,但视图始终显示前一个对象(在选择新对象后) 当然,我要寻找的是在选择一个对象时,在视图中立即做出正确的反应。下面是我的代码片段,全部用VB代码编写 编辑:我用这种方法给出了另一个较小的示例。我录制了一段过程请在进一步阅读之前先看一看强> 对象来自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代码编写 编辑:我用这种方法给出了另一个较小的
<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