【问题标题】:Binding Error in runtime clearing ObservableCollection运行时清除 ObservableCollection 时出现绑定错误
【发布时间】:2016-11-28 02:27:59
【问题描述】:

我有一个运行良好的 ObservableCollection,但是当我清除此 ObservableCollection 时,我无法删除运行时出现的绑定错误:

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=Icon; DataItem='NamedObject' (HashCode=40835417); target element is 'Image' (Name=''); target property is 'Source' (type 'ImageSource')

我编写了一个小代码来重现我在下面显示的问题:(查看):

    <Button Height="40" Width="40" Click="Button_Click"></Button>
    <ListBox ItemsSource="{Binding ProductList}">
        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <UniformGrid IsItemsHost="True"/>
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition/>
                        <RowDefinition Height="Auto" />
                    </Grid.RowDefinitions>
                    <Image Height="32" Source="{Binding Icon}" Stretch="Fill" Width="32"/>
                    <Label Grid.Row="1" Content="{Binding Description}"/>
                </Grid>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

    public ObservableCollection<Product> ProductList { get; set; }

    public void TestList()
    {
        ProductList = new ObservableCollection<Product>();
        ProductList.Add(new Product("Product1", "pack://application:,,,/Product1.png"));
        ProductList.Add(new Product("Product2", "pack://application:,,,/Product2.png"));
        ProductList.Add(new Product("Product3", "pack://application:,,,/Product3.png"));
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
         ProductList.Clear();          
         ProductList.Add(new Product("Product4", "pack://application:,,,/Product4.png"));            
    }

还有我的产品类别:

public class Product : INotifyPropertyChanged
{
    #region "## INotifyPropertyChanged Members ##"
    public event PropertyChangedEventHandler _propertyChanged;

    public event PropertyChangedEventHandler PropertyChanged
    {
        add { this._propertyChanged += value; }
        remove { this._propertyChanged -= value; }
    }

    protected virtual void OnPropertyChanged(string propertyName)
    {
        App.Current.Dispatcher.BeginInvoke((Action)delegate
        {
            if (this._propertyChanged != null)
                this._propertyChanged(this, new PropertyChangedEventArgs(propertyName));
        });
    }
    #endregion

    public string Description
    {
        get { return this.description; }
        set
        {
            this.description = value;
            this.OnPropertyChanged("Description");
        }
    }
    private string description;

    public BitmapImage Icon
    {
        get { return this.icon; }
        set
        {
            this.icon = value;
            this.OnPropertyChanged("Icon");
        }
    }
    private BitmapImage icon;

    public Product(string desc, string iconPath)
    {
        Description = desc;
        BitmapImage bi = new BitmapImage(new Uri(iconPath));
        bi.Freeze();
        Icon = bi;
    }
}

单击按钮并执行以下行时出现错误: 产品列表.清除();

我做了很多测试:

  • 从列表中逐个删除项目

  • 使用 Fallback 和 TargetNullValue:

       <Image Height="32" Source="{Binding Icon, FallbackValue='pack://application:,,,/transparent.png', TargetNullValue='pack://application:,,,/transparent.png'}" Stretch="Fill" Width="32"/>
    

有什么想法吗?

【问题讨论】:

  • 您尝试过 ProductList.ClearItems() 吗? msdn.microsoft.com/en-us/library/ms654925(v=vs.110).aspx
  • 我可以毫无问题地清除产品列表。错误不会重现。
  • INotifyPropertyChanged 的实现看起来有点混乱,甚至可能没有必要,除非您要动态更改列表中各个产品的描述和/或图标。跨度>
  • “.Clear()”函数只在绑定中返回恼人的运行时错误。示例中可能不需要 INotifyPropertyChanged,但它不会影响我遇到的问题。

标签: wpf xaml data-binding observablecollection


【解决方案1】:

尝试删除 TargetNullValue 和 FallbackValue,看看是否仍然出现?如果不是,则文件的 URI 有问题。

另外请记住,如果您经常引用 transparent.png,您会多次将相同的图像加载到内存中。而是考虑像这样在 ResourceDictionary 中添加一行:

<BitmapImage UriSource="/MyApp;component/Images/transparent.png" x:Key="Transparent" PresentationOptions:Freeze="True" />

然后像这样在 XAML 中使用:

<Image Height="32" Source="{Binding Icon, FallbackValue={StaticResource:Transparent}, TargetNullValue={StaticResource:Transparent}" Stretch="Fill" Width="32"/>

此更改将加载您的图像一次,但在许多地方使用它会减少内存压力。

【讨论】:

  • 谢谢你的建议,很有用。无论如何,错误仍然存​​在。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-20
  • 2013-06-16
  • 1970-01-01
相关资源
最近更新 更多