“BindingExpression 路径错误”使用 ItemsControl 和 VirtualizingStackPanel

发布于 2024-10-16 19:55:53 字数 10608 浏览 2 评论 0原文

我在 Windows Phone 7 上使用 Silverlight。

使用 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>

这是在 UserControl 中,其 DataContext 设置为 MainViewModel ViewModel。

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')..

它正在主视图模型上寻找“Title”属性(其 Notes 属性是 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 

谢谢, 达米安

I'm using Silverlight on Windows Phone 7.

Is it normal to get loads of "BindingExpression path error" debug messages when using a VirtualizingStackPanel? I think it is happening because the visual items are temporarily unbound from the data items collection as they are recycled ...

I have an ItemsControl whose ItemsPanel's ItemsPanelTemplate is a VirtualizingStackPanel. It binds to a "Notes" ObservableCollection on my ViewModel.

<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>

This is within a UserControl whose DataContext is set to a MainViewModel ViewModel.

The ListDataTemplate contains a Button, which itself contains some text, data-bound to a property of the items in the Notes ObservableCollection:

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

When I run my program it all works fine - only a small number of items in my Notes collection are bound to at any one time. However I get lots of debug errors as I scroll up and down:

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')..

It is looking for the "Title" property on the main view model (whose Notes property is the ItemsSource) - I think this is normal - it is a transient situation as the visual items are unbound from items in the Notes collection in order to be recycled by assigning them to another item in the collection.

Has anyone else seen this? Am I right that it is normal?

If I create a dummy Title property on my MainViewModel and set a debug breakpoint then I see this stack trace. Note the "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 

Thanks,
Damian

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

日记撕了你也走了 2024-10-23 19:55:53

我认为您对情况的评估是正确的,但这听起来像是 VirtualizingStackPanel 工作方式中的一个错误。它不会影响应用程序在需要时的执行或绑定,但引发异常是一项相对昂贵的操作,因此在取消链接容器时相应地更新适当的 DataContext 是有意义的。

我认为将其作为潜在错误提出的最佳地点是 App Hub 论坛

I think your assessment of the situation is correct, but it sounds like a bug in the way the VirtualizingStackPanel works. It's not affecting the execution or bindings of your application at the points where you need it, but raising exceptions is a relatively expensive operation and so it would make sense to update the appropriate DataContext accordingly when unlinking the containers.

I think the best place to raise it as a potential bug would be on the App Hub forums

辞旧 2024-10-23 19:55:53

我知道这篇文章已经很老了,但是不创建虚拟属性的解决方案是确保项目的 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 属性。

I know this post is pretty old, but a solution without creating the dummy properties is making sure the DataContext of the items can only be of the type you expect.

I do this with the following converter on the root of the data template:

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();
    }
}

Add a static resource like this:

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

And in the data template, use the converter:

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

Now the Name property of the parent will never be checked.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文