gpt4 book ai didi

WPF 性能缓慢 - 许多 DataItem=null 绑定(bind)警告

转载 作者:行者123 更新时间:2023-12-03 23:53:28 26 4
gpt4 key购买 nike

我有一个性能非常差的树控件,我正在尝试跟踪问题的根源。

我正在尝试确定以下警告是否重要:

System.Windows.Data Information: 10 : Cannot retrieve value using the binding and no valid fallback value exists; using default instead. BindingExpression:Path=ContextMenu.IsOpen; DataItem=null; target element is 'MultipleSelectionTreeViewItem' (Name=''); target property is 'NoTarget' (type 'Object')

即使关闭所有这些诊断,更新树内容的性能也非常糟糕(一秒钟内重新填充约 300 个项目),这就是我开始查看跟踪输出的原因。

在我的 TreeView 中,每次单击都会发出十几个警告,当我切换树以显示不同的内容时,会出现数百个这样的警告。但是,树的内容总是正确显示,因此数据上下文必须暂时设置为 null。

我为 DataContext 设置了显式绑定(bind)使用值(value)转换器尝试查看发生了什么。
<HierarchicalDataTemplate x:Key="HierarchyItemTemplate"
DataType="{x:Type local:HierarchyItem}"
ItemsSource="{Binding Children}">
<StackPanel DataContext="{Binding Converter={StaticResource DbgConverter}}" Orientation="Horizontal">
...
</StackPanel>
</HierarchicalDataTemplate>

...但该值似乎永远不会等于 null 进入那里。

我可以为所有绑定(bind)设置一个后备值以消除这些警告,但这会给 xaml 带来很多不必要的困惑,并且似乎它隐藏了问题而不是解决它(假设它甚至是一个问题!)。

所以我的问题是:
  • 这些诊断是否可能导致性能问题?
  • 如果是这样,当诊断关闭时,提供后备值会对性能产生任何影响吗?
  • 如果是这样,有没有比用crud填充xaml更好的方法?

  • 编辑

    使用后备值看起来无论如何都不是解决方案,因为它也无法找到资源:
    System.Windows.ResourceDictionary Warning: 9 : Resource not found; ResourceKey='Img_Folder_Closed_Ex'

    就像它忘记了资源字典中的所有内容,生成所有这些虚假错误,然后再次记住它们并显示正常。

    编辑

    好的,我通过注释掉所有绑定(bind)并将它们一一放回并解决沿途的问题进一步缩小了范围,因此现在它加载并且我可以单击项目并且没有生成任何诊断,直到.. . 当我单击更改树项目的按钮时,它会发疯并吐出数百个错误。这是错误的一小部分:
    System.Windows.Data Information: 21 : BindingExpression cannot retrieve value from null data item. This could happen when binding is detached or when binding to a Nullable type that has no value. BindingExpression:Path=IsIncluded; DataItem=null; target element is 'TreeViewItemIcon' (Name=''); target property is 'NoTarget' (type 'Object')
    System.Windows.Data Information: 10 : Cannot retrieve value using the binding and no valid fallback value exists; using default instead. BindingExpression:Path=IsIncluded; DataItem=null; target element is 'TreeViewItemIcon' (Name=''); target property is 'NoTarget' (type 'Object')
    System.Windows.Data Information: 41 : BindingExpression path error: 'IsFolder' property not found for 'object' because data item is null. This could happen because the data provider has not produced any data yet. BindingExpression:Path=IsFolder; DataItem=null; target element is 'TreeViewItemIcon' (Name=''); target property is 'NoTarget' (type 'Object')
    System.Windows.Data Information: 20 :System.Windows.Data Information: 21 : BindingExpression cannot retrieve value from null data item. This could happen when binding is detached or when binding to a Nullable type that has no value. BindingExpression:Path=IsFolder; DataItem=null; target element is 'TreeViewItemIcon' (Name=''); target property is 'NoTarget' (type 'Object')
    System.Windows.Data Information: 10 : Cannot retrieve value using the binding and no valid fallback value exists; using default instead. BindingExpression:Path=IsFolder; DataItem=null; target element is 'TreeViewItemIcon' (Name=''); target property is 'NoTarget' (type 'Object')
    System.Windows.ResourceDictionary Warning: 9 : Resource not found; ResourceKey='Img_QA'
    System.Windows.Data Information: 41 : BindingExpression path error: 'IsIncluded' property not found for 'object' because data item is null. This could happen because the data provider has not produced any data yet. BindingExpression:Path=IsIncluded; DataItem=null; target element is 'TreeViewItemIcon' (Name=''); target property is 'NoTarget' (type 'Object')
    BindingExpression cannot retrieve value due to missing information. BindingExpression:Path=IsFolder; DataItem=null; target element is 'TreeViewItemIcon' (Name=''); target property is 'NoTarget' (type 'Object')
    System.Windows.Data Information: 21 : BindingExpression cannot retrieve value from null data item. This could happen when binding is detached or when binding to a Nullable type that has no value. BindingExpression:Path=IsFolder; DataItem=null; target element is 'TreeViewItemIcon' (Name=''); target property is 'NoTarget' (type 'Object')
    System.Windows.Data Information: 10 : Cannot retrieve value using the binding and no valid fallback value exists; using default instead. BindingExpression:Path=IsFolder; DataItem=null; target element is 'TreeViewItemIcon' (Name=''); target property is 'NoTarget' (type 'Object')
    System.Windows.Data Information: 41 : BindingExpression path error: 'IsIncluded' property not found for 'object' because data item is null. This could happen because the data provider has noSystem.Windows.Data Information: 20 : BindingExpression cannot retrieve value due to missing information. BindingExpression:Path=IsIncluded; DataItem=null; target element is 'TreeViewItemIcon' (Name=''); target property is 'NoTarget' (type 'Object')
    System.Windows.Data Information: 21 : BindingExpression cannot retrieve value from null data item. This could happen when binding is detached or when binding to a Nullable type that has no value. BindingExpression:Path=IsIncluded; DataItem=null; target element is 'TreeViewItemIcon' (Name=''); target property is 'NoTarget' (type 'Object')
    System.Windows.Data Information: 10 : Cannot retrieve value using the binding and no valid fallback value exists; using default instead. BindingExpression:Path=IsIncluded; DataItem=null; target element is 'TreeViewItemIcon' (Name=''); target property is 'NoTarget' (type 'Object')
    t produced any data yet. BindingExpression:Path=IsIncluded; DataItem=null; target element is 'TreeViewItemIcon' (Name=''); target property is 'NoTarget' (type 'Object')
    System.Windows.Data Information: 20 : BindingExpression cannot retrieve value due to missing information. BindingExpression:Path=IsIncluded; DataItem=null; target element is 'TreeViewItemIcon' (Name=''); target property is 'NoTarget' (type 'Object')
    System.Windows.Data Information: 21 : BindingExpression cannot retrieve value from null data item. This could happen when binding is detached or when binding to a Nullable type that has no value. BindingExpression:Path=IsIncluded; DataItem=null; target element is 'TreeViewItemIcon' (Name=''); target property is 'NoTarget' (type 'Object')
    System.Windows.Data Information: 10 : Cannot retrieve value using the binding and no valid fallback value exists; using default instead. BindingExpression:Path=IsIncluded; DataItem=null; target element is 'TreeViewItemIcon' (Name=''); target property is 'NoTarSystem.Windows.ResourceDictionary Warning: 9 : Resource not found; ResourceKey='Img_QA'
    System.Windows.Data Information: 41 : BindingExpression path error: 'Name' property not found for 'object' because data item is null. This could happen because the data provider has not produced any data yet. BindingExpression:Path=Name; DataItem=null; target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')
    System.Windows.Data Information: 20 : BindingExpression cannot retrieve value due to missing information. BindingExpression:Path=Name; DataItem=null; target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')
    System.Windows.Data Information: 21 : BindingExpression cannot retrieve value from null data item. This could happen when binding is detached or when binding to a Nullable type that has no value. BindingExpression:Path=Name; DataItem=null; target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')
    System.Windows.Data Information: 10 : Cannot retrieve value using the binding and no valid fallback value exists; using default instead. BindingExpression:Path=Name; DataItem=null; target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')
    get' (type 'Object')

    如果我将按钮处理程序更改为仅将 ItemsSource 设置为一个空列表,那么它会生成相同的大量错误。看起来好像当源断开连接时,WPF 重新评估所有绑定(bind),并且正如人们所期望的那样,它们都失败了。

    编辑

    更简单的说...
  • ItemsSource 绑定(bind)到 ObservableCollection。
  • 我在 ObservableCollection 上调用 Clear()。
  • 所有绑定(bind)都被重新评估并且无法再找到它们的数据(因为它已被删除)
  • 最终所有项目都被删除

  • 为什么要重新评估这些绑定(bind)?有没有办法让它在没有所有额外工作的情况下移除这些元素?

    编辑

    我创建了一个展示部分问题的项目。它会生成错误,提示在调用 Clear() 时找不到资源,但它不会产生 dataItem=null 消息。我将继续尝试用简单的例子重现那些。不幸的是,我被防火墙阻止了 pastebin 等,所以这里是从标准 WPF 应用程序更改的代码......

    应用程序.xaml:
    <Application x:Class="ObservableCollectionTest.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    StartupUri="MainWindow.xaml">
    <Application.Resources>
    <Style x:Key="{x:Type TreeViewItem}" TargetType="{x:Type TreeViewItem}">
    <Setter Property="HorizontalContentAlignment" Value="Left" />
    <Setter Property="VerticalContentAlignment" Value="Center" />
    </Style>
    </Application.Resources>
    </Application>

    MainWindow.xaml:
    <Window x:Class="ObservableCollectionTest.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:l="clr-namespace:ObservableCollectionTest"
    Title="MainWindow" Height="350" Width="525">

    <Window.Resources>

    <ResourceDictionary>
    <ResourceDictionary.MergedDictionaries>
    <ResourceDictionary Source="/ObservableCollectionTest;component/Theme.xaml" />
    </ResourceDictionary.MergedDictionaries>

    <l:Model x:Key="TheModel" />

    </ResourceDictionary>

    </Window.Resources>

    <Grid>
    <Grid.Resources>
    <ObjectDataProvider x:Key="TheModelProvider" ObjectInstance="{StaticResource TheModel}" />

    <HierarchicalDataTemplate
    x:Key="TheModelTemplate"
    DataType="{x:Type l:TestItem}"
    ItemsSource="{Binding Items}">
    <StackPanel Orientation="Horizontal">
    <Image Style="{DynamicResource ImageStyle}" />
    <Label>
    <TextBlock Style="{DynamicResource TextBlockStyle}" Text="{Binding Name}" />
    </Label>
    </StackPanel>
    </HierarchicalDataTemplate>
    </Grid.Resources>
    <Grid.RowDefinitions>
    <RowDefinition />
    <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <TreeView
    ItemsSource="{Binding Source={StaticResource TheModelProvider}, Path=Items}"
    ItemTemplate="{StaticResource TheModelTemplate}"/>

    <Button
    Grid.Row="1"
    Height="30"
    Content="Empty the list"
    Click="EmptyTheList_Click" />
    </Grid>
    </Window>

    主窗口.cs:
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;

    namespace ObservableCollectionTest
    {
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
    public MainWindow()
    {
    PresentationTraceSources.DataBindingSource.Listeners.Add(
    new ConsoleTraceListener());

    PresentationTraceSources.DataBindingSource.Switch.Level = SourceLevels.All;

    InitializeComponent();
    }

    private void EmptyTheList_Click(object sender, RoutedEventArgs e)
    {
    (Resources["TheModel"] as Model).Items.Clear();
    }
    }
    }

    模型.cs:
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Linq;
    using System.Text;

    namespace ObservableCollectionTest
    {
    class Model
    {
    public ObservableCollection<TestItem> Items { get; set; }

    public Model()
    {
    Items = new ObservableCollection<TestItem>()
    {
    new TestItem()
    {
    Name = "TopLevel",
    Items = new List<TestItem>()
    {
    new TestItem() { Name = "Item1", Items = new List<TestItem>() },
    new TestItem()
    {
    Name = "Item2",
    Items = new List<TestItem>()
    {
    new TestItem() { Name = "SubItem1", Items = new List<TestItem>() },
    new TestItem() { Name = "SubItem2", Items = new List<TestItem>() },
    new TestItem() { Name = "SubItem3", Items = new List<TestItem>() }
    }
    },
    new TestItem() { Name = "Item3", Items = new List<TestItem>() },
    new TestItem() { Name = "Item4", Items = new List<TestItem>() }
    }
    }
    };
    }
    }

    class TestItem
    {
    public string Name { get; set; }

    public bool IsRoot { get { return Name == "TopLevel"; } }

    public List<TestItem> Items { get; set; }
    }
    }

    主题.xaml:
    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <ResourceDictionary.MergedDictionaries>
    <ResourceDictionary Source="/ObservableCollectionTest;component/Common.xaml" />
    </ResourceDictionary.MergedDictionaries>

    <BitmapImage x:Key="Img_Folder_Open_In" UriSource="/ObservableCollectionTest;component/VS11_Light_Folder_Open_In.png" />
    <BitmapImage x:Key="Img_Folder_Closed_In" UriSource="/ObservableCollectionTest;component/VS11_Light_Folder_Closed_In.png" />

    </ResourceDictionary>

    Common.xaml:
    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <Style x:Key="TextBlockStyle" TargetType="TextBlock">
    <Setter Property="Foreground" Value="Blue" />
    <Setter Property="Background" Value="Yellow" />

    <Style.Triggers>
    <MultiDataTrigger>
    <MultiDataTrigger.Conditions>
    <Condition Binding="{Binding Name}" Value="TopLevel" />
    <Condition Binding="{Binding IsExpanded, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type TreeViewItem}}, FallbackValue=False}" Value="True" />
    </MultiDataTrigger.Conditions>
    <Setter Property="Background" Value="Red" />
    </MultiDataTrigger>
    </Style.Triggers>
    </Style>

    <Style x:Key="ImageStyle" TargetType="{x:Type Image}">
    <Style.Triggers>
    <MultiDataTrigger>
    <MultiDataTrigger.Conditions>
    <Condition Binding="{Binding IsRoot}" Value="False" />
    <Condition Binding="{Binding IsExpanded, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type TreeViewItem}}, FallbackValue=False}" Value="True" />
    </MultiDataTrigger.Conditions>
    <Setter Property="Source" Value="{DynamicResource Img_Folder_Open_In}" />
    </MultiDataTrigger>

    <MultiDataTrigger>
    <MultiDataTrigger.Conditions>
    <Condition Binding="{Binding IsRoot}" Value="False" />
    <Condition Binding="{Binding IsExpanded, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type TreeViewItem}}, FallbackValue=False}" Value="False" />
    </MultiDataTrigger.Conditions>
    <Setter Property="Source" Value="{DynamicResource Img_Folder_Closed_In}" />
    </MultiDataTrigger>
    </Style.Triggers>
    </Style>

    </ResourceDictionary>

    FWIW,我也在使用 .NET 3.5(不幸的是我不得不这样做),但这个问题也确实出现在 .NET 4.0 中。

    我在项目中还有两张图片:

    VS11_Light_Folder_Closed_In.png (VS11_Light_Folder_Closed_In.png)
    VS11_Light_Folder_Open_In.png (VS11_Light_Folder_Open_In.png)

    编辑

    尝试更改 ObjectDataProvider使用动态资源:
    <ObjectDataProvider x:Key="TheModelProvider" ObjectInstance="{DynamicResource TheModel}" />

    但这产生了这个异常:

    Exception generated using DynamicResource for model

    最佳答案

    我已经设法摆脱了所有的绑定(bind)错误!

    我不知道为什么,但将资源添加到 Application.Resources而不是使用 UserControl.Resources解决了Resource not found错误。这远不是一个理想的解决方案(将用户控制资源的范围限定为用户控制会更好),但它确实有效。

    所有其他dataItem=null类型错误可以通过在各种绑定(bind)中提供回退值来解决。

    这已经解决了引发这个问题的性能问题,所以我原来的问题的答案是 修复绑定(bind)错误确实会对性能产生很大影响 .现在我已经修复了绑定(bind),我的树更新几乎是即时的,而不是占用一秒钟 :)

    非常感谢您的帮助!

    杰里米

    关于WPF 性能缓慢 - 许多 DataItem=null 绑定(bind)警告,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17492359/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com