2

我使用Silverlight在Windows Phone 7「BindingExpression路徑錯誤」使用的ItemsControl和VirtualizingStackPanel

這是正常使用VirtualizingStackPanel時得到「BindingExpression路徑錯誤」調試消息的負荷?我認爲這是發生的,因爲視覺項目暫時從數據項集合中解放出來,因爲它們被回收...

我有一個ItemsControl,其ItemsPanel的ItemsPanelTemplate是一個VirtualizingStackPanel。它綁定到我的ViewModel上的「Notes」ObservableCollection。

<ItemsControl x:Name="ListView" ItemsSource="{Binding Notes}" 
       ItemTemplate="{StaticResource ListDataTemplate}"> 
    <ItemsControl.ItemsPanel> 
     <ItemsPanelTemplate> 
      <VirtualizingStackPanel/> 
     </ItemsPanelTemplate> 
    </ItemsControl.ItemsPanel> 
    <ItemsControl.Template> 
     <ControlTemplate> 
      <ScrollViewer x:Name="ScrollViewer" Padding="{TemplateBinding Padding}"> 
       <ItemsPresenter/> 
      </ScrollViewer> 
     </ControlTemplate> 
    </ItemsControl.Template> 
</ItemsControl> 

這是一個用戶控件,其DataContext設置爲MainViewModel視圖模型內。

的ListDataTemplate包含一個按鈕,它本身包含一些文字,數據綁定到在Notes的ObservableCollection項目的性質:

<DataTemplate x:Key="ListDataTemplate"> 
     <Button> 
     <Grid> 
      <TextBlock TextWrapping="Wrap" Text="{Binding Title}"> 
     </Grid> 
    </Button> 
</DataTemplate> 

當我運行我的程序這一切工作正常 - 只有一小我的Notes集合中的項目數量在任何時候都是綁定的。不過,我得到很多調試錯誤,因爲我向上和向下滾動:

System.Windows.Data Error: BindingExpression path error: 'Title' property not found on 'EnWp7.ViewModels.MainViewModel' 'EnWp7.ViewModels.MainViewModel' (HashCode=119211466). BindingExpression: Path='Title' DataItem='EnWp7.ViewModels.MainViewModel' (HashCode=119211466); target element is 'System.Windows.Controls.TextBlock' (Name=''); target property is 'Text' (type 'System.String').. 
System.Windows.Data Error: BindingExpression path error: 'Title' property not found on 'EnWp7.ViewModels.MainViewModel' 'EnWp7.ViewModels.MainViewModel' (HashCode=119211466). BindingExpression: Path='Title' DataItem='EnWp7.ViewModels.MainViewModel' (HashCode=119211466); target element is 'System.Windows.Controls.TextBlock' (Name=''); target property is 'Text' (type 'System.String').. 
System.Windows.Data Error: BindingExpression path error: 'Title' property not found on 'EnWp7.ViewModels.MainViewModel' 'EnWp7.ViewModels.MainViewModel' (HashCode=119211466). BindingExpression: Path='Title' DataItem='EnWp7.ViewModels.MainViewModel' (HashCode=119211466); target element is 'System.Windows.Controls.TextBlock' (Name=''); target property is 'Text' (type 'System.String').. 
System.Windows.Data Error: BindingExpression path error: 'Title' property not found on 'EnWp7.ViewModels.MainViewModel' 'EnWp7.ViewModels.MainViewModel' (HashCode=119211466). BindingExpression: Path='Title' DataItem='EnWp7.ViewModels.MainViewModel' (HashCode=119211466); target element is 'System.Windows.Controls.TextBlock' (Name=''); target property is 'Text' (type 'System.String').. 

它正在尋找的「標題」屬性在主視圖模型(其注屬性是的ItemsSource) - 我認爲這是正常 - 這是一個短暫的情況,因爲視覺項目與Notes集合中的項目沒有任何關係,以便通過將它們分配給集合中的另一個項目進行回收。

有沒有其他人看到過這個?我是對的,這是正常的?

如果我在我的MainViewModel上創建了一個虛擬Title屬性並設置了一個調試斷點,我就看到了這個堆棧跟蹤。請注意「UnlinkContainerFromItem」:

...!EnWp7.ViewModels.MainViewModel.Title.get() Line 54 C# 
mscorlib.dll!System.Reflection.RuntimeMethodInfo.InternalInvoke(System.Reflection.RuntimeMethodInfo rtmi = {System.Reflection.RuntimeMethodInfo}, object obj = {EnWp7.ViewModels.MainViewModel}, System.Reflection.BindingFlags invokeAttr = Default, System.Reflection.Binder binder = null, object parameters = null, System.Globalization.CultureInfo culture = null, bool isBinderDefault = false, System.Reflection.Assembly caller = null, bool verifyAccess = true, ref System.Threading.StackCrawlMark stackMark = LookForMyCaller) 
mscorlib.dll!System.Reflection.RuntimeMethodInfo.InternalInvoke(object obj = {EnWp7.ViewModels.MainViewModel}, System.Reflection.BindingFlags invokeAttr = Default, System.Reflection.Binder binder = null, object[] parameters = null, System.Globalization.CultureInfo culture = null, ref System.Threading.StackCrawlMark stackMark = LookForMyCaller) + 0x14e bytes 
mscorlib.dll!System.Reflection.RuntimePropertyInfo.InternalGetValue(System.Reflection.PropertyInfo thisProperty = {System.Reflection.RuntimePropertyInfo}, object obj = {EnWp7.ViewModels.MainViewModel}, object[] index = null, ref System.Threading.StackCrawlMark stackMark = LookForMyCaller) + 0x4e bytes 
mscorlib.dll!System.Reflection.RuntimePropertyInfo.GetValue(object obj = {EnWp7.ViewModels.MainViewModel}, object[] index = null) + 0x2 bytes 
System.Windows.dll!System.Windows.CLRPropertyListener.Value.get() + 0x1b bytes 
System.Windows.dll!System.Windows.PropertyAccessPathStep.ConnectToPropertyInSource() + 0x148 bytes 
System.Windows.dll!System.Windows.PropertyAccessPathStep.ConnectToProperty() + 0x16 bytes 
System.Windows.dll!System.Windows.PropertyAccessPathStep.ReConnect(object newSource = {EnWp7.ViewModels.MainViewModel}) + 0x13 bytes  
System.Windows.dll!System.Windows.PropertyPathListener.ReConnect(object source = {EnWp7.ViewModels.MainViewModel}) + 0x10 bytes 
System.Windows.dll!System.Windows.Data.BindingExpression.SourceAquired() + 0x11 bytes 
System.Windows.dll!System.Windows.Data.BindingExpression.DataContextChanged(object o = {System.Windows.Controls.TextBlock}, System.Windows.DataContextChangedEventArgs e = {System.Windows.DataContextChangedEventArgs}) + 0x26 bytes 
System.Windows.dll!System.Windows.FrameworkElement.OnDataContextChanged(System.Windows.DataContextChangedEventArgs e = {System.Windows.DataContextChangedEventArgs}) + 0x15 bytes 
System.Windows.dll!System.Windows.FrameworkElement.OnAncestorDataContextChanged(System.Windows.DataContextChangedEventArgs e = {System.Windows.DataContextChangedEventArgs}) + 0x11 bytes 
System.Windows.dll!System.Windows.FrameworkElement.NotifyDataContextChanged(System.Windows.DataContextChangedEventArgs e = {System.Windows.DataContextChangedEventArgs}) + 0x59 bytes 
System.Windows.dll!System.Windows.FrameworkElement.OnAncestorDataContextChanged(System.Windows.DataContextChangedEventArgs e = {System.Windows.DataContextChangedEventArgs}) + 0x18 bytes 
System.Windows.dll!System.Windows.FrameworkElement.NotifyDataContextChanged(System.Windows.DataContextChangedEventArgs e = {System.Windows.DataContextChangedEventArgs}) + 0x59 bytes 
System.Windows.dll!System.Windows.FrameworkElement.OnAncestorDataContextChanged(System.Windows.DataContextChangedEventArgs e = {System.Windows.DataContextChangedEventArgs}) + 0x18 bytes 
System.Windows.dll!System.Windows.FrameworkElement.NotifyDataContextChanged(System.Windows.DataContextChangedEventArgs e = {System.Windows.DataContextChangedEventArgs}) + 0x59 bytes 
System.Windows.dll!System.Windows.FrameworkElement.OnAncestorDataContextChanged(System.Windows.DataContextChangedEventArgs e = {System.Windows.DataContextChangedEventArgs}) + 0x18 bytes 
System.Windows.dll!System.Windows.FrameworkElement.NotifyDataContextChanged(System.Windows.DataContextChangedEventArgs e = {System.Windows.DataContextChangedEventArgs}) + 0x59 bytes 
System.Windows.dll!System.Windows.FrameworkElement.OnAncestorDataContextChanged(System.Windows.DataContextChangedEventArgs e = {System.Windows.DataContextChangedEventArgs}) + 0x18 bytes 
System.Windows.dll!System.Windows.FrameworkElement.NotifyDataContextChanged(System.Windows.DataContextChangedEventArgs e = {System.Windows.DataContextChangedEventArgs}) + 0x59 bytes 
System.Windows.dll!System.Windows.FrameworkElement.OnAncestorDataContextChanged(System.Windows.DataContextChangedEventArgs e = {System.Windows.DataContextChangedEventArgs}) + 0x18 bytes 
System.Windows.dll!System.Windows.FrameworkElement.NotifyDataContextChanged(System.Windows.DataContextChangedEventArgs e = {System.Windows.DataContextChangedEventArgs}) + 0x59 bytes 
System.Windows.dll!System.Windows.FrameworkElement.OnAncestorDataContextChanged(System.Windows.DataContextChangedEventArgs e = {System.Windows.DataContextChangedEventArgs}) + 0x18 bytes 
System.Windows.dll!System.Windows.FrameworkElement.NotifyDataContextChanged(System.Windows.DataContextChangedEventArgs e = {System.Windows.DataContextChangedEventArgs}) + 0x59 bytes 
System.Windows.dll!System.Windows.FrameworkElement.OnPropertyChanged(System.Windows.DependencyProperty dp = {System.Windows.CoreDependencyProperty}) + 0x1d bytes 
System.Windows.dll!System.Windows.DependencyObject.RaisePropertyChangeNotifications(System.Windows.DependencyProperty dp = {System.Windows.CoreDependencyProperty}, object newValue = {EnWp7.ViewModels.MainViewModel}, object oldValue = {EnWp7.Store.NoteLocal}) + 0x38 bytes 
System.Windows.dll!System.Windows.DependencyObject.ClearValueInternal(System.Windows.DependencyProperty dp = {System.Windows.CoreDependencyProperty}) + 0x138 bytes 
System.Windows.dll!System.Windows.DependencyObject.ClearValue(System.Windows.DependencyProperty dp = {System.Windows.CoreDependencyProperty}) + 0x7 bytes 
System.Windows.dll!System.Windows.Controls.ItemContainerGenerator.UnlinkContainerFromItem(System.Windows.DependencyObject container = {System.Windows.Controls.ContentPresenter}, object item = {EnWp7.Store.NoteLocal}, bool isRecycling = true) + 0x1f bytes 
System.Windows.dll!System.Windows.Controls.ItemContainerGenerator.Remove(System.Windows.Controls.Primitives.GeneratorPosition position = {System.Windows.Controls.Primitives.GeneratorPosition}, int count = 2, bool isRecycling = true) + 0x14a bytes 
System.Windows.dll!System.Windows.Controls.ItemContainerGenerator.System.Windows.Controls.Primitives.IRecyclingItemContainerGenerator.Recycle(System.Windows.Controls.Primitives.GeneratorPosition position = {System.Windows.Controls.Primitives.GeneratorPosition}, int count = 2) + 0x9 bytes  
System.Windows.dll!System.Windows.Controls.VirtualizingStackPanel.CleanupRange(int startIndex = 0, int count = 2) + 0x20 bytes 
System.Windows.dll!System.Windows.Controls.VirtualizingStackPanel.CleanupContainers(System.Windows.Controls.ItemsControl itemsControl = {System.Windows.Controls.ItemsControl}) + 0x73 bytes  
System.Windows.dll!System.Windows.Controls.VirtualizingStackPanel.MeasureOverride(System.Windows.Size constraint = {System.Windows.Size}) + 0xe4 bytes 
System.Windows.dll!System.Windows.FrameworkElement.MeasureOverride(System.IntPtr nativeTarget = 102509504, float inWidth = 480.0, float inHeight = 499.0, out float outWidth = 0.0, out float outHeight = 0.0) + 0x45 bytes 

感謝, 達米安

+0

如果使用'VirtualizingStackPanel.VirtualizationMode =「Standard」'綁定錯誤消失了嗎? –

+0

不確定WP7上允許嗎? 如果我設置了,那麼我會得到一個運行時錯誤(「VirtualizingStackPanel元素上的未知屬性VirtualizationMode。」) – Damian

+0

我已更新我的問題以闡明我正在使用Windows Phone - 抱歉那。 – Damian

回答

2

我認爲你對形勢的判斷是正確的,但它聽起來像的方式VirtualizingStackPanel工作中的錯誤。它不會影響您的應用程序在您需要的位置執行或綁定,但引發異常是一項相對昂貴的操作,因此在取消鏈接容器時相應地更新相應的DataContext是有意義的。

我認爲最好的地方,以提高其作爲一個潛在的錯誤將是對App Hub forums

+0

謝謝德里克 - 我已經發布在這裏:http://forums.create.msdn.com/forums/t/75083.aspx – Damian

+0

也沒有反應。爲了避免錯誤,我在主視圖模型(yuck)上創建了虛擬屬性。 也發佈了連接上的條目 http://connect.microsoft.com/VisualStudio/feedback/details/642598/bindingexpression-path-error-using-itemscontrol-and-virtualizingstackpanel – Damian

+0

好主意。我相信,隨着框架的成熟,我們會解決這些問題。 –

1

我知道這個職位是很老,但不創建虛擬性的解決方案是確保項目的DataContext的可以只有你期望的類型。

我這樣做與數據模板的根目錄下變頻器:

public class SpecificTypeConverter : IValueConverter 
{ 
    public string Type { get; set; } 

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (value == null || value.GetType().FullName == this.Type) 
     { 
      return value; 
     } 

     return DependencyProperty.UnsetValue; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 

添加靜態資源是這樣的:

<p:PhoneApplicationPage.Resources> 
    <converters:SpecificTypeConverter x:Key="MustBeItem" Type="My.Namespace.MyListItemViewModel" /> 
</p:PhoneApplicationPage.Resources> 

,並在數據模板,使用轉換器:

<DataTemplate> 
    <StackPanel DataContext="{Binding Converter={StaticResource MustBeItem}}" > 
     <TextBlock Tekst="{Binding Path=Name}" /> 
    </StackPanel> 
</DataTemplate> 

現在,父項的Name屬性將不會被檢查。

相關問題