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 を参照しようとすると、null のように見えます。 全景写真

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")ただし、まだ null であることがわかるため、シリーズを見つけることができなかったと結論付けることができます。問題は、なぜ失敗したのかということです。

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の場合はコレクションパラメータをContentPropertyAttribute指定します。Seriesこれにより、より自然な Xaml が可能になります。

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

ただしChart、最終的な UI を表す「オブジェクト ツリー」に正確に何を含めるかを決定するために多くの余分な作業があるため、シリーズ コレクション アイテムはすぐに「オブジェクト ツリー」の一部にはなりません。その結果、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");
    }
  }
}
于 2010-05-03T10:28:10.963 に答える