2012-03-02 113 views
1

考慮下面的代碼:當counter仍然null控制初始化順序的悲劇

<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(); 
     } 
    } 
} 

滑塊將提高其ValueChanged事件期間初始化。

這是一個更大的問題的例子,我一直在使用WPF,UI事件可以在任何時候觸發,並且沒有一個地方可以放置我的初始化代碼,以保證它在所有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; 
} 

末後,你可以使用WPF的Dispatcher以不同的DispatcherPriority運行UI線程上的事件。默認值是Normal,它運行後LoadedRender,並且DataBind操作

Dispatcher.BeginInvoke(DispatcherPriority.DataBind, 
    new Action(delegate() { counter.Text = e.NewValue.ToString(); }));