在Prism,MVVM,Windows 8.1 StoreApp中,我希望ViewModel捕获ListView中的SelectItem。 ListView包含ObservableCollection对象。 ViewModel需要查找所选对象的更多详细信息并通知View。 View依次显示对象的细节。
我已实现此功能,但View allways显示前一个对象(选择新对象后)
当然,我所寻找的是在选择对象的视图中立即和正确的反应。这是我的代码片段,所有代码都在VB代码中。
编辑:我已经提出了另一个 - 更小的例子,使用这种方法。我记录了这个过程in this video. 请在进一步阅读之前先看一下!!
对象来自ViewModel:
Public Property Persons As New ObservableCollection(Of Person)
它们绑定到用户控件:
<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>
当我单步执行代码时,我可以看到在ViewModel中捕获了SelectedItem事件,调用了所选人员的处理程序,更新了属性。使用Prism也意味着会触发NotifyPropertyChanged事件。它确实被解雇了,否则前一个对象不会显示我猜。
但为什么View没有使用正确的(Person)对象立即更新?
如果你有线索......那是我的贵宾!
此致
答案 0 :(得分:0)
让我试着理解你所说的内容&#34;对View&#34;没有反应。你是说UI没有改变,即使&#39; ActualPerson = SelectedPerson&#39;叫做?
控件有一个名为MODE的绑定属性,用于决定数据流。显示人员信息的TextBlocks的MODE可以是 OneWay 。绑定可能是 OneTime ,这会导致问题。
答案 1 :(得分:0)
您能否确认来自您的存储库的内容?我假设它不是一个可观察的集合。至少它不应该,我认为它将是一个可序列化的POCO对象。这意味着您需要将项添加到observable集合中。如果不使用CollectionView,我这样做的方法是拥有一个ObservableCollection类型的只读变量,它永远不会改变。然后,当您对消息发出请求时,我会确保清除集合,为新项目做好准备。一旦返回消息,循环遍历响应中的每个模型项(消息)并将它们转换为MessageViewModels(一个包含可绑定属性和验证(数据注释)的新类。)当每个ViewModel项创建时,它将被添加到observablecollection。向集合添加项目的行为将引发listview正在侦听的事件,因此将显示该项目(只要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});
}
这有意义吗?
答案 2 :(得分:0)
一个糟糕的解决方案,但也许它很有帮助。你可以再次打电话给#34; OnProperyChanged。我再次说&#34;&#34;因为假设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
2015年2月4日编辑:好的解决方案在这里:OnPropertyChanged not fired when SetProperty is called
简单地删除单词&#34; Property&#34;在私人声明中。这是因为它传递了ByRef,因此它不能成为属性。