How to read rss feed from here in wp7 app using c#: "http://www.nyc.gov/apps/311/311Today.rss"?
My Xaml code:
<ListBox HorizontalAlignment="Left" Margin="10,10,0,0" Name="listBox1" VerticalAlignment="Top" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel VerticalAlignment="Top">
<TextBlock x:Name="titleTxt" Height="30" Text="{Binding Title}" VerticalAlignment="Bottom" />
<TextBlock x:Name="dateTxt" Height="30" Text="{Binding Date}" />
<TextBlock x:Name="descTxt" Height="30" Text="{Binding Desc}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
My C# code:
private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
XDocument xDoc = XDocument.Load("http://www.nyc.gov/apps/311/311Today.rss");
XNamespace content = XNamespace.Get("http://purl.org/rss/1.0/modules/content/");
var items = xDoc.Descendants("item")
.Select(i => new
{
Title = i.Element("title").Value,
Date = DateTime.Parse(i.Element("pubDate").Value),
Desc = i.Element(content + "encoded").Value,
})
.ToArray();
listBox1.ItemsSource = items;
}
using (var wc = new WebClient())
{
XDocument xDoc = XDocument.Parse(wc.DownloadString("http://www.nyc.gov/apps/311/311Today.rss"));
XNamespace content = XNamespace.Get("http://purl.org/rss/1.0/modules/content/");
var items = xDoc.Descendants("item")
.Select(i => new
{
Title = i.Element("title").Value,
Date = DateTime.Parse(i.Element("pubDate").Value),
Desc = i.Element(content + "encoded").Value,
})
.ToArray();
}
A while ago I wrote an entire tutorial covering this topic. Details here:
Building a RSS reader for Windows Phone 7 – Designing the structure
Building a RSS reader for Windows Phone 7 – Developing the functionality
Related
I have a problem where im trying to use a Telerik Jump List with DataVirtualizationMode.Automatic, but i can't get it to work. The reason why i want to use this, is because i want my app to only download the data(games) which is in the current view of the Jump List control and not the whole data everytime. For example if i have searched for "Batman", and its returning 50 games, i don't want it to download and load all the games, only those i can see in the Jump List control.
Here is a sample of using DataVirtualizationMode.Automatic from Telerik, but i couldn't get it to work with my app: http://www.telerik.com/help/windows-phone/raddataboundlistbox-features-datavirtualization-automatic.html
Below is my Jump List control which i want to use with data virtualization.
MainPage.xaml:
<phone:PivotItem Header="Browse">
<Grid>
<telerikPrimitives:RadTextBox Name="txtSearch" HorizontalAlignment="Left" VerticalAlignment="Top" Height="80" Width="390"/>
<telerikPrimitives:RadImageButton Name="imgBtnSeachGame" VerticalAlignment="Top" HorizontalAlignment="Right" ButtonShape="Ellipse" BorderThickness="2" Margin="0,8,0,0" Click="imgBtnSeachGame_Click"></telerikPrimitives:RadImageButton>
<Controls:RadJumpList Name="jlGameList" ItemsSource="{Binding}" Tap="jlGameList_Tap" Margin="0,90,0,0" DataVirtualizationMode="Automatic">
<Controls:RadJumpList.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="20"></RowDefinition>
</Grid.RowDefinitions>
<Border Grid.Row="0" Background="{StaticResource PhoneAccentBrush}"
Padding="{StaticResource PhoneTouchTargetOverhang}"
Margin="0,0,0,0">
<TextBlock Name="tblGameTitle" Style="{StaticResource PhoneTextGroupHeaderStyle}" ManipulationStarted="tblGameTitle_ManipulationStarted" ManipulationCompleted="tblGameTitle_ManipulationCompleted">
<Run Text="{Binding GameTitle}"></Run>
</TextBlock>
</Border>
<Grid Background="#242424" Grid.Row="1">
<Image Name="imgGameList" Margin="0,0,0,0" Stretch="Fill" HorizontalAlignment="Left" VerticalAlignment="Top" Height="96" Width="96">
<Image.Source>
<BitmapImage UriSource="{Binding BoxArtFrontThumb}"
CreateOptions="BackgroundCreation" DecodePixelHeight="96" DecodePixelWidth="96" />
</Image.Source>
</Image>
<TextBlock Margin="110,0,0,0" Text="Platform" FontWeight="Bold" TextWrapping="Wrap" Foreground="YellowGreen" FontSize="{StaticResource PhoneFontSizeNormal}"/>
<TextBlock Name="txtPlatform" Margin="110,20,0,0" Text="{Binding Platform}"></TextBlock>
<TextBlock Text="Release Date" FontWeight="Bold" Margin="110,46,0,0" Foreground="YellowGreen" FontSize="{StaticResource PhoneFontSizeNormal}"/>
<TextBlock Name="txtReleaseDate" Margin="110,66,0,0" Text="{Binding ReleaseDate}"></TextBlock>
<!--</StackPanel>-->
</Grid>
<Grid Grid.Row="2"></Grid>
</Grid>
</DataTemplate>
</Controls:RadJumpList.ItemTemplate>
</Controls:RadJumpList>
</Grid>
</phone:PivotItem>
Below is where i bind my DataContext to my GetGamesListItems ObservableCollection in my GameData class. The imgBtnSearchGame_Click event method is being called when a user have typed for example "Batman" in my textbox txtSearch and tapped the button, it will then send the text to my GetGamesListData method.
MainPage.cs:
GameData gd = new GameData();
public MainPage()
{
InitializeComponent();
jlGameList.DataContext = gd.GetGamesListItems;
}
private void imgBtnSeachGame_Click(object sender, RoutedEventArgs e)
{
if (!string.IsNullOrEmpty(txtSearch.Text))
{
gd.GetGamesListData(txtSearch.Text, "", "");
}
}
Below is where i download the data in XML for the game name searched for. For example if it is "Batman" it will find and return all games with "Batman". The "BoxArtFrontThumb" Property is where im storing all the images for each game and is using async, because sometimes there can be quite alot of images it has to download and show.
GameData.cs
public void GetGamesListData(string name, string platform, string genre)
{
var webClient = new WebClient();
webClient.DownloadStringCompleted += GetGamesListRequestCompleted;
webClient.DownloadStringAsync(new Uri("http://thegamesdb.net/api/GetGamesList.php?name=" + name));
}
private async void GetGamesListRequestCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error == null)
{
GetGamesListItems.Clear();
var feedXml = XDocument.Parse(e.Result);
var gameDataTasks = feedXml.Root.Descendants("Game").Select(
async x => new GetGamesList
{
ID = (int)x.Element("id"),
GameTitle = (string)x.Element("GameTitle"),
ReleaseDate = (string)x.Element("ReleaseDate") ?? "N/A",
Platform = (string)x.Element("Platform") ?? "N/A",
BoxArtFrontThumb = new Uri(await GetBoxArtFrontThumbAsync((int)x.Element("id")), UriKind.RelativeOrAbsolute),
}).ToList();
var gameData = await Task.WhenAll(gameDataTasks);
foreach (var item in gameData)
{
GetGamesListItems.Add(item);
}
}
}
Below is where its finding and storing the images for the games.
public async Task<string> GetBoxArtFrontThumbAsync(int id)
{
var client = new HttpClient();
var result = await client.GetStringAsync("http://thegamesdb.net/api/GetArt.php?id=" + id);
var feedXml = XDocument.Parse(result);
var gameData = feedXml.Root.Descendants("Images").Select(x => new GetArt
{
BoxArtFrontThumb = new Uri(GetBoxArtFrontThumb(x), UriKind.RelativeOrAbsolute),
}).ToList();
return gameData.Single().BoxArtFrontThumb.ToString();
}
private static string GetBoxArtFrontThumb(XElement gameNode)
{
string data = "http://thegamesdb.net/banners/" + (string)gameNode.Descendants("boxart")
.FirstOrDefault(b => (string)b.Attribute("side") == "front");
if (data == "http://thegamesdb.net/banners/")
{
data = "/NoImage.jpg";
}
return data;
}
I really hope i explained this well enough and hope that there is someone that can help me solve this problem. Thanks.
Although you are using JumpList, the mechanism for Virtualizing the data is the same as the DataBoundListBox. (You can find more information here in the DataBoundListBox docs. There is a good tutorial using an OData service.)
In order for the Automatic mode to work properly, you need to be using Telerik's VirtualizingDataCollection object and initialize it with the proper arguments (count and page size).
I don't see this in the code you have provided above, can you please open a support ticket so that I can investigate further? See my comment above for the link. Let me know the ticket number and I'll provide further assistance.
I have the following problem :
this is my xaml code:
<ListBox Grid.Row="1" Name="ResultsView">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<StackPanel Width="340">
<TextBlock TextWrapping="Wrap" Text="{Binding Path=Title}"/>
<TextBlock FontWeight="Bold" Text="{Binding Path=Author}"/>
<TextBlock Text="{Binding Path=Published}"/>
<TextBlock Text="{Binding Path=Guid}"/>
<TextBlock Text="{Binding Path=Link}"/>
<TextBlock Text="{Binding Path=Description}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
and this my code for binding the listbox:
private void Feed(object Sender, DownloadStringCompletedEventArgs e)
{
XElement _xml;
try
{
if (!e.Cancelled)
{
_xml = XElement.Parse(e.Result);
ResultsView.Items.Clear();
foreach (XElement value in _xml.Elements("channel").Elements("item"))
{
Tweet _item = new Tweet();
_item.Title = value.Element("title").Value;
_item.Author = value.Element("author").Value;
_item.Published = DateTime.Parse(value.Element("pubDate").Value);
_item.Guid = value.Element("guid").Value;
_item.Link = value.Element("link").Value;
_item.Description = Regex.Replace(value.Element("description").Value,
#"<(.|\n)*?>", String.Empty);
ResultsView.Items.Add(_item);
MessageBox.Show("test");
}
}
}
catch
{
// Ignore Errors
}
}
the code when i launch the binding:
private void Lookup_Click(object sender, RoutedEventArgs e)
{
WebClient _client = new WebClient();
_client.DownloadStringCompleted += Feed;
_client.DownloadStringAsync(new Uri((_value + Location.Text)));
}
and this is the rss feed : rss feed link
here is indeed a valid rss feed but I never add an item to my listbox. (the alert is never displayed) and I can not find out why. Someone would have an idea? Thanks in advance.
Your main issue is that you ignore XML namespaces in the feed.
It should look something like:
XNameSpace ns = ...;
foreach (XElement value in _xml.Elements( ns + "channel").Elements(ns + "item"))
...
See this Question for some RSS related examples.
After that, I'm not so sure that a DataTemplate is applied to Items. Customary is to bind through the ItemsSource property.
And don't use _ on local variables names. They are only to be used like that on private fields.
I have Json links and i need to get the data into listview. listview consists of picture, Itemname and Price. I m using Newtonsoft.Json. I need to pass headers(username, password,..) and then call the menuitem link into my application to access the menuitem data. I have many items in this listview to display. I am giving only one example below for Json data. Pls suggest me any good information as i am new to json. Thank you.
{"data":[{"Menuitemid":1,"Menucategoryid":1,"Itemname":"Hot And Spicy Chicken Wings","Description":"About Hot And Spicy Chicken Wings","Price":12.0,"Picture":"http://www.ownboughtearned.com/demo/wp-content/uploads/2012/11/small_thumbnail.png","Thumbnail":null,"Active":true}]}
/
/Listbox binding in xaml
<ListBox x:Name="lstItems" SelectionChanged="lstItems_SelectionChanged" CharacterSpacing="-1" >
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderThickness="0,0,0,1.2" BorderBrush="Silver"
HorizontalAlignment="Stretch" MinWidth="440">
<Grid Margin="0 10 0 10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<!--<RowDefinition Height="*" />-->
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="105" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="70" />
<!--<ColumnDefinition Width="*" />-->
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Grid.Row="0">
<Border BorderBrush="Silver" CornerRadius="3" Height="97"
Width="97" Background="White">
<Image Source="{Binding Path=Picture}" Stretch="Fill"
Height="95" Width="95" />
</Border>
</StackPanel>
<TextBlock Text="{Binding Path=Itemname}" MaxWidth="290" Margin="13 0 0 0"
FontSize="25" Foreground="#5b261e" TextWrapping="Wrap" TextTrimming="None"
Grid.Column="1" Grid.Row="0">
</TextBlock>
<TextBlock Margin="5" Text="{Binding Path=Price}"
FontSize="20" Foreground="#5b261e" Grid.Column="2" Grid.Row="1" VerticalAlignment="Center" />
</Grid>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
//MenuRepository.cs
namespace MenuInfo.Concrete
{
public class MenuRepository : IMenuRepository
{
public List<MenuItem> listitems = new List<MenuItem>();
public List<MenuItem> ListMenus()
{
System.Uri targetUri = new System.Uri("http://xxxxxxxxxx.testshell.net/api/restaurant/menuitems/1");
System.Net.HttpWebRequest httpWebRequest = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(targetUri);
httpWebRequest.Method = "GET";
httpWebRequest.Accept = "application/json";
httpWebRequest.Headers["username"] = "info#xxxxxxxxxx.com";
httpWebRequest.Headers["password"] = "xxxxxxxxxxxxxxxxxxxxxxxx";
httpWebRequest.BeginGetResponse(OnGetResponseCompleted, httpWebRequest);
return listitems;
}
private async void OnGetResponseCompleted(IAsyncResult ar)
{
try
{
var httpWebRequest = (HttpWebRequest)ar.AsyncState;
var response = httpWebRequest.EndGetResponse(ar);
var jsonSerializer = new DataContractJsonSerializer(typeof(MenuItemObject));
var responseObject = (MenuItemObject)jsonSerializer.ReadObject(response.GetResponseStream());
foreach (MenuItem loc in responseObject.data)
{
listitems.Add(loc);
}
}
catch (Exception ex)
{
}
}
}
}
Your problem stems from the fact that you are returning an empty collection from the ListMenus method. The method will return before it has a chance to populate the collection within the OnGetResponseCompleted callback. You can get around this in one of two ways. The first is to change you listitems variable to be an ObservableCollection.
public ICollection<MenuItem> listitems = new ObservableCollection<MenuItem>();
With this approach you will continue to return an empty collection, but when you add items to it within the OnGetResponseCompleted method, it will notify the ListBox that an item was added (provided that you set the ITemsSource to be the result of the ListMenus method. Doing it this way has negative performance impacts. For each item that you add, it notifies the UI to update rather than one big update with all of the items. It is also likely that it will throw an exception that you are trying to update a UI component when not on the UI thread. The callback OnGetResponseCompleted will likely be on a separate thread.
Another, and better approach would be to return the results using the async/await pattern. You could use the new HttpClient class to do this, but if you like using a WebRequest, you can still accomplish this using a TaskCompletionSource.
public Task<IList<MenuItem>> ListMenus()
{
var completion = new TaskCompletionSource<IList<MenuItem>>();
System.Uri targetUri = new System.Uri("http://xxxxxxxxxx.testshell.net/api/restaurant/menuitems/1");
System.Net.HttpWebRequest httpWebRequest = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(targetUri);
httpWebRequest.Method = "GET";
httpWebRequest.Accept = "application/json";
httpWebRequest.Headers["username"] = "info#xxxxxxxxxx.com";
httpWebRequest.Headers["password"] = "xxxxxxxxxxxxxxxxxxxxxxxx";
httpWebRequest.BeginGetResponse(ar =>
{
try
{
using (var response = httpWebRequest.EndGetResponse(ar))
{
using (var reader = new StreamReader(response.GetResponseStream()))
{
var responseObject =
Newtonsoft.Json.JsonConvert.DeserializeObject<MenuItemObject>(reader.ReadToEnd());
foreach (MenuItem loc in responseObject.data)
{
listitems.Add(loc);
}
}
}
}
catch (Exception ex)
{
}
completion.SetResult(listitems);
}, null);
return completion.Task;
}
With this approach, you would await the result of the ListMenus and set the ItemsSource from it.
lstItems.ItemsSource = await ListMenus();
Now you get the results populated, and do not have the performance impact of adding items one at a time.
I have a list and want to assign the downloaded feeds her. Also wanted to say that I am using the same code I've used in another app, but is giving an error as few as this. The other works perfectly. I will post few as the source of this. For if you can not stay too long.
private void carregaListas()
{
WebClient webClient = new WebClient();
webClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(webClient_DownloadStringCompleted);
webClient.DownloadStringAsync(new System.Uri("http://www.news-medical.net/syndication.axd?format=rss"));
}
private void webClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error != null)
{
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
stkLife.Visibility = Visibility.Visible;
stbOfLife.Begin();
});
}
else
{
// Save the feed into the State property in case the application is tombstoned.
//gridProgressBar.Visibility = Visibility.Collapsed;
this.State["feed"] = e.Result;
UpdateFeedList(e.Result);
}
}
private void UpdateFeedList(string feedXML)
{
StringReader stringReader = new StringReader(feedXML);
XmlReader xmlReader = XmlReader.Create(stringReader);
SyndicationFeed feed = SyndicationFeed.Load(xmlReader);
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
feedListBox.ItemsSource = feed.Items;
});
}
Error: "Items collection must be empty before using ItemsSource."
XAML code:
<ListBox x:Name="feedListBox" Margin="0,0,-12,0" SelectionChanged="feedListBox_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,17">
<StackPanel.Background>
<SolidColorBrush Color="#FFC5C5C5" Opacity="0.35"/>
</StackPanel.Background>
<TextBlock Text="{Binding Title.Text, Converter={StaticResource RssTextTrimmer}}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}" Foreground="White" FontSize="30"/>
<TextBlock Text="{Binding Summary.Text, Converter={StaticResource RssTextTrimmer}}" TextWrapping="Wrap" Style="{StaticResource PhoneTextSubtleStyle}" Foreground="#99FFFFFF"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
I Have used this sample: http://code.msdn.microsoft.com/wpapps/RSS-Reader-Sample-1702775f
I'm trying to bind some data to a wp7 listbox (with custom item template) which includes a thumbnail image for each entry. The thing is - I'm running into one problem - when the linked image redirects to a 404 page - I get an empty image as a result and frankly - I have no idea how to check if the loaded data is a proper image or not ... here's the code I'm using right now:
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Grid Height="62"
Width="62">
<Image Stretch="UniformToFill"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<Image.Source>
<BitmapImage UriSource="{Binding MiniImage}"
CreateOptions="DelayCreation, BackgroundCreation" />
</Image.Source>
</Image>
</Grid>
<StackPanel HorizontalAlignment="Center"
VerticalAlignment="Center">
<TextBlock Text="{Binding Title}"
Margin="12,4,0,0"
FontSize="26"
FontFamily="Segoe WP Bold" />
<TextBlock Text="{Binding PubDate}"
Margin="12,0,0,9"
FontSize="16"
FontStyle="Italic"
Padding="5,0,0,0"
FontFamily="Segoe WP"
Opacity="0.5" />
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
and here's the code behind:
foreach (var item in RssFeedItems)
{
var inputString = item.Description;
var tempImageList = new List<string>();
var inputStringBuilt = new StringBuilder(item.Description);
var temp = 1;
while (temp > 0)
{
var img = inputString.IndexOf("<img", StringComparison.Ordinal);
var src = inputString.IndexOf("src", img, StringComparison.Ordinal);
var quot = inputString.IndexOf('"', src + 5);
var len = quot - (src + 5);
var sub = len > 0 ? inputString.Substring(src + 5, len) : null;
tempImageList.Add(sub);
var closingBracket = inputString.IndexOf(">", src, StringComparison.Ordinal);
inputStringBuilt.Clear();
inputStringBuilt.Append(inputString);
inputStringBuilt.Remove(img, closingBracket - img);
inputString = inputStringBuilt.ToString();
temp = inputString.IndexOf("<img", StringComparison.Ordinal);
}
item.MiniImage = tempImageList[0] ?? "ApplicationIcon.png";
var f = tempImageList.IndexOf(null) - 1;
while (f >= 0)
{
PostImages.Add(tempImageList[f]);
f--;
}
tempImageList.Clear();
FirstListBox.Items.Add(item);
}
any ideas?
You might want to issue a web request in your code behind, pass the results into PictureDecoder.DecodeJpeg and bind to the WriteableBitmap returned from that instead of the URL. This way you can detect error conditions in the web request and react accordingly.
The Image element has an event called ImageFailed you will get an exception (contained in the ExceptionRoutedEventArgs)
You could use this to detect error when loading images.