问题
I've been trying to learn the ins-and-outs of Windows Phone 7 programming over the past few weeks. I have learned most of the basics but I've been having trouble finding a tutorial explaining exactly how to do something with XML. I want to create a very basic app which accesses an XML file at a web address and displays the various items within the file as text within the app. I've come across several tutorials which all seem to do it in a different way, or aren't explaining exactly the thing it is I want to do. I don't want to search the XML file, I don't want to update it, I just want to retrieve it's contents. Within the XML file are "items" and within those are categories like "title" and "description". I want the app to list all of the items and within each one display it's title and description.
To be more specific I know that I bind the contents to textblocks using {Binding Title} or {Binding Description}. I'm just not sure how to connect to the file using WebClient or whatever the easiest method is. I have no problem displaying the contents of an offline XML file that is already in my solution explorer.
I'm sure there is a very simple way to do this, and I really appreciate all of your help.
回答1:
ScottGu created an app which demonstrates what you need. (Code below is very similar as couldn't find link to source from his example.)
The app retrieves XML from a web service (in this case from Twitter.)
private void GetTweets()
{
WebClient twtr = new WebClient();
twtr.DownloadStringCompleted += new DownloadStringCompletedEventHandler(twitter_DownloadStringCompleted);
twtr.DownloadStringAsync(new Uri("http://search.twitter.com/search.atom?&q=searchterm"));
}
It then parses the XML into a collection of object.
void twitter_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error != null)
return;
XElement xmlTweets = XElement.Parse(e.Result);
var list = new List<TweetViewModel>();
foreach (XElement t in xmlTweets.Elements("{http://www.w3.org/2005/Atom}entry"))
{
var userName = t.Element("{http://www.w3.org/2005/Atom}author").Element("{http://www.w3.org/2005/Atom}name").Value.Split(' ')[0];
var message = t.Element("{http://www.w3.org/2005/Atom}title").Value;
var imageSource = (from t2 in t.Elements("{http://www.w3.org/2005/Atom}link")
where t2.Attribute("type").Value.Contains("image")
select t2.Attribute("href").Value).First();
list.Add(new TweetViewModel
{
UserName = userName,
Message = message,
ImageSource = imageSource
});
}
twitterList.ItemsSource = list;
}
public class TweetViewModel
{
public string UserName { get; set; }
public string Message { get; set; }
public string ImageSource { get; set; }
}
This is then bound to a list.
<ListBox HorizontalAlignment="Left" Name="twitterList" VerticalAlignment="Top" Width="476">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Height="132">
<Image Source="{Binding ImageSource}" Height="73" Width="73" VerticalAlignment="Top" Margin="0,10,8,0"/>
<StackPanel Width="370">
<TextBlock Text="{Binding UserName}" Foreground="#FFC8AB14" FontSize="28" />
<TextBlock Text="{Binding Message}" TextWrapping="Wrap" FontSize="24" />
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
It was written with the first CTP of the tools/SDK but hopefully it should still be simple enough to get this working.
回答2:
UPDATE:
I think you were right that the problem may be when I call GetRoster. This is the context in which I'm calling it:
'
namespace TwitterMix
{
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
InitializeComponent();
}
private void GetRoster()
{
WebClient rstr = new WebClient();
rstr.DownloadStringCompleted += new DownloadStringCompletedEventHandler(roster_DownloadStringCompleted);
rstr.DownloadStringAsync(new Uri("http://www.danfess.com/data.xml"));
}
'
What would be the correct place in which to call it? By the way I'm sorry about the code sections not appearing correctly.
Hey guys! Thanks for the help! I didn't create an account earlier so this is probably going to show up as an answer since I'm on a different computer. I did my best in changing that Twitter Tutorial into what I am trying to do. I'm getting no errors but it's not showing any content within the emulator. I created an XML file and uploaded it to my personal website. Unfortunately, I cannot get the code sample button to work even remotely well. So I'm sorry this looks so poorly. The XML file contained this info:
<?xml version="1.0" encoding="utf-8" ?>
<roster>
<person><name>Blake</name><age>25</age></person>
<person><name>Jane</name><age>29</age></person>
<person><name>Bryce</name><age>29</age></person>
<person><name>Colin</name><age>29</age></person>
</roster>
Here is MainPage.xaml.cs:
private void GetRoster()
{
WebClient rstr = new WebClient();
rstr.DownloadStringCompleted += new DownloadStringCompletedEventHandler(roster_DownloadStringCompleted);
rstr.DownloadStringAsync(new Uri("http://www.MyPersonalWebsiteURL.com/data.xml"));
}
void roster_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error != null)
return;
XElement xmlPersons = XElement.Parse(e.Result);
var list = new List<RosterViewModel>();
foreach (XElement person in xmlPersons.Elements("person"))
{
var name = person.Element("name").Value;
var age = person.Element("age").Value;
list.Add(new RosterViewModel
{
Name = name,
Age = age,
});
}
rosterList.ItemsSource = list;
}
public class RosterViewModel
{
public string Name { get; set; }
public string Age { get; set; }
}
}
Now MainPage.xaml:
'
<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!--TitlePanel contains the name of the application and page title-->
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock x:Name="ApplicationTitle" Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="page name" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<ListBox HorizontalAlignment="Left" Name="rosterList" ItemsSource="rosterList" VerticalAlignment="Top" Width="476">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Height="132">
<StackPanel Width="370">
<TextBlock Text="{Binding Name}" Foreground="#FFC8AB14" FontSize="28" />
<TextBlock Text="{Binding Age}" TextWrapping="Wrap" FontSize="24" />
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Grid>
'
However! When I run the app in the emulator I receive no errors, but no content is displayed whatsoever. I know the solution is probably very simple so I'd like to reiterate how much your help means to me. Thanks very much for any advice you can provide.
来源:https://stackoverflow.com/questions/4138694/connect-to-xml-file-at-web-address-for-wp7-app