はかせのラボ

私の頭の中を書いていく雑記ブログです

WPF データバインディング is 何?

どうも、先日ダイパリメイクが発表されテンションが高いhakaseです。

さて前回WPFの初歩を刻んだところで、
今回はWPFの基本であり全てとも言って過言ではない、
「データバインディングについて書いていきます。

データバインディング is 何

よくMVVMとかMVCの設計パターンを勉強していると、
「ViewとModelは分離しろ」
疎結合になるようにしろ」

的な文言を見ると思います。

それを実現するためにWPFに用意されている機能です。(ざっくり)

WPFは基本的にViewはxamlで、ModelやViewModelはC#で作ります。
つまりC#xamlのつながりをかな~りゆるくするために使います。

イメージこんなの。
f:id:hakase0274:20210228164202p:plain

DataContextっていうのはxamlに設定できるC#インスタンスのことです。
TextBlockのTextプロパティにDataContextの中にあるTextプロパティの値がはめられます。

あとはそれぞれのTextプロパティが変わったとき、
それを通知してそれぞれの値を更新するという流れです。

具体例を交えて

実際に具体例を交えてやっていきます。
前回の記事で出した例を流用して話をします。

まずはxamlC#インスタンスを繋げます。
とりあえずDataContextにC#インスタンスを突っ込みます。

xmlns:vm="clr-namespace:LivetApp1.ViewModels"

<Window.DataContext>
    <vm:MainWindowViewModel />
</Window.DataContext>

xmlns~はC#でいうusingみたいなもんです。
DataContextの中に突っ込みたいC#クラス名を入れます。
(そしたら勝手にインスタンス化してくれます)
ちなみにDataContextには一つのインスタンスしか入れれません。

そしてDataContext内のプロパティをxamlのプロパティにあてはめます。

<Grid>
    <TextBlock Text="{Binding BindText,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
</Grid>

あてはめたクラスとプロパティはこんな感じ。

private string mBindText = "Hello World";
public string BindText
{
    get => mBindText;
    set => RaisePropertyChangedIfSet(ref mBindText,value);
}

C#->xamlはRaisePropertyChangedで通知を行います。
これはLivetの機能なので詳細割愛です。

xaml->C#はModeをTwoWayとかにしておけば勝手に通知されます。

例ではフルで書いてますが、
ModeとUpdateSourceTriggerはDefaultで設定されているので、
基本なんも書かなくても通知はいきます。

つまりやることとしては
・DateContextにインスタンスをはめる
xaml側プロパティにBindingを書く
C#でプロパティを定義し変更時に通知する
ぐらいです。簡単ですね。

あとがき

今回はデータバインディングとはなんぞや?ってのを書いてみました。

ぶっちゃけ自分はここに書いてあることぐらいしかわかっていません。
RaisePropertyChangedがどういう方法でxamlに通知してるのかとか、
よくわかっていません。(コード読めって話ですが)

今後もまったり作ったりしながら勉強していきまーす・・

それでは今回はこの辺でノシ

WPF Livet使ってWPFアプリを作り始めた

どうも、hakaseです。
もうそろ北海道を脱出してから一年になります。

コロナとかで色々大変でしたが、
なんとか家事等にも慣れてきてデュエマ等の開発以外の趣味も増え、
すこぶる元気に過ごせています。

ただまぁなんやかんやでプログラム書くのは好きなので、
まったりプログラムも書いてました。

今回は自宅で細々と書いては捨ててを繰り返している
Livetを使ったアプリ開発について
備忘録も兼ねて書いていきたいと思います。

なおxamlとかMVVMとかBindingとか出てきますが、
そういった用語だとかはまた別で解説記事上げますので
この記事では解説しません。
(書いてて読みづらい&ようわからんってなってしまったので)

解説記事はなるはやで上げるのでお待ちください。

環境

Windows10
VS2019
Livet

Livet(りべっと)とは

まずこの記事ではLivetというMVVMフレームワークを使用します。
どういうことができるフレームワークかというと、
MVVMという設計をしやすくするものです。

ダウンロードはこちら

い つ も の

基本編入門編ではもはやおなじみHello Worldのプログラムを組みます。

上記のリンクからLivetをダウンロードしてもらうと
VS2019にLivetのプロジェクトテンプレートが追加されるので
それを使ってプロジェクトを作ります。
f:id:hakase0274:20210131163418p:plain
.NetCoreか.NetFrameworkかはお好みでどうぞ。

MVVMではModel/View/ViewModelのどれを使っても
Hello Worldが出せるのでこの記事では全パターンやってみます。
(どれもそんな難しくないので)

まずはViewから
テンプレートを作成した時勝手にできる
MainWIndow.xamlに下のコードを追加。

<Grid>
    <TextBlock Text="Hello World"/>
</Grid>

そして実行
f:id:hakase0274:20210131164315p:plain

次ViewModelを使うパターン
まずMainWindow.xamlの先頭にあるWindowのタグ内に下記のコードを追加

xmlns:vm="clr-namespace:LivetApp1.ViewModels"

そしてWindowタグの下あたりに追加

<Window.DataContext>
    <vm:MainWindowViewModel />
</Window.DataContext>

そのあとViewパターンで追加したコードを一部変更

<Grid>
    <TextBlock Text="{Binding BindText,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
</Grid>

そしてこれまた勝手に作られているMainWIndowViewModel.csにこんなの追加

private string mBindText = "Hello World";
public string BindText
{
    get => mBindText;
    set => RaisePropertyChangedIfSet(ref mBindText,value);
}

はい実行
f:id:hakase0274:20210131164956p:plain

最後Model使うパターン
まずMainWindowViewModelをこんな感じに変更

public MainWindowViewModel() 
{
    mModel = new Model();
    var listener = new PropertyChangedEventListener(mModel);
    listener.RegisterHandler(nameof(Model.BindText), (s,e) => { RaisePropertyChanged(nameof(BindText)); });
    CompositeDisposable.Add(listener);
}

private Model mModel;

public string BindText 
{
    get => mModel.BindText;
    set => mModel.BindText = value;
}

そしてこれまたぬるっと作成されているModel.csに追加

private string mText = "HelloWorld";
public string BindText 
{
    get => mText;
    set => RaisePropertyChangedIfSet(ref mText,value);
}

最後の実行
f:id:hakase0274:20210131165625p:plain

はい全部無事Hello Worldがでました~

あとがき

今回は備忘録を兼ねてLivetのインストールから
Hello Worldまでやってみました。

WPFは色々と用語や前提知識があるので、
一記事だけでちゃんとした実装と解説を書くのは
少なくとも私の文章力では無理でした。

全部をまとめた長尺の記事を書くのもありかと思いましたが、
私の気力が持たないのと読む側も辛いだろうということで
少しずつ記事を拡充していく方向性で行くことにしました。

一応コード等は全てgithubの方に上げているので
こちらのコードを見てもらってそれでもわからないことは
Twitter等で聞いてもらえればと思います。
(そうすればどこが分かりにくかったとかの情報が収集され記事のクオリティがあがるかも)
github.com

それでは今回はこの辺でノシ