2012-03-02 17 views
1

は、次のコードを考えてみましょう:コントロールの初期化順序フィアスコ

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 
    <StackPanel> 
     <Slider ValueChanged="slider_ValueChanged/> 
     <TextBox x:Name="counter"/> 
    </StackPanel> 
</Window> 

namespace Project1 
{ 
    public partial class Window1 : Window 
    { 
     public MainWindow() { InitializeComponent(); } 

     void slider_ValueChanged(object sender, 
      RoutedPropertyChangedEventArgs<double> e) 
     { 
      counter.Text = e.NewValue.ToString(); 
     } 
    } 
} 

counterはまだnullいる間にスライダーが初期化時にそのValueChangedイベントを発生させます。

これは、私がWPFを使用して実行してきたより大きな問題の例です。UIイベントはいつでも発生する可能性があり、初期化コードを置く場所が1つもないため、 WPFシステムが所有するすべてのポインタが初期化された後、UIイベントが発生する前に実行されます。

これに対処する最もエレガントな方法は何ですか?この特定の例ではデータバインディングを使用する必要があるという点は、この点にあります。

答えて

2

でこの質問へ答えは、ファイルの後ろの窓コードがノー初期化コードにはほとんどが含まれているMVVMパターンを使用することです。

このパターンでは、UIはデータバインディングのみで残りのコードに接続されます。 INotifyPropertyChangedを実装する特別なビュー・モデル・クラスを作成し、ビジネス・ロジックをとり、それをUIがバインドする一連のプロパティとして公開します。

もちろん、ビューモデルの初期化方法を完全に制御できます。

3

があなたの状況

まずオフに応じて、これに対処するための多くの方法があり、あなたは、単にオブジェクトが初期化されない可能性がありますという事実を認識し、処理の前にそれをチェックできます。彼らは、オブジェクトが初期化された後まで発生しませんので、例えば、

if (counter.Text != null) 
    counter.Text = e.NewValue.ToString(); 

第二に、あなたは、オブジェクトのLoadedイベントであなたのイベントを添付することができます。

void Counter_Loaded(object sender, EventArgs e) 
{ 
    slider.ValueChanged += Slider_ValueChanged; 
} 

void Counter_Unloaded(object sender, EventArgs e) 
{ 
    slider.ValueChanged -= Slider_ValueChanged; 
} 

そして、すべての最後に、あなたは異なるDispatcherPriorityでUIスレッド上のイベントを実行するために、WPFのDispatcherを使用することができます。デフォルトはLoaded後に実行NormalRender、およびDataBind操作

Dispatcher.BeginInvoke(DispatcherPriority.DataBind, 
    new Action(delegate() { counter.Text = e.NewValue.ToString(); })); 
関連する問題