2014-08-30 154 views
2

在Prism,MVVM,Windows 8.1 StoreApp中,我希望ViewModel捕获ListView中的SelectItem。 ListView包含一个ObservableCollection对象。 ViewModel需要查找选定对象的更多细节并通知视图。该视图反过来应该显示对象的细节。Prism MVVM模式:视图始终落后于ViewModel中属性更改的一步

我已经实现了这一点,但视图显示百达前者的对象

当然,我正在寻找的是在视图立即和正确反应的选择(选择一个新的后)目的。这里是我的codenippets,全部用VB代码。

编辑:我已经提出了另一个 - 更小的例子,使用这种方法。我做了一个过程的记录in this video.请再阅读之前看看它!

的对象来自视图模型为:

公共财产的人作为新的ObservableCollection(人)

他们被绑定到用户控件:

<Grid> 
    <ListView 
       ItemsSource="{Binding Persons}" 
       ItemTemplate="{StaticResource BusinessCard}"> 
     <Interactivity:Interaction.Behaviors> 
      <Core:EventTriggerBehavior EventName="SelectionChanged"> 
       <Behaviors:ListViewSelectionChangedAction/> 
      </Core:EventTriggerBehavior> 
     </Interactivity:Interaction.Behaviors> 
    </ListView> 
</Grid> 

通过行为最终会通过此代码在ViewModel中结束:

Sub New(InjectedEventAggregator As IEventAggregator) 

     LocalEventAggregator = InjectedEventAggregator 
     LocalEventAggregator.GetEvent(Of PersonIsSelectedEvent)().Subscribe(AddressOf HandlePersonIsSelected, True) 

此事件是由这个程序

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 

编辑:,这是应显示所选ActualPerson的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)对象更新immediatelty?

如果您有线索....成为我的嘉宾!

Regards

+0

您尚未显示'视图反过来应显示对象的详细信息'的代码。如果XAML代码绑定到ActualPerson对象,它应该显示ActualPerson的详细信息。你可以尝试将TextBlock的Text属性绑定到ActualPerson。并检查你看到的是什么。 – 2014-08-31 15:35:57

+0

@Wonderfulworld感谢您的反馈。我在原文中进行了编辑。从列表视图中选择的对象是一个人。基于此,ActualPerson属性被刷新。问题不是绑定本身,而是时机:只有前一个对象才完整显示。绑定到其他属性的作品,但反应相同滞后:总是在前一次点击中选择的对象。 – user2366741 2014-08-31 20:49:50

+0

你的代码对我来说是正确的。只要调用“ActualPerson = SelectedPerson”,UI就会更新。除非ActualPerson是之前的对象,否则您应该看到最近点击过的人。在ActualPerson的Set操作中放置一个断点并查看它是否被调用两次,并且是任何将最新对象设置回前一个对象的人。 – 2014-09-01 07:47:51

回答

0

让我试着理解你在“对视图没有反应”中所说的话。即使'ActualPerson = SelectedPerson'被调用,你是说UI没有改变吗?

控件具有一个名为MODE的绑定属性,它决定数据流。显示个人信息的TextBlock的MODE可以是单向。有可能绑定是OneTime这是造成这个问题。

+0

您了解它正确!视图没有任何反应。并且YES ActualPerson = SelectedPerson被调用,YES也调用ActualPerson属性中的Set-SetProperty。这就是为什么我把头发拉出来并将它撞到墙上。我无法弄清楚什么是错的。据我所知,OneWay绑定是默认的。我已改为OneWay。行为没有差异。 – 2014-09-01 14:54:54

+0

@wonderfulworld为了更轻松地看到发生了什么,我构造了另一个小例子。查看原始发布中的第一个修改。你也可以看看[这里](https://prismwindowsruntime.codeplex。com/discussion/564825)查看关于此的完整讨论。 – user2366741 2014-09-03 07:11:05

+0

您是否尝试过调用SetProperty(_Messages,value,“Messages”)?最后一个参数是属性而不是字段。 – 2014-09-03 08:08:08

0

您能否确认您的存储库中有哪些内容?我假设它不是一个可观察的集合。至少它不应该是,我认为这将是一个可序列化的POCO对象。这意味着您需要将这些项目添加到可观察集合中。如果不使用CollectionView,我这样做的方式是使用ObservableCollection类型的readonly变量,该变量永远不会更改。然后,当您向消息发出请求时,我会确保收集已清除,为新的新项目做好准备。一旦消息被返回,循环通过响应中的每个模型项目(消息),并将它们转换为MessageViewModels(一个包含可绑定属性和验证(数据注释)的新类,因为每个ViewModel项目都被创建,所以它被添加到的ObservableCollection。将项目添加到集合将引发一个事件列表视图被监听,因此将显示该项目(只要MessageViewModel有一个相关的数据模板的行为。

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

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

OnNavigateTo

Messages.Clear; 
foreach(var message in await _messageRepository,GetMessagesAsync()) 
{ 
    Messages.Add(new MessageViewModel(){Name = message.Name, Text = message.Text}); 
} 

这有道理吗?

+0

您可以确定存储库的内容是可观察的集合。将原始json数据转换为ViewModel层中可用的内容完全在存储库中完成。我从你在这里提出的建议中得到了很多帮助,并提出了最终的工作解决方案。谢谢! – 2014-09-03 15:48:36

0

一个不好的解决方案,但也许是有帮助的。你可以再次调用OnProperyChanged。我说“再次”,因为它被认为是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 

编辑15年4月2日:很好的解决方案是在这里:OnPropertyChanged not fired when SetProperty is called

就这么简单的私人声明去掉“财产”一词。这是因为它通过了ByRef,所以它不能成为一个属性。

相关问题