2014-03-03 85 views
0

我已阅读多个答案,但根本无法得到任何解决我的问题。我有一个从Web请求中接收XML的程序,在该请求中我只抓取该XML中的特定属性。在逐步浏览时,我可以看到一切正常,检索获取正确的XML,排序并获取正确的标记作品,然后将每个标记的内容分配给其在另一个类中的相关变量。另外,当逐步完成时,“gridInfo”显示一个列表,将显示我想要显示的每个值。绑定ObservableCollection列表

我无法工作的是将列表绑定到DataGrid。正如你所看到的,我创建了一个新的ObserableCollection类,其中存储了每个变量并调用该对象。我创建了该类的列表,并将XML中的值存储到该列表中。任何人都可以帮忙吗?

也在寻找我读了你会发现它不是在这里的一切都包含在它自己开始和结束标记内的正常格式的XML时,这就是为什么我不得不使用DocumentElement还有的getElementsByTagName

代码背后:

// This action will seach the IMDb API for the associated infromation for the IMDBID that is tagged with the title you chose in the ListBox. 
    private void Movie_List_SelectionChanged(object sender, SelectionChangedEventArgs e) 
    { // Grabs the IMDBID associated to the movie title selected to be used with the second API request. 
     var p = Movie_List.SelectedIndex; 

     string titleID = structholder[p].IMDBID; 
     string newurl = "http://www.omdbapi.com/?i=" + titleID + "&r=XML"; 

     // Prepares 2nd API URL request to get data for chosen title. 
     // Creates a XML Document to store the xml data that was sent back by the API. 
     XmlDocument doc = new XmlDocument(); 
     doc.Load(newurl); 

     // Creates a XML Noedlist to store the values that are going to be associated with the given attribute tag. 
     XmlNodeList movieList = doc.DocumentElement.GetElementsByTagName("movie");// GetElementsByTagName("root"); 


     ObservableCollection<Retrievalinfo> test = new  ObservableCollection<Retrievalinfo>(); 

     List<Retrievalinfo> gridInfo = new List<Retrievalinfo>(); 
     foreach (XmlNode node in movieList) 
     { 
      gridInfo.Add(new Retrievalinfo(){ 
      title = node.Attributes["title"].Value.ToString(), 
      actors = node.Attributes["actors"].Value.Split(',').ToList(), 
      genre = node.Attributes["genre"].Value.ToString(), 
      rated = node.Attributes["rated"].Value.ToString(), 
      imdbRating = node.Attributes["imdbRating"].Value.ToString(), 
      released = node.Attributes["released"].Value.ToString(), 
      runtime = node.Attributes["runtime"].Value.ToString(), 
     }); 
     } 

     Movie_DataGrid.ItemsSource = Retrievalinfo; 

    } 

Retrivealinfo类别:

namespace WpfApplication3 
{ 
    public class Retrievalinfo 
{ 

    public Retrievalinfo() 
    { 
     actors = new List<string>(); 
    } 

    //Creating a list of info objects that will store all returned data for selected title. 
    public string title { get; set; } 
    public List<string> actors { get; set; } 
    public string genre { get; set; } 
    public string rated { get; set; } 
    public string imdbRating { get; set; } 
    public string released { get; set; } 
    public string runtime { get; set; } 
} 
} 

XAML:

<ListBox x:Name="Movie_List" ItemsSource="{Binding listInfo}" Grid.ColumnSpan="2" HorizontalAlignment="Left" Height="287" Margin="20,107,0,0" VerticalAlignment="Top" Width="198" SelectionChanged="Movie_List_SelectionChanged" /> 
     <Label Grid.ColumnSpan="2" Content="Movie List" HorizontalAlignment="Left" Height="30" Margin="70,72,0,0" VerticalAlignment="Top" Width="99" FontSize="16" FontFamily="Cooper Black" /> 
     <DataGrid x:Name="Movie_DataGrid" Grid.ColumnSpan="2" HorizontalAlignment="Left" Margin="232,107,0,0" VerticalAlignment="Top" Height="198" Width="497" AutoGenerateColumns="True" ItemsSource="{Binding gridInfo}"> 
     <DataGrid.Columns> 
      <DataGridTextColumn Header="Title" Binding="{Binding Path=title}"/> 
      <DataGridTextColumn Header="Main Actor 1" Binding="{Binding Path=actors[0]}"/> 
      <DataGridTextColumn Header="Main Actor 2" Binding="{Binding Path=actors[1]}"/> 
      <DataGridTextColumn Header="Main Actor 3" Binding="{Binding Path=actor[2]}"/> 
      <DataGridTextColumn Header="Genre" Binding="{Binding Path=genre}"/> 
      <DataGridTextColumn Header="Rated" Binding="{Binding Path=rated}"/> 
      <DataGridTextColumn Header="IMDB Rating" Binding="{Binding Path=imdbRating}"/> 
      <DataGridTextColumn Header="Released" Binding="{Binding Path=released}"/> 
      <DataGridTextColumn Header="Runtime" Binding="{Binding Path=runtime}"/> 
     </DataGrid.Columns> 
    </DataGrid> 

XML我读:

<root response="True"> 
<movie title="Up in the Air" year="2009" rated="R" released="23 Dec 2009" runtime="109 
min" genre="Drama, Romance" director="Jason Reitman" writer="Walter Kirn (novel), Jason 
Reitman (screenplay), Sheldon Turner (screenplay)" actors="George Clooney, Vera Farmiga, 
Anna Kendrick, Jason Bateman" plot="With a job that has him traveling around the country 
firing people, Ryan Bingham leads an empty life out of a suitcase, until his company 
does the unexpected: ground him." language="English" country="USA" awards="Nominated for 
6 Oscars. Another 64 wins & 66  nominations."poster="http://ia.mediaimdb.com/images/M/MV5BMTI3MzYxMTA4NF5BMl5BanBnXkFtZTcwMD 
[email protected]@._V1_SX300.jpg" metascore="83" imdbRating="7.5" imdbVotes="215,961" imdbID="tt1193138" type="movie"/> 
</root>  
+2

Movie_DataGrid.ItemsSource = Retrievalinfo; Retrievalinfo是一个类而不是一个集合。我感到惊讶的是编译。尝试Movie_DataGrid.ItemsSource = gridInfo; – Paparazzi

回答

1

首先,您提供的xml是完美形成的(元素没有结束标记的事实 - 是OK ...以/>(即:<bla attributeName='value' />)结尾的标记被认为是关闭的,并且不需要关闭标签

二 - 为什么不使用LINQ为xml ??它将使代码更简单,更具可读性。

// Prepares 2nd API URL request to get data for chosen title. 
    // Creates a XML Document to store the xml data that was sent back by the API. 
    var doc = XElement.Load(newurl); 

    // Creates a XML Noedlist to store the values that are going to be associated with the given attribute tag. 
    IEnumerable<XElement> movieList = doc.Descendants("movie"); 


    ObservableCollection<Retrievalinfo> gridInfo = new ObservableCollection<Retrievalinfo>(movieList.Select(movieElement => 
     new Retrievalinfo() 
     { 
      title = movieElement.Attribute("title").Value, 
      actors = movieElement.Attribute("actors").Value.Split(',').ToList(), 
      genre = movieElement.Attribute("genre").Value, 
      rated = movieElement.Attribute("rated").Value, 
      imdbRating = movieElement.Attribute("imdbRating").Value, 
      released = movieElement.Attribute("released").Value, 
      runtime = movieElement.Attribute("runtime").Value, 
     })); 

,最后 - 你误会了,为什么摆在首位使用的ObservableCollection 第一。 ,绑定数据 - 只需绑定列表本身。

Movie_DataGrid.ItemsSource = gridInfo; 

当你希望控件显示列表(任何添加,删除等)所做的任何改变,没有重新绑定它(这意味着完全重装吧),用户的ObservableCollection。否则,您可以使用任何顺序的项目(即,实现IEnumerable的任何类型)。

+0

您可以详细介绍linq到xml。这就是您正在使用的属性,如XElement,IEnumerable等。另外我想对xml说的是,在之前的问题和答案中,我看到大多数人使用保存到文件的xml,并希望所有信息存储在开始和结束标记之间,因此GetElementsByTagName适用于它们,但是不是我。 – user3280210

+0

也在您的ObserableCollection行中,movielist.Select ....不提供“movieElement”选项。此外,在序列“movieElement =>”之后没有关闭),除非“new Retrievalinfo()”与该行分开。你能够再次查看你的代码吗? – user3280210

+0

关于LINQ to xml - google it! 它比DOMXml更简单友好。 关于select - 你看到的是lambda表达式,这是一种编写匿名方法的方法。 匿名方法获取一个参数(movieElement,其类型由编译器推断为XElement),并返回新的RetrieveInfo(它确实是命令的一部分)。 –

0

首先的;

我不能去工作列表绑定到一个DataGrid

绑定到List是完全接受,而你可以做到这一点。但是,您必须管理您自己的PropertyChanged事件。这就是为什么我们有ObservableCollection类。当你将任何控件的ItemSource绑定到一个ObservableCollection时,视图会自动通知,当有东西变成它时(添加/删除/修改,不再实例化)。所以你应该使用ObservableCollection。

Secondo;

我看你宣布你gridInfo方法Movie_List_SelectionChanged这是不好的,因为XAML绑定机制会在你的DataContext物业搜索里面。 xaml在那里找不到gridInfo。声明在类这样你的财产在你的DataContext:

public ObservableCollection<Retrievalinfo> gridInfo { get; set; } 

不要忘了初始化它在你的DataContext的构造。另外不要忘记在你的xaml的代码背后声明你的DataContext。

最后,您已经在您的xaml(ItemsSource="{Binding gridInfo}")中声明了您的ItemSource,因此无需在您的代码中(Movie_DataGrid.ItemsSource = Retrievalinfo;)再次执行此操作。

- EDIT--
由于您的评论,我会尽力为您澄清一些事情。一个经典的设计将有3件事:

  • XAML文件,您的看法,在哪里以及如何显示您的信息。
  • 您将在其中声明您的DataContext的代码(.xaml.cs文件)。
  • 您的DataContext。这是.cs,您将拥有要在XAML中绑定的属性。

在你的情况。你有你的XAML,这是不完全正确的方式(你不能说绑定演员[0] ..你需要在你的数据网格内使用itemControl来生成这些列。我会建议尝试一些教程为了让你更好地理解WPF,你有很多简单的方法来提高你对WPF的理解。通常情况下,你应该只设置你的DataContext。像这样:

DataContext = new MyDataContext(); 

然后,最后,在你的DataContext,你应该有你绑定到你的XAML的属性的声明,并在构造函数实例化它们也可以调用方法来从获取您的infomartions。 y数据库(哪些方法也将在DataContext中。根据MVVM设计模式,视图不应该与模型进行通信)。

希望这对你有所帮助。

+0

你的意思是在我的Retreivalinfo类中存储变量的地方。你提到DataContext,这是否意味着我需要在XMAL中声明它? – user3280210

+0

编辑我的答案,请重新考虑阅读它,希望它会有所帮助。 –

+0

是的,我知道列表上的绑定关闭了,这就是我记得我有一个以上的价值。这也有帮助。但另一个问题。我的Retivealinfo类是否像DataContext一样工作?或没有? – user3280210

相关问题