Soy nuevo en multihebra y WPF.Actualización asincrónica de los elementos de ObservableCollection
Tengo ObservableCollection<RSSFeed>
, al inicio de la aplicación, los elementos se agregan a esta colección desde el hilo de la interfaz de usuario. Las propiedades de RSSFeed se unen a WPF ListView. Más tarde, quiero actualizar cada RSSFeed de forma asíncrona. Así que estoy pensando en implementar algo como RSSFeed.FetchAsync()
y subir PropertyChanged en sus propiedades actualizadas.
Sé que ObservableCollection no admite actualizaciones de hilos que no sean el hilo de UI, arroja NotSupportedException. Pero como no estoy manipulando el ObservableCollection sino más bien actualizando las propiedades de sus elementos, ¿puedo esperar que esto funcione y ver los elementos de ListView actualizados? ¿O arrojaría una excepción de todos modos debido a PropertyChanged?
Editar: código
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;
}
}
}
UserProfile.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));
}
}
}
MainWindow.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
}
}
Gracias.
Gracias. Tengo una colección anidada en mi clase RSSFeed. ¿Sería una buena solución si RSSFeed.FetchAsync() generara un evento al completarse y devolviera una instancia de RSSFeed nueva (actualizada) a través de EventArgs? Más tarde, actualizaría el artículo correspondiente en la colección del hilo de la interfaz de usuario. – Martin
Esa es una posible solución. Si pudiéramos ver algún código, podría darte una respuesta más concreta. –
@malymato por lo general, los métodos Async proporcionan una devolución de llamada cuando se completan. ¿Qué tipo de implementación estás usando? –