这是一个有趣的小问题。如果您稍微深入了解变量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
派生类,需要更多的工作来构建其用户界面。在Chart
的情况下,ContentPropertyAttribute
指定了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");
}
}
}