Parsing Xml feed having multiple different categories - windows-phone-8

Can anybody please tell me how can I parse the below Feed
http://teluguone.com/movies/moviesXml.php
In MainPage I will Arrange 8 Buttons like Action,
Comedy,
Love etc as based on different categories given in above feed.
When I click Action Button.The movies present in the Action Category has to be displayed in listbox.
And similarly when clicked on the other buttons also movies related to that particular categories has to be displayed in ListBox.
Anybody please give me hint how can I parse this feed with different categories.I am not understanding how can I parse these different categories.
I have written the following code to download xml file.Does it works.please tell me.
MainPage.Xaml:
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<ListBox x:Name="moviesList" >
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Height="130">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image delay:LowProfileImageLoader.UriSource="{Binding MovieImage}"
Grid.Column="0"
Width="97"
Height="125"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Margin="6"/>
<StackPanel Margin="10,15,0,0"
Grid.Column="1"
Height="60"
Orientation="Horizontal"
VerticalAlignment="Top">
<TextBlock Text="{Binding MovieName}"
FontSize="30" />
</StackPanel>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
Mainpage.xaml.cs:
namespace PhoneApp1
{
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
InitializeComponent();
// is there network connection available
if (!System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable())
{
MessageBox.Show("No network connection available!");
return;
}
// start loading XML-data
WebClient downloader = new WebClient();
Uri uri = new Uri("http://teluguone.com/movies/moviesXml.php", UriKind.Absolute);
downloader.DownloadStringCompleted += new DownloadStringCompletedEventHandler(MoviesDownloaded);
downloader.DownloadStringAsync(uri);
}
void MoviesDownloaded(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Result == null || e.Error != null)
{
MessageBox.Show("There was an error downloading the XML-file!");
}
else
{
// Deserialize if download succeeds
XmlSerializer serializer = new XmlSerializer(typeof(Movies));
XDocument document = XDocument.Parse(e.Result);
Movies movies = (Movies)serializer.Deserialize(document.CreateReader());
moviesList.ItemsSource = movies.Collection;
}
}
}
}
Movie.cs:
public class Movie
{
[XmlElement("MovieName")]
public string MovieName { get; set; }
[XmlElement("MovieActor")]
public string MovieActor { get; set; }
[XmlElement("MovieActress")]
public string MovieActress { get; set; }
[XmlElement("MovieDirector")]
public string MovieDirector { get; set; }
[XmlElement("MovieImage")]
public string MovieImage { get; set; }
}
Movies.cs:
[XmlRoot("Movies")]
public class Movies
{
[XmlArray("movies")]
[XmlArrayItem("movie")]
public ObservableCollection<Movie> Collection { get; set; }
}
ManyThanks in Advance

First understand basic XML structure and write properties based on that. Its very long to describe here, hence I have uploaded my sample project "XML deserialization into C# objects" in GitHub and refer for more info.
Step 1: Write properties based on XML Structure, which your retrieve from Source.
Step 2: Download the XML string using WebClient or Http class.
Step 3: Deserialize those strings using XMLSerializer and bind it to objects.
Step 4: Get respective terms using providing search options from objects.
You can refer my GitHub Project here.

Related

Binding data from Linq Database using Observable Collection - WP8

I'm saving some data in a database using linq. I have a DAO class, where I put all my CRUD methods, and I have another class where I define my table and its columns.
[Table(Name = "CONTACTS")]
public class UserContacts
{
private int _id;
[Column(Name = "ID", IsPrimaryKey = true, IsDbGenerated = true, CanBeNull = false, AutoSync = AutoSync.OnInsert)]
public int ID
{
get { return _id; }
set { _id = value; }
}
private string _name;
[Column(Name = "NAME", CanBeNull = false)]
public string NAME
{
get { return _name; }
set { _name = value; }
}
private string _number;
[Column(Name = "NUMBER", CanBeNull = false)]
public string NUMBER
{
get { return _number; }
set { _number = value; }
}
}
DAO Class
public class DAOUserContacts
{
public IList<UserContacts> list = new List<UserContacts>();
public IList<UserContacts> GetData()
{
try
{
using (DataBaseContext db = new DataBaseContext(DataBaseContext.ConnectionString))
{
list = (from info in db.UserContacts orderby info.COLUMN_NAME ascending select info).ToList();
}
return list;
}
catch (Exception)
{
return null;
}
}
// Other methods
}
I'm showing all data stored in this database in a LongListSelector.
In Main.cs constructor
llsContacts.DataContext = new DAORUserContacts().GetData();
In Main.xaml
<phone:LongListSelector x:Name="llsContacts" ItemsSource="{Binding}" >
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<ListBoxItem local:TiltEffect.IsTiltEnabled="true">
<Grid Margin="0" >
<TextBlock Text="{Binding NAME}" FontFamily="Segoe WP" FontSize="28" Margin="77,0,0,0" />
<TextBlock Text="{Binding NUMBER}" FontFamily="Segoe WP Light" FontSize="17" Margin="77,33,0,0"/>
</Grid>
</ListBoxItem>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>
I made a research on internet, and found about ObservableCollection, and I want to use it. I read this article http://www.codeproject.com/Articles/80555/Databinding-in-Silverlight-applications#_Toc261149245 to understand how it works, but I still have some doubts.
On this article, was created an Employee that inherits from INotifyPropertyChanged, and an Emplyees that inherits from ObservableCollection.
In my case, I want that my list (on xaml) always shows what is in database.
Is OK inheriting my UserContacts from INotifyPropertyChanged? Because this class declares a Table...
And should my DAOClass inherits from ObservableCollection? Or just my GetData() returns a ObservableCollection instead of a List?
Another thing.. there is a button that, when the user press, updates the database (search all the contacts on device, and remove from database what had been removed in phone, and add to database what had been add in phone).
Using ObservableCollection, when the search for contacts finishes, and my database is updated, should I call something to update the LongListSelector on xaml? Or after the database update, the LongListSelector is automatically updated too?
Thanks...
User viewmodel for assigning data context and assign observable collection at xaml side as binding.And viewmodel should have observable collection which you use for binding.Then if you made any changes for the collection automatically updates the longlistselector.
Every time you should change the collection according to your database changes.

Selection Changed Event is Rising when I clicked on Click Event handler

Sorry for the silly question.I even did not understand what should be given as title to this question.
I have 3 buttons and when I click them listboxes should be displayed.
And if I select an item in listbox it should be navigated and start playing.
When I click a button listbox is displaying and when an item is selected it is navigating to to other page and playing.After performing selection changed if I click any button I was getting error like
A first chance exception of type 'System.NullReferenceException' occurred in tori.dll
An unhandled exception of type 'System.NullReferenceException' occurred in tori.dll
Archieves .xaml:
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,-951,0">
<Button Name="btn1" Click="btn1_Click" Content="Daily" HorizontalAlignment="Left" Margin="0,88,0,0" VerticalAlignment="Top" Width="127" Height="72"/>
<Button Name="btn2" Click="btn2_Click" Content="Weekly" HorizontalAlignment="Left" Margin="132,88,0,0" VerticalAlignment="Top" Height="72" Width="140"/>
<Button Name="btn3" Click="btn3_Click" Content="CurrentMonth" HorizontalAlignment="Left" Margin="277,88,0,0" VerticalAlignment="Top" Height="72" Width="169"/>
<ListBox x:Name="itemsList" Margin="0,225,945,0"
SelectionChanged="itemsList_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Height="130">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image delay:LowProfileImageLoader.UriSource="{Binding ThumbnailUrl}"
Grid.Column="0"
Width="500"
Height="125"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Margin="6"/>
<StackPanel Margin="10,20,0,0"
Grid.Column="1"
Height="60"
Orientation="Horizontal"
VerticalAlignment="Center">
<TextBlock Text="{Binding title}"
FontSize="40" />
</StackPanel>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
Archieves.xaml.cs:
namespace tori
{
public partial class Archieves : PhoneApplicationPage
{
public Archieves()
{
InitializeComponent();
}
private void btn1_Click(object sender, RoutedEventArgs e)
{
WebClient downloader = new WebClient();
Uri uri = new Uri(" http://www.toucheradio.com/RSSFeed/rssDaily.php ", UriKind.Absolute);
downloader.DownloadStringCompleted += new DownloadStringCompletedEventHandler(ChannelDownloaded);
downloader.DownloadStringAsync(uri);
}
void ChannelDownloaded(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Result == null || e.Error != null)
{
MessageBox.Show("There was an error downloading the XML-file!");
}
else
{
// Deserialize if download succeeds
XDocument document = XDocument.Parse(e.Result);
var queue = from item in document.Descendants("item")
select new Item
{
title = item.Element("title").Value
,
link = item.Element("link").Value
,
pubDate = item.Element("pubDate").Value
,
ThumbnailUrl = item.Element(item.GetNamespaceOfPrefix("media") + "thumbnail").Attribute("url").Value
,
};
itemsList.ItemsSource = queue;
}
}
private void btn2_Click(object sender, RoutedEventArgs e)
{
WebClient downloader = new WebClient();
Uri uri = new Uri(" http://www.toucheradio.com/RSSFeed/rssWeekly.php ", UriKind.Absolute);
downloader.DownloadStringCompleted += new DownloadStringCompletedEventHandler(Channel1Downloaded);
downloader.DownloadStringAsync(uri);
}
void Channel1Downloaded(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Result == null || e.Error != null)
{
MessageBox.Show("There was an error downloading the XML-file!");
}
else
{
// Deserialize if download succeeds
XDocument document = XDocument.Parse(e.Result);
var queue = from item in document.Descendants("item")
select new Item
{
title = item.Element("title").Value
,
link = item.Element("link").Value
,
pubDate = item.Element("pubDate").Value
,
ThumbnailUrl = item.Element(item.GetNamespaceOfPrefix("media") + "thumbnail").Attribute("url").Value
,
};
itemsList.ItemsSource = queue;
}
}
private void btn3_Click(object sender, RoutedEventArgs e)
{
WebClient downloader = new WebClient();
Uri uri = new Uri("http://www.toucheradio.com/RSSFeed/rssMonthly.php ", UriKind.Absolute);
downloader.DownloadStringCompleted += new DownloadStringCompletedEventHandler(Channel2Downloaded);
downloader.DownloadStringAsync(uri);
}
void Channel2Downloaded(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Result == null || e.Error != null)
{
MessageBox.Show("There was an error downloading the XML-file!");
}
else
{
// Deserialize if download succeeds
XDocument document = XDocument.Parse(e.Result);
var queue = from item in document.Descendants("item")
select new Item
{
title = item.Element("title").Value
,
link = item.Element("link").Value
,
pubDate = item.Element("pubDate").Value
,
ThumbnailUrl = item.Element(item.GetNamespaceOfPrefix("media") + "thumbnail").Attribute("url").Value
,
};
itemsList.ItemsSource = queue;
}
}
private void itemsList_SelectionChanged(Object sender, SelectionChangedEventArgs e)
{
var app = App.Current as App;
app.selectedItem = (Item)itemsList.SelectedItem;
this.NavigationService.Navigate(new Uri("/Details.xaml", UriKind.Relative));
}
Item.cs:
namespace tori
{
public class Item
{
public string title { get; set; }
public string ThumbnailUrl { get; set; }
public string link { get; set; }
public string pubDate { get; set; }
}
}
Details.xaml:
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<Grid Height="617" VerticalAlignment="Top" Margin="-27,96,0,0">
<Image x:Name="ThumbnailUrl"
Width="279"
Height="421"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Margin="0,-29,204,225" />
<Image x:Name="Image1" Tap="Image1_Tap" Margin="46,430,354,92" Source="/Images/pausebutton.png"/>
<TextBlock x:Name="title" FontSize="30" TextWrapping="Wrap" Margin="284,57,-50,436" />
<TextBlock x:Name="pubDate" FontSize="25" Margin="284,186,10,363" />
<MediaElement x:Name="MediaElement1" AutoPlay="True" Margin="0,397,20,0" Height="94" VerticalAlignment="Top" />
Details.xaml.cs:
namespace tori
{
public partial class Details : PhoneApplicationPage
{
Item item;
public Details()
{
InitializeComponent();
var app = App.Current as App;
item = app.selectedItem;
title.Text = item.title;
pubDate.Text = item.pubDate;
ThumbnailUrl.Source = new BitmapImage(new Uri(item.ThumbnailUrl, UriKind.RelativeOrAbsolute));
string s = item.link;
string url = s.Replace("archivesplayer", "hostArchivesURLForMobile");
WebClient downloader = new WebClient();
Uri uri = new Uri(url,UriKind.Absolute);
downloader.DownloadStringCompleted += new DownloadStringCompletedEventHandler(Channel3Downloaded);
downloader.DownloadStringAsync(uri);
}
void Channel3Downloaded(object sender, DownloadStringCompletedEventArgs e)
{
var textData = (string)e.Result;
Regex urlRegex = new Regex("<td height=\"25\" align=\"center\">(?<url>.*)</td>");
MatchCollection mc = urlRegex.Matches(textData);
string url = "";
if (mc.Count > 0)
{
url = mc[0].Groups["url"].Value;
MediaElement1.Source = new Uri(url, UriKind.Absolute);
MediaElement1.Play();
}
}
}
}
After performing selecting item if I click a button I was getting error in this line
title.Text = item.title;
Can anybody please tell me how can I overcome this null exception.When I click on a button selection changed event is raising instead of click event. I am unable to know the reason for this.
Please anybody help me with this.
many Thanks in advance.
When you change the ItemsSource, the SelectionChanged event is raised. I think whenever you change the ItemsSource, the selection is reset (that is - set to null (none selected)). And that's how it should be, otherwise an item that's not in the ItemsSource could be the SelectedItem which is just wrong.
Now, to fix your issue, just check if SelectedItem != null in itemsList_SelectionChanged method.
Something else about your code: the methods btn1_Click, btn2_Click and btn3_Click seem to only have minor differences, so you could put most of the code in one method and just pass it the url. That's even more important for the ChannelDownloaded methods (as they are much longer). Basically you want to reuse code as much as possible. That makes the code easier to read (as it's not 10 pages, but one, so to speak), and easier to maintain (if there's an error - you only need to fix it in one place).

Parsing rss feed using xml serializer

Can anybody please tell me how can I parse this Url
http://bitcast-r.v1.sjc1.bitgravity.com/objectinfo/MIB/radio/inbradio_play.xml
such that all items in feed except the first item should be displayed in listbox.I am unable to understand how to parse omiting the first item.
This is the code I was using for parsing.But in this case I was getting all items of a feed.
But I need not get first item (i.e) torilive.How can I parse such that I should not get first item
MainPage.xaml.cs:
public MainPage()
{
InitializeComponent();
// is there network connection available
if (!System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable())
{
MessageBox.Show("No network connection available!");
return;
}
// start loading XML-data
WebClient downloader = new WebClient();
Uri uri = new Uri("http://bitcast-r.v1.sjc1.bitgravity.com/objectinfo/MIB/radio/inbradio_play.xml", UriKind.Absolute);
downloader.DownloadStringCompleted += new DownloadStringCompletedEventHandler(ChannelDownloaded);
downloader.DownloadStringAsync(uri);
}
void ChannelDownloaded(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Result == null || e.Error != null)
{
MessageBox.Show("There was an error downloading the XML-file!");
}
else
{
// Deserialize if download succeeds
XmlSerializer serializer = new XmlSerializer(typeof(Channel));
XDocument document = XDocument.Parse(e.Result);
Channel channel = (Channel)serializer.Deserialize(document.CreateReader());
listBox.ItemsSource = channel.Collection;
}
}
Channel.cs:
namespace Sample
{
[XmlRoot("rss")]
public class Channel
{
[XmlArray("channel")]
XmlArrayItem("item")]
public ObservableCollection<Items> Collection { get; set; }
}
}
Items.cs:
namespace Sample
{
public class Items
{
[XmlElement("title")]
public string title { get; set; }
[XmlElement("link")]
public string link { get; set; }
[XmlElement("image")]
public string image { get; set; }
}
}
Hope anybody helps.Many Thanks in advance.
Nice program :)
C#
void ChannelDownloaded(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Result == null || e.Error != null)
{
MessageBox.Show("There was an error downloading the XML-file!");
}
else
{
// Deserialize if download succeeds
XmlSerializer serializer = new XmlSerializer(typeof(Channel));
XDocument document = XDocument.Parse(e.Result);
Channel channel = (Channel)serializer.Deserialize(document.CreateReader());
// remove the first item
if (channel.Collection.Count > 0)
channel.Collection.RemoveAt(0);
this.myListBox.ItemsSource = channel.Collection;
}
}
XAML
<ListBox x:Name="myListBox">
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderThickness="0,0,0,1" BorderBrush="Red">
<StackPanel>
<TextBlock Text="{Binding title}"></TextBlock>
<TextBlock Text="{Binding link}" Width="350"></TextBlock>
<Image Source="{Binding image}" Width="50" Height="50" HorizontalAlignment="Left" VerticalAlignment="Top"></Image>
</StackPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Code In Action:
You can modify the template to get your desired results.

How to create a dictionary with multiple columns

I am working on a Windows Phone 8 app and I have some data that I need to work with. I am reading the data from a website and I have basically 4 pieces of information coming in from the website. I need to be able to do some parsing and filtering on this data before displaying it so I would like to add it to some sort of array/collection/dictionary.
Before with a C# WinForms app, I would just create a DataTable in memory that had 4 columns and just add a row for each entry. I don't think I can use DataTables with Windows Phone so I am wondering what other ways I can store this information in memory. The app doesn't store any information so I have no real need to use IsolatedStorage for any of this.
Is there some sort of Dictionary/Collection that I can use that will do something similar to a DataTable? In that it will let me store 4 pieces of information per entry?
Thanks!
If you need something simple, you could create a class which will hold the data:
public class DataFromWebSite
{
public string Name { get; set; }
public int Age { get; set; }
public string Country { get; set; }
public string Telephone { get; set; }
}
In the example above, I've used a strongly-typed class where each property could hold an exact value/data-type. So, Age is an integer rather than being a string for example.
Then, I'd create a collection object to hold the values:
var list = new ObservableCollection<DataFromWebSite>();
// add items to the list...
list.Add(new DataFromWebSite
{
Name = "John",
Age = 42,
Country = "Antartica",
Telephone = "941223445"
});
list.Add(new DataFromWebSite
{
Name = "Carrol",
Age = 24,
Country = "Atlantis",
Telephone = "100223445"
});
ObservableCollections work well with UIs where the list may change over time. For example, a ListBox bound to an ObservableCollection will show changes to the list when items are added or removed (but it won't show changes to the properties such as Age without implementing INotifyPropertyChange).
Then, using some of the LINQ extensions, you can do simple/readable queries:
var greaterThan30 = list.Where(d => d.Age > 30);
foreach (var item in greaterThan30)
{
Debug.WriteLine("{0}-{1}", item.Name, item.Age);
}
The above would produce a list that has only objects where the Age property is greater than 30.
Or you could use LINQ:
var greaterThan30 = from d in list
where d.Age > 30
select d;
If one of the values being returned was unique (for example an ID):
public class DataFromWebSite
{
public string Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public string Telephone { get; set; }
}
You could store the list as a Dictionary<string, DataFromWebSite>:
var keyed = new Dictionary<string, DataFromWebSite>();
var d = new DataFromWebSite
{
Id = "ABC123-A";
Name = "John",
Age = 42,
Telephone = "941223445"
};
keyed.Add(d.Id, d);
// to get a value back:
if (keyed.ContainsKey("ABC123-A")) {
var d2 = keyed["ABC123-A"];
}
And, if you wanted to get the list from the Dictionary:
var list = keyed.Values.ToArray();
This is a bit of an open-ended questions for XAML (as you're really asking how use collection controls and how to do binding).
Basically, any collection would do, then use a control to bind to the various properties of elements in that collection. You could use a ListBox control, bind it to the collection, then declare an ItemTemplate within it to bind to the various properties within the elements in the collection.
<ListBox ItemsSource="{Binding Customers}" Margin="0,5,0,10">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" >
<TextBlock Padding="3,0,3,0"
Text="{Binding FirstName}" FontSize="{StaticResource PhoneFontSizeSmall}"/>
<TextBlock Text="{Binding LastName}" FontSize="{StaticResource PhoneFontSizeSmall}"/>
<TextBlock Text=", " FontSize="{StaticResource PhoneFontSizeSmall}"/>
<TextBlock Text="{Binding Address}" FontSize="{StaticResource PhoneFontSizeSmall}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
And you'd set the DataContext of the page (or name the ListBox and set its DataContext) to an object that has property named Customers which is the collection you want to view in a list box e.g.:
public MyPage()
{
//...
DataContext = this;
}
public List<Customer> Customers {get;set;}
I've ignored INotifyPropertyChanged, I'll leave that as an exercise to the reader.

Binding a Dictionary to a WinRT ListBox

I've read a number of posts on binding Dictionary to WPF ListView and ListBox but I can't get equivalent code to work in WinRT.
<Grid Margin="10" Width="1000" VerticalAlignment="Stretch">
<ListBox Name="StatListView" ItemsSource="{Binding FooDictionary}" >
<ListBox.ItemTemplate>
<DataTemplate >
<Grid Margin="6">
<StackPanel Orientation="Horizontal" >
<TextBlock Text="{Binding Key}" Margin="5" />
<TextBlock Text="{Binding Value}" Margin="5" />
</StackPanel>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
public Dictionary<string, string> FooDictionary
{
get
{
Dictionary<string, string> temp = new Dictionary<string, string>();
temp.Add("key1", "value1");
temp.Add("key2", "value2");
temp.Add("key3", "value3");
temp.Add("key4", "value4");
return temp;
}
}
What is the proper binding?
The error in the output window is (trimmed to the most useful part):
Error: Cannot get 'Key' value (type 'String') from type
'System.Runtime.InteropServices.WindowsRuntime.CLRIKeyValuePairImpl`2
[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=4.0.0.0,
Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, ....
Internally, WinRT is converting the type to:
System.Runtime.InteropServices.WindowsRuntime.CLRIKeyValuePairImpl<K, V>
If you add to your DataTemplate:
<TextBlock Text="{Binding}" Margin="5" />
You'll see that it emits the above type with String, String.
However, for some reason, it's not being properly handled as expected. If you search for that type on the Internet, you'll see that there's a documented bug for the issue on Connect.
A simple work around would be to place your data in a simple object that is not a KeyValuePair:
List<StringKeyValue> temp = new List<StringKeyValue>();
temp.Add(new StringKeyValue { Key = "key1", Value = "value1" } );
temp.Add(new StringKeyValue { Key = "key2", Value = "value2" });
temp.Add(new StringKeyValue { Key = "key3", Value = "value3" });
temp.Add(new StringKeyValue { Key = "key4", Value = "value4" });
this.DefaultViewModel["FooDictionary"] = temp;
public class StringKeyValue
{
public string Key { get; set; }
public string Value { get; set; }
}
As an aside, from a simple test at least, it's not the Dictionary that's causing the issue at all, it's the fact that it's a KeyValuePair object instance that's being converted to the CLRIKeyValuePairImpl type mentioned above. I tried just using a list and adding a KeyValuePair<string, string> instance to a List, and that failed as well.
I've come up with a workaround, that involves generating your own Key Value pairs dynamically.
If you've specialized Dictionary, just add this:
public IEnumerable<MyPair<K, V>> Collection
{
get {
foreach (var v in this)
{
MyPair<K, V> p = new MyPair<K, V>() { Key = v.Key, Value = v.Value };
yield return p;
}
}
}
and define your Pair type:
public class MyPair<K, V>
{
public K Key { get; set; }
public V Value { get; set; }
}
Also, be careful that you create a new object each time. Some items walk across the object, and store the return, which can lead to everything looking like the last item, if you try to reuse the MyPair like I originally did.