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,所以它不能成爲一個屬性。

相關問題