Набор инструментов Silverlight 4, построение графиков и линейных серий равен нулю - PullRequest
4 голосов
/ 02 мая 2010

Я создаю диаграмму Silverlight, используя набор инструментов Silverlight 4, апрельский выпуск.

Рассмотрим следующую таблицу:

 <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, она кажется пустой картинка http://i41.tinypic.com/9k4h7t.png Полный просмотр

1 Ответ

6 голосов
/ 03 мая 2010

Это интересный маленький гоча. Помогает, если вы немного загляните за пределы того, как переменная 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 в классах, что позволяет более естественно описать структуру пользовательского интерфейса. E.g.:-

<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 требует много дополнительной работы, чтобы определить, что именно должно быть в «дереве объектов», которое будет представлять его окончательный интерфейс, элементы коллекции серии не сразу становятся частью «дерева объектов». , В результате FindName в InitializeComponent просто не находит их.

Работа вокруг - Вариант 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");
    }
  }
}
...