【问题标题】:Refreshing UI after update to a ListBox-bound collection更新到 ListBox 绑定集合后刷新 UI
【发布时间】:2012-03-17 03:56:33
【问题描述】:

我试图直观地显示一个项目(在我的例子中是 BitmapImage)已使用 WPF/MVVM 添加到 ListBox 中的集合中。为了提供一些背景知识,我正在使用采集卡捕获流式视频,并且在视频流式传输时拍摄静止图像。这些图像是通过单击 UI 上的“静止图像”按钮捕获的。捕获图像后,我想在 UI 上的单独面板中显示所述图像的缩略图。我知道需要做什么才能做到这一点,但我似乎无法让它发挥作用。现在,我的模型完成所有数据检索。

public ObservableCollection<BitmapImage> GetAssetThumbnails()
{
    var imageDir = ImgPath != null ? new DirectoryInfo(ImgPath) : null;
    if(imageDir != null)
    {
        try
        {
            foreach (FileInfo imageFile in imageDir.GetFiles("*.jpg"))
            {
                var uri = new Uri(imageFile.FullName);
                _assetThumbnails.Add(new BitmapImage(uri));
            }

        }
        catch (Exception)
        {
            return null;
        }
    }

    return _assetThumbnails;
}

我的 ViewModel 在其构造函数中创建模型的新实例,然后将公共属性 AssetCollection 设置为等于 _assetModel.GetAssetThumbnails()。 ViewModel 具有所有标准的 OnPropertyChanged 事件和事件处理。

private void OnPropertyChanged(string propertyName)
{
    if(PropertyChanged != null)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

#region Public Properties
public ObservableCollection<BitmapImage> AssetCollection
{
    get { return _assetCollection; }
    set
    {
        if (_assetCollection != value)
        {
            _assetCollection = value;
            OnPropertyChanged("AssetCollection");    
        }
    }
}
#endregion

private void _assetCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    OnPropertyChanged("AssetCollection");
}
public event PropertyChangedEventHandler PropertyChanged;

然后,在我的 XAML 文件中,我将 ListBox 的项目源绑定到 AssetCollection。

<ListBox x:Name="lstBoxAssets" ItemsSource="{Binding AssetCollection}" Grid.Row="1" Background="{DynamicResource GrayColor}" Margin="5,0,0,5" ></ListBox>   

我读到集合中的每个项目都应该实现 INotifyPropertyChanged 接口。我尝试为实现它的位图图像创建一个包装器类,但它也不起作用。有什么我在这里想念的吗?图像最初会显示,但在捕获并保存图像后不会刷新。我有一种感觉,它源于事件PropertyChanged 没有被调用。我通过调试注意到它在检查时始终为空,因此永远不会调用 OnPropetyChanged 方法。我不确定我应该在哪里添加这个事件处理程序。我只使用代码隐藏文件将视图模型的数据上下文添加到视图中,仅此而已。这就是我通常认为添加任何事件处理的地方。谁能看到我在这里遗漏的一些简单的东西?

【问题讨论】:

  • 尝试“我尝试为实现该功能的位图图像创建一个包装器类,但它也不起作用。”再次。对项目的更改需要通过 NotifyPropertyChanged 来自项目。您使用公共财产吗?
  • 是的,该属性是公开的。我将尝试再次创建一个包装类。上次我可能错过了什么。

标签: wpf mvvm listbox observablecollection


【解决方案1】:

您是在更新列表时更改ObservableCollection,还是更改存储在集合中的项目?

如果您要更改集合中的项目,您需要找到一种方法来告诉 WPF 当单个项目发生更改时集合已更改,以便它知道重新绘制它。

通常集合中的项目实现INotifyPropertyChanged,因此很容易将PropertyChange 通知附加到列表中的项目,通知WPF 在属性更改时引发CollectionChanged 事件。

// Wireup CollectionChanged in Constructor
public MyViewModel()
{
    ListOfSomeItems = new List<SomeItem>();
    AssetCollection.CollectionChanged += AssetCollection_CollectionChanged;
}

// In CollectionChanged event, wire up PropertyChanged event on items
void AssetCollection_CollectionChanged(object sender, CollectionChangedEventArgs e)
{
    if (e.NewItems != null)
    {
        foreach(Asset item in e.NewItems)
            item.PropertyChanged += Asset_PropertyChanged;
    }
    if (e.OldItems != null)
    {
        foreach(Asset item in e.OldItems)
            item.PropertyChanged -= Asset_PropertyChanged;
    }
}

// In PropertyChanged, raise CollectionChanged event
void Asset_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    OnPropertyChanged("AssetCollection");
}

如果项目未实现 INotifyPropertyChanged,则您必须在集合中的项目更改时手动引发 CollectionChanged 事件。

AssetCollection[0].Thumbnail = new BitmapImage(uri);
OnPropertyChanged("AssetCollection");

如果您通过添加/删除项目来更改 ObservableCollection 本身并且没有看到 UI 更新,那么听起来这可能是我们看不到的地方的语法错误。

我看到的最常见的是更改私有属性而不是公共属性。

// Will not raise the CollectionChanged notification
_assetCollection = _assetModel.GetAssetThumbnails();

// Will raise the CollectionChanged notification
AssetCollection = _assetModel.GetAssetThumbnails();

虽然我也看到很多人使用List 或自定义集合而不是ObservableCollection,这不会引发CollectionChanged 事件。

【讨论】:

  • 好吧,当我捕获一个新图像时,它只是保存在 ObservableCollection 中的图像保存在同一目录中。所以我想我需要更改项目 inside 集合,而不是集合本身。你的例子很有帮助,谢谢!我会尝试对您列出的一些更改进行一些更改,看看它们是否有效。
  • 我会接受这个作为答案,因为这有助于我理解我在代码中做错了什么。我仍然无法正确更新 UI,但这超出了此问题的范围,因为它与创建缩略图后未引发的事件有关。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-29
  • 2011-11-07
  • 2021-10-20
  • 2011-05-25
  • 2017-04-18
  • 2016-11-08
相关资源
最近更新 更多