2

次のコードを検討してください。

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

Sliderは、初期化中ValueChangedイベントを発生させます。counternull

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

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

4

2 に答える 2

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後に実行されますLoadedRenderDataBind

Dispatcher.BeginInvoke(DispatcherPriority.DataBind, 
    new Action(delegate() { counter.Text = e.NewValue.ToString(); }));
于 2012-03-02T16:36:37.030 に答える
2

この質問に対する正しい答えは、ウィンドウ コード ビハインド ファイルに初期化コードがほとんどまたはまったく含まれていない MVVM パターンを使用することです

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

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

于 2013-04-29T17:02:15.473 に答える