【问题标题】:Silverlight 4 toolkit, charting and lineSeries is nullSilverlight 4 工具包、图表和 lineSeries 为空
【发布时间】:2011-02-14 18:19:19
【问题描述】:

我使用 4 月发布的 Silverlight 4 工具包创建了一个 Silverlight 图表。

考虑下面的图表:

 <Grid x:Name="LayoutRoot" Background="White">
  <Charting:Chart Title="Chart to test" Name="MySuperChart">
   <Charting:LineSeries x:Name="MyLineSeries" Title="Something" />
  </Charting:Chart>
 </Grid>

到目前为止一切顺利。我可以通过MySuperChart.Series[0] 访问图表中的系列,但是当我尝试引用 MyLineSeries 时,它似乎为空。 Full view

【问题讨论】:

    标签: silverlight charts silverlight-toolkit


    【解决方案1】:

    这是一个有趣的小问题。如果您深入了解变量MyLineSeries 的创建和分配方式,将会有所帮助。导航到InitializeComponent 方法的定义。您最终会看到 MainPage.g.cs 生成的文件。它将包含此字段:-

    internal System.Windows.Controls.DataVisualization.Charting.LineSeries MyLineSeries;
    

    InitializeComponent 中你会发现这一行:-

    this.MyLineSeries = ((System.Windows.Controls.DataVisualization.Charting.LineSeries)(this.FindName("MyLineSeries")));
    

    所以表面上看,当你的构造函数中对InitializeComponent 的调用完成时,MyLineSeries 应该已经被赋值了。但是,您可以看到它仍然为空,因此可以得出结论,FindName("MyLineSeries") 未能找到该系列。那么问题来了,为什么会失败?

    为什么 FindName 不起作用?

    FindName 搜索文档中称为“对象树”的内容,寻找具有指定名称的对象(所谓的名称范围会增加复杂性,但在这里没有发挥作用)。通常,对象通过常见的基本类型(如PanelContentControl)最终进入“对象树”,这些基本类型分别具有ChildrenChild 等属性。这些属性在类的ContentProperty 属性中指定,从而可以更自然地描述 UI 结构。例如:-

    <Button x:Name="MyButton">
      <Image x:Name="MyImage" ... />
    </Button>
    

    代替

    <Button x:Name="MyButton">
      <Button.Child>
        <Image x:Name="MyImage" ... />
      </Button.Child>
    </Button>
    

    另一方面,Chart 控件不是简单的Panel 派生类,在构建其 UI 方面还有很多工作要做。对于ChartContentPropertyAttribute 指定Series 集合参数。这允许您更自然的 Xaml:-

    <Charting:Chart Title="Chart to test" Name="MySuperChart">
      <Charting:LineSeries x:Name="MyLineSeries" Title="Something" />
    </Charting:Chart>
    

    但是,因为Chart 有很多额外的工作来确定“对象树”中究竟应该是什么来代表其最终 UI,所以系列集合项目不会立即成为“对象树”的一部分.结果InitializeComponent 中的FindName 根本找不到它们。

    解决方法 - 选项 1

    您可以使用您对图表中“MyLineSeries”序数位置的了解来处理构造函数中MyLineSeries 变量的分配。从 Xaml 中删除 x:Name="MyLineSeries" 然后在代码中:-

    public partial MainPage : UserControl
    {
      private LineSeries MyLineSeries;
    
      public MainPage()
      {
        InitializeComponent();
        MyLineSeries = (LineSeries)MySuperChart.Series[0];
      }
    }
    

    解决方法 - 选项 2

    您可以等到该系列在“对象树”中可用,一旦包含的UserControl 触发了它的Loaded 事件,这是真的:-

    public partial MainPage : UserControl
    {
      public MainPage()
      {
        InitializeComponent();
        Loaded += (s, args) =>
        {
          MyLineSeries = (LineSeries)FindName("MyLineSeries");
        }
      }
    }
    

    【讨论】:

    • 所以你说这是一种错误?他们不解析 x:Name?
    • @Snake: x:Name 确实被解析了,但是自动生成的代码部分假设在执行 InitializeComponent 时可以在“对象树”中找到该元素.我不确定我是否会将其归类为错误。
    • @AnyhonyWJones:实际上您的解决方法 2 不起作用。它没有找到名称。
    • @Snake:我的错,你说得对。我是根据 SL3 和 Nov09 工具包的经验编写的。我刚刚在 SL4 中使用 April09 工具包进行了相同的测试,第二个选项不再有效。这很烦人。 :(
    • 是的。虽然我可以使用第一个修复程序,但我不喜欢它。不过谢谢!
    猜你喜欢
    • 1970-01-01
    • 2011-09-20
    • 1970-01-01
    • 2013-03-16
    • 1970-01-01
    • 2014-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多