2010-04-19 105 views
4

我有一個Silverlight控件,它具有我的根ViewModel對象,因爲它是數據源。 ViewModel公開了一張卡片列表以及一個SelectedCard屬性,該屬性綁定到視圖頂部的下拉列表中。然後,我在底部顯示SelectedCard的屬性。我的XAML顯示爲(減少爲簡單起見):Silverlight 3數據綁定子屬性不更新

<StackPanel Orientation="Vertical"> 
    <ComboBox DisplayMemberPath="Name" 
      ItemsSource="{Binding Path=Cards}" 
      SelectedItem="{Binding Path=SelectedCard, Mode=TwoWay}" 
      /> 
    <TextBlock Text="{Binding Path=SelectedCard.Name}" 
      /> 
    <ListBox DisplayMemberPath="Name" 
      ItemsSource="{Binding Path=SelectedCard.PendingTransactions}" 
      /> 
</StackPanel> 

我希望將TextBlock和列表框更新,每當我選擇在ComboBox一個新的項目,但事實並非如此。我相信這與TextBlock和ListBox實際綁定到SelectedCard的屬性有關,因此它正在偵聽該對象屬性的屬性更改通知。但是,我會認爲數據綁定足夠聰明,可以識別綁定表達式中的父對象已經更改並更新整個綁定。

它注意到PendingTransactions屬性(綁定到ListBox)是延遲加載的。因此,我第一次在ComboBox中選擇一個項目時,我會進行異步調用並加載列表和UI更新以顯示與所選項目相對應的信息。但是,當我重新選擇一個項目時,UI不會改變!

例如,如果我的原始列表包含三張卡片,則默認選擇第一張卡片。數據綁定確實嘗試訪問該Card對象上的PendingTransactions屬性並正確更新ListBox。如果我選擇列表中的第二張卡片,則會發生同樣的情況,並顯示該卡片的PendingTransactions列表。但是,如果我再次選擇第一張卡片,則在我的用戶界面中沒有任何變化!設置斷點,我能夠確認正在更新SelectedCard屬性。

我該如何做這項工作?

回答

0

原來,問題不在UI中。 PendingTransactions類使用異步WCF調用向服務器延遲加載其值。異步模式使用事件來通知調用者操作已完成,因此可以將數據解析到類中。因爲每張卡片都有自己的PendingTransactions類的實例,並且我們使用ServiceFactory來管理我們的WCF代理,所以每個實例都將它們的事件處理程序連接到相同的事件(爲了性能原因,我們正在使用單例方法 - 暫時) 。因此,每當任何實例觸發異步操作時,每個實例都會收到該事件。

這意味着數據綁定工作正常。 PendingTransactions系列每次查看新卡片時都會覆蓋自己。所以,看起來選擇一張以前的卡片實際上並沒有做任何事情,事實上,它選擇了正確的對象進行綁定,數據被搞砸了,看起來沒有任何變化。

感謝您的建議和指導!

0

如果您使用Silverlight 3,則需要使用INotifyPropertyChanged。

例子:

public class CardViewModel : INotifyPropertyChanged 
{ 
public event PropertyChangedEventHandler PropertyChanged; 
public ObservableCollection<Card> Cards { get; set; } 
private Card _selectedCard; 
public SelectedCard 
{ 
    get 
    { 
    return _selectedCard; 
    } 
    set 
    { 
    if (value != _selectedCard) 
    { 
    _selectedCard = value; 
    NotifyPropertyChanged("SelectedCard"); 
    } 
    } 
} 
public CardViewModel() 
{ 
    Cards = new ObservableCollection<Card>(); 
    //Populate Cards collection with objects 
} 
public void NotifyPropertyChanged(string item) 
{ 
    if (PropertyChanged!=null) 
    { 
    PropertyChanged(this, new PropertyChangedEventArgs(item)); 
    } 
} 
} 

所有你需要做的就是設置這個類你的觀點的DataContext,一切都應該是快樂的。

+0

這就是我唯一的例外,即Cards屬性是ReadOnlyCollection,因爲它不會改變。 – SonOfPirate 2010-04-19 16:07:56

0

我最近一直在使用的模式是將一個容器的詳細信息的數據上下文綁定到列表框的選定項。您的情況中的XAML變爲:

<StackPanel Orientation="Vertical"> 
    <ComboBox x:Name="_lbxCards"  <-- new 
       DisplayMemberPath="Name" 
       ItemsSource="{Binding Path=Cards}" 
       SelectedItem="{Binding Path=SelectedCard, Mode=TwoWay}" 
       /> 
    <StackPanel DataContext={Binding ElementName=_lbxCards,Path=SelectedItem}> <-- new 
     <TextBlock Text="{Binding Path=Name}"         <-- updated 
        /> 
     <ListBox DisplayMemberPath="Name" 
       ItemsSource="{Binding Path=PendingTransactions}"    <-- updated 
       /> 
    </StackPanel>                <-- new 
</StackPanel> 
+0

這根本不起作用!我沒有任何約束力。至少在它第一次綁定之前,我使用元素引用選擇了一個項目,根本沒有任何事情發生。 – SonOfPirate 2010-04-19 16:35:46