c# - ObservableCollection 项的异步更新

标签 c# wpf asynchronous observablecollection

我是多线程和 WPF 的新手。

我有一个 ObservableCollection<RSSFeed> ,在应用程序启动时,项目从 UI 线程添加到此集合。 RSSFeed 的属性绑定(bind)到 WPF ListView。稍后,我想异步更新每个 RSSFeed。所以我正在考虑实现类似 RSSFeed.FetchAsync() 的东西并在其更新后的属性上引发 PropertyChanged。

我知道 ObservableCollection 不支持来自 UI 线程以外的线程的更新,它会抛出 NotSupportedException。但是由于我不是在操作 ObservableCollection 本身而是更新其项目的属性,我是否可以期望它起作用并看到 ListView 项目已更新?或者它会因为 PropertyChanged 而抛出异常吗?

编辑:代码

RSSFeed.cs

public class RSSFeed
{
    public String Title { get; set; }
    public String Summary { get; set; }
    public String Uri { get; set; }        
    public String Encoding { get; set; }
    public List<FeedItem> Posts { get; set; }
    public bool FetchedSuccessfully { get; protected set; }        

    public RSSFeed()
    {
        Posts = new List<FeedItem>();
    }

    public RSSFeed(String uri)
    {
        Posts = new List<FeedItem>();
        Uri = uri;
        Fetch();
    }

    public void FetchAsync()
    { 
        // call Fetch asynchronously
    }

    public void Fetch()
    {
        if (Uri != "")
        {
            try
            {
                MyWebClient client = new MyWebClient();
                String str = client.DownloadString(Uri);

                str = Regex.Replace(str, "<!--.*?-->", String.Empty, RegexOptions.Singleline);
                FeedXmlReader reader = new FeedXmlReader();
                RSSFeed feed = reader.Load(str, new Uri(Uri));

                if (feed.Title != null)
                    Title = feed.Title;
                if (feed.Encoding != null)
                    Encoding = feed.Encoding;
                if (feed.Summary != null)
                    Summary = feed.Summary;
                if (feed.Posts != null)
                    Posts = feed.Posts;

                FetchedSuccessfully = true;
            }
            catch
            {
                FetchedSuccessfully = false;
            }

        }
    }

用户配置文件.cs

public class UserProfile : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    public event CollectionChangeEventHandler CollectionChanged;

    private ObservableCollection<RSSFeed> feeds;
    public ObservableCollection<RSSFeed> Feeds 
    { 
        get { return feeds; }
        set { feeds = value; OnPropertyChanged("Feeds"); }
    }

    public UserProfile()
    {
        feeds = new ObservableCollection<RSSFeed>();
    }

    protected void OnPropertyChanged(string name)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }

    protected void OnCollectionChanged(RSSFeed feed)
    {
        CollectionChangeEventHandler handler = CollectionChanged;
        if (handler != null)
        {
            handler(this, new CollectionChangeEventArgs(CollectionChangeAction.Add, feed));
        }
    }
}

主窗口.xaml.cs

public partial class MainWindow : Window, INotifyPropertyChanged
{
    // My ListView is bound to this
    // ItemsSource="{Binding Posts}
    public List<FeedItem> Posts
    {
        get 
        {
            if (listBoxChannels.SelectedItem != null)
                return ((RSSFeed)listBoxChannels.SelectedItem).Posts;
            else
                return null;
        }
    }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        // here I load cached feeds
        // called from UI thread

        // now I want to update the feeds
        // since network operations are involved, 
        // I need to do this asynchronously to prevent blocking the UI thread
    }

}

谢谢。

最佳答案

在 .Net 4.5 中,您可以使用 BindingOperations.EnableCollectionSynchronization 添加对 ObservableCollection 后台线程更新的支持。这对 MVVM 非常有效。

参见: BindingOperations.EnableCollectionSynchronization() equivalent for .net 4.0

关于c# - ObservableCollection 项的异步更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10518786/

相关文章:

c# - C# 的部分类是糟糕的设计吗?

c# - 输入不是有效的 Base64 字符串,因为它包含一个非 base 64 字符,超过两个填充字符

c# - AddDays() 在 while 循环中不起作用

c# - TextBlock 作为复选框内容不显示

javascript - setState() 的异步性质不显示父组件更新的 props

javascript - 在从异步函数内部调用函数时,是否有任何理由更喜欢 node.js 中函数的异步版本?

Objective-C:如何为异步方法正确使用内存管理

c# - 使用线程从两个长时间运行的方法返回值

wpf - 如何使基于 XAML 的 UI 开发变得可以忍受?

wpf - MultiBinding unsetvalue 的回退值