Riprendiamo la nostra serie di articoli per la costruzione dell'RSS Reader in WPF. Questa è la volta della definizione della ListView.
Iniziamo a creare 2 wrapper che nascondono gli oggetti COM a WPF.
Incorriamo in questo modo in meno problematiche di Binding.
Ecco i due Wrapper
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Feeds.Interop;
using System.Collections;
namespace WpfRssReader
{
public class myFeed
{
private IFeed _currentFeed;
public string Copyright
{
get { return _currentFeed.Copyright; }
}
public string Description
{
get { return _currentFeed.Description; }
}
public string Image
{
get { return _currentFeed.Image; }
}
public myFeedItem[] Items
{
get
{
List<myFeedItem> _items = new List<myFeedItem>();
foreach (IFeedItem item in (IEnumerable)_currentFeed.Items)
{
_items.Add(new myFeedItem() { CurrentFeedItem = item });
}
return _items.ToArray();
}
}
public DateTime PubDate
{
get { return _currentFeed.PubDate; }
}
public string Title
{
get { return _currentFeed.Title; }
}
public string Url
{
get { return _currentFeed.Url; }
}
public IFeed CurrentFeed
{
get { return _currentFeed; }
set
{
_currentFeed = value;
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Feeds.Interop;
namespace WpfRssReader
{
public class myFeedItem : IFeedItem
{
private IFeedItem _currentFeedItem;
public IFeedItem CurrentFeedItem
{
get { return _currentFeedItem; }
set { _currentFeedItem = value; }
}
public string Author
{
get { return _currentFeedItem.Author; }
}
public string Comments
{
get { return _currentFeedItem.Comments; }
}
public string Description
{
get { return _currentFeedItem.Description; }
}
public string DownloadUrl
{
get { return _currentFeedItem.DownloadUrl; }
}
public object Enclosure
{
get { return _currentFeedItem.Enclosure; }
}
public string Guid
{
get { return _currentFeedItem.Guid; }
}
public bool IsRead
{
get
{
return _currentFeedItem.IsRead;
}
set
{
_currentFeedItem.IsRead = value;
}
}
public DateTime LastDownloadTime
{
get { return _currentFeedItem.LastDownloadTime; }
}
public string Link
{
get { return _currentFeedItem.Link; }
}
public int LocalId
{
get { return _currentFeedItem.LocalId; }
}
public DateTime Modified
{
get { return _currentFeedItem.Modified; }
}
public object Parent
{
get { return _currentFeedItem.Parent; }
}
public DateTime PubDate
{
get { return _currentFeedItem.PubDate; }
}
public string Title
{
get { return _currentFeedItem.Title; }
}
public void Delete()
{
_currentFeedItem.Delete();
}
public string Xml(FEEDS_XML_INCLUDE_FLAGS includeFlags)
{
return _currentFeedItem.Xml(includeFlags);
}
}
}
Una volta preparate le classi dobbiamo apportare una piccolissima correzione al codice che inserisce il feed all'interno del TAG degli oggetti della TreeView in modo da utilizzare le nuove classi al posto degli oggetti COM che ci restituisce il FeedFolder.
[code language="c#"]
foreach (IFeed feed in ((IFeedsEnum)feedfolder.Feeds))
{
TreeViewItem tvi = new TreeViewItem()
{
Header = feed.Name,
Tag = new myFeed() { CurrentFeed = feed } // <<<-------- Riga modificata.
};
// Esegue il download asincrono degli items presenti nel feed
ThreadPool.QueueUserWorkItem(delegate
[/code]
A questo punto facciamo una piccola modifica anche allo xaml ed inseriamo il DataTemplate per la visualizzazione dei feed.
[code language="XML"]
<ListView Width="Auto" Height="Auto" BorderThickness="0,0,0,0"
ItemsSource="{Binding Path=SelectedItem.Tag.Items, ElementName=tvFeedsFolders, Mode=OneWay}" IsSynchronizedWithCurrentItem="True">
<ListView.ItemTemplate>
<DataTemplate>
<Grid
Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListView}}, Path=Width}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="3*" />
<RowDefinition Height="1*" />
</Grid.RowDefinitions>
<Rectangle Margin="0" Grid.RowSpan="2" RadiusX="3" RadiusY="3" />
<TextBlock Text="{Binding Path=Title}"
FontFamily="Calibri"
FontSize="16"
FontWeight="Bold"
Grid.Column="0" Grid.Row="0"/>
<WrapPanel Grid.Column="0" Grid.Row="1">
<TextBlock Text="{Binding Path=PubDate}" FontStyle="Italic" />
<TextBlock Text=" " />
<TextBlock Text="{Binding Path=Author}" FontWeight="Bold"/>
</WrapPanel>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
[/code]
Aggiungiamo in fine un elemento Frame che ci permetterà di visualizzazre il contenuto HTML dei posts.
[code language="XML"]
<Border
DataContext="{Binding Path=SelectedItem, ElementName=lvDetails}"
Margin="3,3,0,0" Grid.Column="1" Grid.Row="2" BorderBrush="#FF222222" BorderThickness="1,1,1,1" CornerRadius="4,4,4,4" Padding="4,4,4,4">
<Frame Source="{Binding Path=Link}" NavigationUIVisibility="Hidden"></Frame>
</Border>
[/code]
In allegato a questo post trovate il progetto completo con le parti sviluppate fino a questo punto.
Nei post futuri vedremo compe personalizzare il layout di quest'applicazione con Blend e come applicare alcuni Effetti che WPF ci permette di realizzare.
Buon divertimento.