绑定到从XML填充的ObservableCollection不起作用

时间:2016-11-30 11:26:48

标签: c# xaml uwp

使用Blend。

我正在尝试将GridView或TextBlock绑定到Observable集合。可观察集合从XML文件中获取其数据。我的测试程序运行,但当我按下“显示句子”按钮时,GridView或TextBlock中没有数据显示。

我的XML文件:

(从一个在Visual Studio控制台项目中正常运行的大型复杂文件中模拟)

<Book ISBN ="9144252184178">
  <Title>
    <TitleLine>Title First Line</TitleLine>
    <TitleLine>Title Second Line</TitleLine>
  </Title>
  <Authors>
    <Author>Some Body</Author>
    <Author>No Body</Author>
  </Authors>
  <Pages>
    <Page PageNumber ="1">
      <Sentences>
        <Sentence SentenceID = "1">
          <SentenceText>Once there was a giant </SentenceText>
          <SentenceFileName>9144252184178.1.1</SentenceFileName>
          <SentenceWords>
            <SentenceWord Start = "" Part = "">once</SentenceWord>
            <SentenceWord Start = "" Part = "">there</SentenceWord>
            <SentenceWord Start = "" Part = "">was</SentenceWord>
            <SentenceWord Start = "" Part = "">a</SentenceWord>
            <SentenceWord Start = "" Part = "">giant</SentenceWord>
          </SentenceWords>
        </Sentence>
        <Sentence SentenceID = "2">
          <SentenceText>Every day, etc</SentenceText>
          <SentenceFileName>9144252184178.1.2</SentenceFileName>
          <SentenceWords>
            <SentenceWord Start = "" Part = "">every</SentenceWord>
            <SentenceWord Start = "" Part = "">day</SentenceWord>
            <SentenceWord Start = "" Part = "">etc</SentenceWord>
          </SentenceWords>
        </Sentence>
      </Sentences>
    </Page>
  </Pages>
</Book>

MainPage.xaml中:

(显示我试图绑定到ObservableCollection失败的几种方法)

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
  <StackPanel>
    <Button x:Name="button" Content="Show Sentence" Click="button_Click"/>
    <GridView Background="Bisque" ItemsSource="{x:Bind ThisSentence}">
      <GridView.ItemTemplate>
        <DataTemplate x:DataType="data:Sentences">
          <StackPanel Background="AliceBlue">
            <TextBlock Text="Sentence"/>
            <TextBlock Text="{x:Bind SentenceID}"/>
            <TextBlock Text="{x:Bind SentenceText}"/>
           </StackPanel>
         </DataTemplate>
      </GridView.ItemTemplate>
    </GridView>
    <Border Background="LightBlue">
      <TextBlock Text="{Binding ThisSentence.SentenceID, Mode=OneWay}"/>
    </Border>
  </StackPanel>
</Grid>  

MainPage.xaml.cs中:

namespace ImportFromXML
{
    public sealed partial class MainPage : Page
    {
        private ObservableCollection<Book> thisSentence_;
        public ObservableCollection<Book> ThisSentence
        {
            get { return thisSentence_; }
            set { thisSentence_ = value; }
        }

        public MainPage()
        {
            this.InitializeComponent();
        }

        private void button_Click(object sender, RoutedEventArgs e)
        {
           var newTask = Task.Run(() => thisSentence_ = SentenceManager.GetSentence("0","0")) ;
           DataContext = ThisSentence;
        }
    }
}

Book.cs:

(这是我的类和我的SentenceManager。在VS Console项目中运行时,SentenceManager Linq代码对我的XML起作用。)

public class Book
{
    public string ISBN { get; set; }
    public IList<Title> title = new List<Title>();
    public IList<Authors> authors = new List<Authors>();
    public IList<Pages> pages = new List<Pages>();
}

public class Title
{
    public string TitleLine { get; set; }
}

public class Authors
{
    public string AuthorName { get; set; }
}

public class Pages
{
    public string PageNumber { get; set; }
    public IList<Sentences> sentences = new List<Sentences>();
    public IList<Contents> contents = new List<Contents>();
 }

public class Sentences
{
    public string SentenceID { get; set; }
    public string SentenceText { get; set; }
    public string SentenceFileName { get; set; }
    public IList<SentenceWords> sentenceWords = new List SentenceWords>();
}

public class SentenceWords
{
    public string SentenceWord { get; set; }
    public string Ending { get; set; }
    public string Parent { get; set; }
}


public class SentenceManager
{
    public static ObservableCollection<Book> GetSentence(string pageNumber, string sentenceID)
    {

        XDocument xdoc = XDocument.Load(@"C:\Users\Richard\Documents\ImportFromXML\book.xml");
        List<Book> sentence = (from bk in xdoc.Elements("Book")
                               select new Book
                               {
                                 pages = (from pag in bk.Element("Pages").Elements("Page")
                                          where (string)pag.Attribute("PageNumber") == pageNumber
                                          select new Pages
                                           {
                                             sentences = (from sen in pag.Element("Sentences").Elements("Sentence")
                                                          where (string)sen.Attribute("SentenceID") == sentenceID
                                                          select new Sentences
                                                          {
                                                            SentenceID = sen.Attribute("SentenceID").Value,
                                                            SentenceText = sen.Element("SentenceText").Value,
                                                            SentenceFileName = sen.Element("SentenceFileName").Value,
                                                          }).ToList(),
                                            }).ToList(),
                               }).ToList();

        ObservableCollection <Book> Sentence = new ObservableCollection<Book>(sentence);
        return Sentence;
    }
}

在我的程序中,我必须将许多控件绑定到我的xml数据的各个部分,所以这只是一个例子。

我是一个新手,所以请不要让你的建议太神秘,否则我可能不理解!感谢你给与我的帮助。

1 个答案:

答案 0 :(得分:0)

首先,当您通过ThisSentence绑定x:Bind属性时

ItemsSource="{x:Bind ThisSentence}"

根本没有必要设置DataContext

但是,绑定模式必须设置为OneWay,因为默认值为OneTime

ItemsSource="{x:Bind ThisSentence, Mode=OneWay}"

此外,酒店必须通知价值变化。在从DependencyObject派生的类中,通常通过使其成为依赖属性来完成:

public static readonly DependencyProperty ThisSentenceProperty =
    DependencyProperty.Register(
        "ThisSentence",
        typeof(MainPage),
        typeof(ObservableCollection<Book>),
        new PropertyMetadata(null));

public ObservableCollection<Book> ThisSentence
{
    get { return (ObservableCollection<Book>)GetValue(ThisSentenceProperty); }
    set { SetValue(ThisSentenceProperty, value); }
}

您还应该等待Click处理程序中的Task。

private async void button_Click(object sender, RoutedEventArgs e)
{
    ThisSentence = await Task.Run(() => SentenceManager.GetSentence("0", "0"));
}

请注意,事件处理程序是规则的例外,不应该是任何async void方法。

如果您想使用Binding而不是x:Bind,您应该在Page的构造函数中设置一次DataContext,例如

public MainPage()
{
    InitializeComponent();
    DataContext = this;
}

现在你也可以写

ItemsSource="{Binding ThisSentence}"