【WPF】FrameworkElement.DataContextプロパティの値が変わるタイミング。

  • 2014.03.30 Sunday
  • 14:23
JUGEMテーマ:コンピュータ

【WPF】FrameworkElement.DataContextプロパティを無効にする方法
http://pro.art55.jp/?eid=1304213


前回は、DataContextに設定した値をクリアーし、親要素の値を再設定したい場合は、DependencyProperty.UnsetValueを設定するばよいという方法を紹介しましたが、今回はDataContextの値が変更されるタイミングを見ていきたいと思います。私の個人の意見としては、一度設定したDataContextの値を変えてしまうような実装は、WPFアプリケーションの設計としては、バグの元になりやすく、間違っていると思います。(伝搬して変更した子要素のDataContextも値の書き換えという事にはなりますが、それは対象外と・・・)

今回は、DataContextの値が変わるタイミングです。正直、私はこの点に関して意識したことは全くありませんでした。前述の通り書き換えないからです。必要なタイミングまでには、値が設定されていたので気にしていなかったということなのですが、DependencyProperty.UnsetValueを設定したタイミングで、その設定した要素や親要素を見に行っているような動きをしていたため、少し違和感を感じたのがきっかけです。親要素が変わったタイミングで子要素に伝搬するだけだと思っていたからです。

試してみました。

    <Grid Background="Pink" x:Name="TopPanel" DataContextChanged="OnDataContextChanged">
        <Grid Margin="40" Background="HotPink" x:Name="MiddlePanel" DataContextChanged="OnDataContextChanged">
            <Grid Margin="40" x:Name="BottomPanel"  Background="DeepPink" DataContextChanged="OnDataContextChanged">
                <Button Margin="40" x:Name="Button" Click="OnClick"  DataContextChanged="OnDataContextChanged">Click</Button>
            </Grid>
        </Grid>
    </Grid>

        private void OnClick(object sender, RoutedEventArgs e)
        {
            Debug.Print("BottomPanel.DataContext に20を設定する");
            BottomPanel.DataContext = 20;

            Debug.Print("TopPanel.DataContextに10を設定する");
            TopPanel.DataContext = 10;

            Debug.Print("BottomPanel.DataContextにDependencyProperty.UnsetValueを設定する");
            BottomPanel.DataContext = DependencyProperty.UnsetValue;

            Debug.Print("Buttonのコンテンツを書き換える。");
            var button = (Button)sender;
            button.Content = button.DataContext;
        }

        private void OnDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            var element = sender as FrameworkElement;
            string message = string.Format("{0}.{1} = {2}", element.Name, e.Property.Name, e.NewValue);
            // MessageBox.Show(message);
            Debug.Print(message);
        }

これを実行すると、以下の出力が得られます。

BottomPanel.DataContext に20を設定する
BottomPanel.DataContext = 20
Button.DataContext = 20
TopPanel.DataContextに10を設定する
TopPanel.DataContext = 10
MiddlePanel.DataContext = 10
BottomPanel.DataContextにDependencyProperty.UnsetValueを設定する
BottomPanel.DataContext = 10
Button.DataContext = 10
Buttonのコンテンツを書き換える。


VirualTreeの位置関係はXAMLの通り

TopPanel - MiddlePanel - BottomPanel - Button

まず、BottomPanelの値を変えると、
BottomPanelとその子のButtonのDataContextの値が変わっていることがわかります。

TopPanel - MiddlePanel - BottomPanel(20) - Button(20)

TopPanelの値を変えると、TopPanel とMiddlePanel まで値が変わります。
すでにBottomPanelに値が設定されているため、BottomPanel以降は伝搬しません。

TopPanel(10) - MiddlePanel(10) - BottomPanel(20) - Button(20)

BottomPanelをDependencyProperty.UnsetValueを設定することで、無効にします。
そうすると、そのタイミングで、BottomPanelは親要素のDataContextが反映されます。
そして、子要素(Button)にも伝搬します。

TopPanel(10) - MiddlePanel(10) - BottomPanel(無効) - Button(20)
TopPanel(10) - MiddlePanel(10) - BottomPanel(10) - Button(10)

以上のことから、DataContextはDataContextに値を設定したタイミングで、常に自分自身から子要素までの値が切り替わっていることが確認できました。私が想定したもう一つの可能性は、DataContextの値が必要となったタイミングで値が切り替わっているのではないかというものがあったのですが、そうではないようです。「見込生産」か「受注生産」かどちらなんだろうってちょいと思ったんですが、「見込生産」に該当するようです。

まとめ、

1.FrameworkElement.DataContextプロパティは、値が変わったタイミングで、
  値が設定されていない直近の子要素まで伝搬する。
2.FrameworkElement.DataContextプロパティに、DependencyProperty.UnsetValueを設定すると
  設定された要素は、親要素から値を取得し設定される(値の場合は値、nullの場合はnull)。
  さらに1の通り、値が伝搬する。

 
コメント
コメントする








    
この記事のトラックバックURL
トラックバック

calendar

S M T W T F S
      1
2345678
9101112131415
16171819202122
23242526272829
30      
<< September 2018 >>

あわせて読みたい

あわせて読みたいブログパーツ

selected entries

categories

archives

recent comment

  • 【キーボード】6年前のRealForceを復活させることはできる!?その3
    art55 (05/22)
  • 【キーボード】6年前のRealForceを復活させることはできる!?その3
    分解大好き (05/18)
  • 【.NET Framework 4.5】 IListがIReadOnlyListを継承してない理由。
    art55 (02/04)
  • 【.NET Framework 4.5】 IListがIReadOnlyListを継承してない理由。
    Gen (02/04)
  • 【キーボード】RealForce が壊れて帰ってきた。
    art55 (04/29)
  • 【.NET Framework 4.5】 IListがIReadOnlyListを継承してない理由。
    art55 (02/23)
  • 【.NET Framework 4.5】 IListがIReadOnlyListを継承してない理由。
    かるあ (02/22)
  • 【C#】Dictionaryの実装・データ構造・アルゴリズムを観察する。
    art55 (01/16)
  • 【C#】Dictionaryの実装・データ構造・アルゴリズムを観察する。
    karuakun (01/16)
  • 【NetOffice】【Excel】死なないExcelプロセスをKillする。
    art55 (12/05)

recent trackback

recommend

recommend

recommend

C#プログラマのための.NETアプリケーション最適化技法 (Programmer's SELECTION)
C#プログラマのための.NETアプリケーション最適化技法 (Programmer's SELECTION) (JUGEMレビュー »)
Sasha Goldshtein,Dima Zurbalev,Ido Flatow,サシャ・ゴルドシュタイン,ディマ・ズルバレフ,イド・フラトー

recommend

ろんりと集合
ろんりと集合 (JUGEMレビュー »)
中内 伸光
とてもわかりやすいです。

recommend

recommend

シャノン・ノイマン・ディジタル世界
シャノン・ノイマン・ディジタル世界 (JUGEMレビュー »)
市川 忠男
4章がリレーショナルデータベースな内容になってます。ページ数があまりありませんが、ポイントがものすごく的確にまとまっていて、感動します。

recommend

recommend

東プレ Realforce91UBK-S 静音キーボード 静電容量無接点方式 変荷重 ブラック NG01BS
東プレ Realforce91UBK-S 静音キーボード 静電容量無接点方式 変荷重 ブラック NG01BS (JUGEMレビュー »)

テンキーレス、静音のRealForce91UBK-S。スコスコ感がたまらなく気持ちいいです。家と会社で2台持ってます。

recommend

recommend

プログラミング.NET Framework 第4版 (プログラミングシリーズ)
プログラミング.NET Framework 第4版 (プログラミングシリーズ) (JUGEMレビュー »)
Jeffrey Richter
発売予定美 2013年10月10日。.NET Frameworkとお付き合いする人のバイブルですね。

recommend

recommend

キャット・シッターの君に。
キャット・シッターの君に。 (JUGEMレビュー »)
喜多嶋 隆
私のイラストレータデビュー本です。

recommend

Essential .NET ― 共通言語ランタイムの本質
Essential .NET ― 共通言語ランタイムの本質 (JUGEMレビュー »)
ドン・ボックス,クリス・セルズ,Don Box,Chris Sells,吉松 史彰

links

profile

search this site.

others

mobile

qrcode

powered

無料ブログ作成サービス JUGEM