4

我使用 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 时访问图表中的系列,它似乎为空。 全视图图片

4

1 回答 1

6

这是一个有趣的小问题。如果您稍微了解一下变量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搜索文档中称为“对象树”的内容,查找具有指定名称的对象(所谓的名称范围会增加复杂性,但此处不适用)。Panel通常,对象通过常见的基本类型(例如或ContentControl分别具有Children和等属性)最终进入“对象树” Child。这些属性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 还需要做很多工作。在指定集合参数Chart的情况下。这允许您更自然的 Xaml:-ContentPropertyAttributeSeries

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

然而,由于Chart需要做很多额外的工作才能确定“对象树”中将代表其最终 UI 的确切内容,因此系列集合项目不会立即成为“对象树”的一部分。结果根本找不到它们FindNameInitializeComponent

解决方法 - 选项 1

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

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");
    }
  }
}
于 2010-05-03T10:28:10.963 回答