10294


this.DataContextで値を反映する場合と  
btnA.DataContextで値を反映する場合の違いは何でしょうか。

スレッドでbtnA,btnBを同時に実行した場合thisを使った場合は画面がちらつきました。  
詳しい方がいましたら教えて頂けると助かります。

XAML

[code]

        <Grid>
        <Button x:Name="btnA" Content="{Binding ButtonContentA}" Click="Button_ClickA"/>
        <Button x:Name="btnB" Content="{Binding ButtonContentB}" Click="Button_ClickB"/>
    </Grid>
    
[/code]

C#

[code]

    void Worker_ProgressChangedA(object sender, System.ComponentModel.ProgressChangedEventArgs e)
        {
        //スレッドの画面再描画でthisを使うと画面がちらつく
        //this.DataContext = new { ButtonContentA =  e.ProgressPercentage };
        btnA.DataContext = new { ButtonContentA = e.ProgressPercentage };
        }
    
    void Worker_ProgressChangedB(object sender, System.ComponentModel.ProgressChangedEventArgs e)
        {    
        //this.DataContext = new { ButtonContentB =  e.ProgressPercentage };
        btnA.DataContext = new { ButtonContentB = e.ProgressPercentage };
        }
    
[/code]


CC BY-SA 3.0
2015-05-15T10:54:00.513
10229
2015-05-18T03:38:13.943
7462
question
c# wpf xaml
DataContextを使う際のthisとx:Name指定の違いについて


DataContext自体を逐次変更するのは正しいスタイルとは言えません。  
this.DataContext自体を変更すると下位のコントロールすべてに変更通知が飛びます。

データバインドを使う場合、DataContextにはINotifyPropertyChangedを実装したオブジェクトを代入し使いまわしましょう。データバインドしたコントロールはプロパティの変更を常に監視しています。変更通知を投げればコントロール側も変更を追従します。

[code]

    // NotificationObjectは実装を探して見てください。ここでは割愛します。
    public class SamplePresenter : NotificationObject
    {
        public int ButtonContentA
        {
            get { return _ButtonContentA; }
            set
            {
                if (_ButtonContentA != value)
                {
                    _ButtonContentA = value;
                    // ここでPropertyChangedEventArgs("ButtonContentA")が
                    // 通知されると思ってください
                    RaisePropertyChanged("ButtonContentA");
                }
            }
        }
        private int _ButtonContentA;
    }
    
    public partial class SampleWindow : Window
    {
        // 少し手抜きですが以下のようにバインドされていたとして
        public SampleWindow() {
            this.DataContext = Presenter = new SamplePresenter();
        }
        public SamplePresenter Presenter { get; set; }
    
        void Worker_ProgressChangedA(object sender, System.ComponentModel.ProgressChangedEventArgs e)
        {
            //スレッドからPresenterの値を更新します
            this.Presenter.ButtonContentA = e.ProgressPercentage;
        }
    }
    
[/code]


CC BY-SA 3.0
2015-05-18T02:29:55.393
10294
2015-05-18T02:29:55.393
9407
10229
answer


DataBindingsとDataContextの基本的な利用方法に関しては以下のエントリーにざっくりまとめているので、目を通して参考にしていただければ幸いです。

> サンプルコードを見ながら理解するMVVMの基礎的な実装 - Neutral Scent  
>  <http://d.hatena.ne.jp/kaorun/20141202/1417532472>

すでにpgrhoさんやharu666さんが述べられているように、DataContextはデータ更新のたびに逐一変更するべきではありません。this.DataContextを変更してしまうと、対象となるウインドウもしくはフォーム全体の再描画が都度走ってしまうためフリッカが起きていると思われます。

単に値を代入・表示したいだけであれば、WinForms時代のように、btnA.Content/btnB.Contentに直接変更値を代入してしまうのも手ですが、DataBindingを利用してよりモダンにMVVM的な実装を目指すのであれば、INotifyPropertyChangedインターフェイスを継承したクラス(ViewModel)を実装し、このクラスで生成したデータをこのウインドウ(View)で表示するよ、とDataContextに割り当て、そのクラスの変更をView側に通知してやるのが今風である、というイメージです。


CC BY-SA 3.0
2015-05-18T03:38:13.943
10297
2015-05-18T03:38:13.943
2947
10229
answer