[私の他の質問からの回答をここにコピーします。]
すごいソーセージ!私はそれを考え出した!
通常、Initializedイベントを受け取る (またはオーバーライド内にいるOnInitialized) 場合、XAML 設定のプロパティ値にアクセスできます。ただし、UI をハイドレートし、関連するメンバー変数を設定するために呼び出されるUserControlことに依存するため、クラスの動作は少し異なります。InitializeComponent
問題は、呼び出しがコンストラクター内にあることです。これにより、呼び出しが終了しOnInitialized(したがってInitializedイベントが発生します)、XAML セットのプロパティが適用される前に発生します。つまり、まだそれらにアクセスできないことを意味します。必要です。
Loadedこれらのプロパティに基づいて初期化を完了するために、イベントの良い使い方だと思うかもしれませんが、そこで追加の初期化を実行している場合、消費者がLoadedイベントにサブスクライブする場合に、消費者との潜在的な競合状態を作成しています。あなたの前にそれを取得し、ハンドラーであなたのコントロールにアクセスしようとすると、初期化されていないコントロールにアクセスします。
その後、何かが起こりました...上で示したようにInitializeComponent、コンストラクターから呼び出しを削除すると、Initializedイベントは期待どおりに機能しますが、まだ呼び出していないため、もちろん UI はまだハイドレートされていませんInitializeComponent。
OnInitializedでは、その呼び出しをオーバーライドの先頭、つまり への呼び出しのbase.OnInitialized前、つまりInitializedイベントが発生する前に移動するとどうなるでしょうか?
うん!それはうまくいきました!:)
Initializedこの方法では、XAML で設定されたプロパティを取得できるだけでなく、(イベントは言うまでもなく)誰かがイベントを取得する前に UI を完全に読み込むこともできますLoaded。これが、イベントのInitialized使用方法です。
以下は修正されたコードです...
public partial class TestControl : UserControl
{
protected override void OnInitialized(EventArgs e)
{
InitializeComponent();
base.OnInitialized(e);
}
public static readonly DependencyProperty TestValueProperty = DependencyProperty.Register(
"TestValue",
typeof(string),
typeof(TestControl),
new UIPropertyMetadata("Original Value"));
public string TestValue
{
get { return (string)GetValue(TestValueProperty); }
set { SetValue(TestValueProperty, value); }
}
}
- 注: そこで他のことを行う必要がある場合を除き、コンストラクターはもう必要ありません。その場合は、呼び出しの後まで名前で構成要素のコントロールにアクセスできないことを覚えておいてください
InitializeComponent。ただし、これは、そのような名前ベースの初期化をInitializeComponentとの間で移動することを計画する必要があることを意味し、問題なくbase.OnInitialize動作します。