Windows Phone "ListBox" ItemsSource - c#

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

Related

Modifiing ItemsSource within BackgroundWorker Causes an Exception

I have a ListBox with an ObservableCollection as ItemsSource in my application.
Also I have serveral classes that provides data for this ItemsSource.
public ObservableCollection<Notification> NotificationItems { get; set; }
private object _stocksLock = new object();
I create the collection within my constructor like that
this.NotificationItems = new ObservableCollection<Notification>();
System.Windows.Data.BindingOperations.EnableCollectionSynchronization(
this.NotificationItems, _stocksLock);
I am loading the modules providing data for the ListBox from serveral dll assemblies. The method to get Notification data for the collection is called within a BackgroundWorker
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += GetPluginModuleNotifications;
List<IModul> Modules = new List<IModul>();
//[...]
foreach (IModul PluginModul in AssemblyList)
{
//[...]
Modules.Add(PluginModul);
//[...]
}
this.Notifications.ItemsSource = this.NotificationItems;
object[] Parameter = new object[] { Modules, this.ComponentFactory,
this.MyListBox};
//-->Edited
worker.WorkerReportsProgress = true;
worker.ProgressChanged += OnProgressChanged;
//<--Edited
worker.RunWorkerAsync(Parameter);
//...
//-->EDITED
private void OnProgressChanged(object sender, ProgressChangedEventArgs e)
{
Notification toAdd = (Notification)e.UserState;
this.NotificationItems.Add(toAdd);
}
//<--EDITED
I want each of the IModul items to provide Items for the ListBox.
This part works fine at all so the data I want to receive is loaded.
Here is my BackgroundWorker.DoWork Event
private void GetPluginModuleNotifications(object sender, DoWorkEventArgs e)
{
object[] args = e.Argument as object[];
if (args == null || args.Length != 3) return;
List<IModul> Module = args[0] as List<IModul>;
IComponentFactory Factory = args[1] as IComponentFactory;
// DXListBox lb = args[2] as DXListBox;
if (Module == null || Factory == null) return;
foreach (IModul Modul in Module)
{
Notification[] res = Modul.GetImportantNotifications(Factory);
if (res == null || res.Length == 0) continue;
foreach (Notification notif in res)
{
//-->EDITED
(sender as BackgroundWorker).ReportProgress(1, notif);
System.Threading.Thread.Sleep(100);
//this.ReceiveNotification(notif);
//<--EDITED
}
}
}
private void ReceiveNotification(Notification obj)
{
if (obj == null) return;
Dispatcher.BeginInvoke(new Action(() =>
{
this.NotificationItems.Add(obj);
if (this.NotificationPanel.Width.Value == 0)
this.NotificationPanel.Width = new GridLength(NOTIFICATION_BAR_WIDTH);
}));
}
The XAML for the NotificationPanel looks like this:
.<dx:DXListBox x:Name="Notifications" VerticalAlignment="Stretch" BorderBrush="Transparent" MouseDoubleClick="NotificationGotoSource" ItemsSource="{Binding NotificationItems}">
<dx:DXListBox.ItemTemplate>
<DataTemplate DataType="{x:Type cbcore:Notification}">
<StackPanel Orientation="Horizontal">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="38" />
<ColumnDefinition Width="*" MinWidth="157"/>
<ColumnDefinition Width="15" />
</Grid.ColumnDefinitions>
<Image Source="{Binding ImageSource}" Grid.Column="0" Width="32" Height="32" VerticalAlignment="Top" HorizontalAlignment="Left" />
<StackPanel Orientation="Vertical" Grid.Column="1">
<Label FontWeight="Bold" FontSize="10" MaxHeight="25" MaxWidth="150">
<TextBlock Text="{Binding Headline}" TextWrapping="Wrap" />
</Label>
<Label FontWeight="Normal" FontSize="9" MaxHeight="100" MaxWidth="150">
<TextBlock Text="{Binding Note}" TextWrapping="Wrap" />
</Label>
</StackPanel>
<Label Cursor="Hand" Padding="0" Margin="0" MouseLeftButtonUp="Notification_RemoveSelected" Grid.Column="2"
OverridesDefaultStyle="True" BorderBrush="Black" Background="Transparent"
FontSize="8" FontWeight="Bold" VerticalAlignment="Top" HorizontalAlignment="Right">
<TextBlock Foreground="Red" TextAlignment="Center">X</TextBlock>
</Label>
</Grid>
</StackPanel>
</DataTemplate>
</dx:DXListBox.ItemTemplate>
</dx:DXListBox>
When I am running my application it will cause an XamlParseException that the object is owned by another thread and the main ui thread cannot acces it.
Can anyone help me to solve that problem?
Set the BackgroundWorker.WorkerSupportProgress to True and attach the ProgressChangedEvent. Replace your ReceiveNotification method with ReportProgress calls to update the UI. The ProgressChangedEventHandler is marshalling to the UI thread, so no invokerequired.
I think you use the wrong dispatcher. In your case you use the dispatcher of the background worker.
Try to keep a refererence of the UI Dispatcher, according to here You just need to access with Application.Current.Dispatcher.
The exception was thrown not cause the ObservableCollection was owned by another Thread, but the public BitmapImage ImageSource within the Notification model.
When the application tries to read the BitmapImage using Binding it fails. So my solution looks like following:
private BitmapImage _ImageSource = null;
public object _originalImageSource= null;
public object ImageSource
{
get { return this._ImageSource; }
set
{
this._originalImageSource = value;
if (this._ImageSource != value)
{
this._ImageSource = value is BitmapImage ? (BitmapImage)value :
value is Uri ?
new BitmapImage(value as Uri) :
new BitmapImage(new Uri(value.ToString()));
this.RaisePropertyChanged("ImageSource");
}
}
}
Within the OnProgressChanged Method I create a 1:1 copy of the Notification using the _originalImageSource to create a new BitmapImage
//-->EDITED
private void OnProgressChanged(object sender, ProgressChangedEventArgs e)
{
Notification t = (Notification)e.UserState;
Notification toAdd = new Notification(t.Parent, t.OriginalSource, t.Headline, t.Note, t._originalImageSource);
this.NotificationItems.Add(toAdd);
if (this.NotificationItems.Count > 0 && this.NotificationPanel.Width.Value == 0)
this.NotificationPanel.Width = new GridLength(NOTIFICATION_BAR_WIDTH);
}
//<--EDITED
Thanks a lot for your support.

Telerik RadJumpList using DataVirtualizationMode.Automatic

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 can't display the result of my rss reader

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.

how to navigate from a listbox in windows phone 7 application

I am building an application for Windows Phone 7 where in a ListBox I am showing data from the web service.
The WebService contains the following data:
News Title, News Description, Date Start and image path.
In the list box I am showing News Title, Date Start and image path.
Now on clicking an item from the list box I want to navigate to another page which should show all the three details along with news description.
My xaml is:
<ListBox Name="listBox1" SelectionChanged="listBox1_SelectionChanged">
<!-- SelectionChanged="listBox1_SelectionChanged"-->
<ListBox.ItemTemplate>
<DataTemplate>
<Button>
<Button.Content>
<ScrollViewer HorizontalScrollBarVisibility="Auto" Height="80" Width="400">
<StackPanel Orientation="Horizontal" Margin="0,0,0,0">
<Image Source="{Binding ImageBind }" Height="80" Width="120"/>
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Path=News_Title}" TextWrapping="Wrap"></TextBlock>
<!-- <TextBlock Text="{Binding Path=News_Description}" TextWrapping="Wrap"></TextBlock>-->
<TextBlock Text="{Binding Path=Date_Start}" TextWrapping="Wrap" ></TextBlock>
</StackPanel>
</StackPanel>
</ScrollViewer>
</Button.Content>
</Button>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
The .cs file is:
public News()
{
InitializeComponent();
KejriwalService.aapSoapClient client = new KejriwalService.aapSoapClient();
client.getarvindNewsCompleted += new EventHandler<KejriwalService.getarvindNewsCompletedEventArgs>(client_getarvindNewsCompleted);
client.getarvindNewsAsync();
progressName.Visibility = System.Windows.Visibility.Visible;
}
void client_getarvindNewsCompleted(object sender, KejriwalService.getarvindNewsCompletedEventArgs e)
{
string result = e.Result.ToString();
List<Newss> listData = new List<Newss>();
XDocument doc = XDocument.Parse(result);
progressName.Visibility = System.Windows.Visibility.Collapsed;
foreach (var location in doc.Descendants("UserDetails"))
{
Newss data = new Newss();
data.News_Title = location.Element("News_Title").Value;
//data.News_Description = location.Element("News_Description").Value;
data.Date_Start = location.Element("Date_Start").Value;
data.image_path = location.Element("image_path").Value;
data.ImageBind = new BitmapImage(new Uri( #"http://political-leader.vzons.com/ArvindKejriwal/images/uploaded/"+data.image_path, UriKind.Absolute));
listData.Add(data);
}
listBox1.ItemsSource = listData;
}
Now in a new page say newsdetails.xaml i want to navigate from this page and show the complete details.
Please help.
I am stuck in this as I am new in this domain.
I am almost done with my app if this is done.
private void listBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (listBox1.SelectedIndex == -1)
return;
var item = listBox1.SelectedItem as Newss;
if (!IsolatedStorageSettings.ApplicationSettings.Contains("SelectedObject"))
{
IsolatedStorageSettings.ApplicationSettings["SelectedObject"] = item;
NavigationService.Navigate(new Uri("/NewsDetails.xaml", UriKind.Relative));
}
}
Define static global variables in that page where your listbox selection change event is:
public static string title;
public static string news_description;
On listbox selection change assign these variables:
private void listBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (listBox1.SelectedIndex == -1)
return;
var item = listBox1.SelectedItem as Newss;
if (!IsolatedStorageSettings.ApplicationSettings.Contains("SelectedObject"))
{
IsolatedStorageSettings.ApplicationSettings["SelectedObject"] = item;
title=item.News_Title;
news_description=item.News_Description;
NavigationService.Navigate(new Uri("/NewsDetails.xaml", UriKind.Relative));
}
}
And in your navigation NewsDetails.cs page Access these items like this:
string Title=YourPageName.title;//
string Description=YourPageName.news_description;
show these values as you want

reading rss feed in wp7 with c#

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

Categories