gpt4 book ai didi

c# - ObservableCollection 项的异步更新

转载 作者:太空狗 更新时间:2023-10-29 21:06:02 27 4
gpt4 key购买 nike

我是多线程和 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/

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