Quantcast
Channel: かずきのBlog@hatena
Viewing all articles
Browse latest Browse all 1387

アニバーサリーアップデートでのコンパイル時データバインディングの強化点 Functions in binding paths

$
0
0

なんて訳すんでしょうね。バインディングパス内関数とか?

アニバーサリーアップデートと共に降ってきたBuild 14393のSDKですが、こいつをMin versionに設定したプロジェクトでのみコンパイル時データバインディングの新機能が有効になります。つまりアニバーサリーアップデート未満では使えない…!

さて、どんなものか見て行ってみましょう。

簡単に言うと、コンパイル時データバインディングのパスの中にキャストや関数呼び出しが書けるようになってます。キャストは今回説明するFunctions in binding pathsの機能ではないですがバインディングのパスが強化されたという点では同じです。

どんなもんか見て行ってみましょう。 例として以下のようなViewModel(PrismのBindableBase使用)があるとします。

publicclass MainPageViewModel : BindableBase
{
    privatestring input;

    publicstring Input
    {
        get { returnthis.input; }
        set { this.SetProperty(refthis.input, value); }
    }

    publicstaticstring ToUpper(string x)
    {
        return x?.ToUpper();
    }
}

これをMainPageのDataContextにセットします。

<Page.DataContext><local:MainPageViewModel /></Page.DataContext>

そして、以下のようにキャストしてパスを書くことができます!

<TextBox Text="{x:Bind ((local:MainPageViewModel)DataContext).Input, Mode=TwoWay}" />

今まではコードビハインドとかでキャストして公開するプロパティ定義するとかしないといけなかったですが、それをしなくても書ける…!がめんどくさい!!ので今まで通りコードビハインドにこんなプロパティ生やすほうがいいと思うの!

publicsealedpartialclass MainPage : Page
{
    private MainPageViewModel ViewModel => this.DataContext as MainPageViewModel;

    public MainPage()
    {
        this.InitializeComponent();
    }
}

さて本題です。関数が呼べます。

<Page x:Class="App64.MainPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"      xmlns:local="using:App64"      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"      mc:Ignorable="d">
    <Page.DataContext>
        <local:MainPageViewModel />
    </Page.DataContext>
    <StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <TextBox Text="{x:Bind ViewModel.Input, Mode=TwoWay}" />
        <TextBlock Text="{x:Bind local:MainPageViewModel.ToUpper(ViewModel.Input), Mode=OneWay}" />
    </StackPanel>
</Page>

先ほどViewModelに定義してたToUpperメソッドを呼び出しています。インスタンスメソッドでも呼べます。ToUpperメソッドを例えばコードビハインドのインスタンスメソッドとして以下のように定義したとします。

publicsealedpartialclass MainPage : Page
{
    private MainPageViewModel ViewModel => this.DataContext as MainPageViewModel;

    public MainPage()
    {
        this.InitializeComponent();
    }
    publicstring ToUpper(string x)
    {
        return x?.ToUpper();
    }
}

そうすると、こんな風に書けます。

<Page x:Class="App64.MainPage"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:local="using:App64"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"mc:Ignorable="d"><Page.DataContext><local:MainPageViewModel /></Page.DataContext><StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"><TextBox Text="{x:Bind ViewModel.Input, Mode=TwoWay}" /><TextBlock Text="{x:Bind ToUpper(ViewModel.Input), Mode=OneWay}" /></StackPanel></Page>

実行するとこんな感じになります。TextBoxの内容が大文字になって表示されます。

f:id:okazuki:20160804220453p:plain

TwoWayバインディングにも対応しています。例えば表示や入力上は大文字を表示しつつ裏では小文字で管理したいみたいなシナリオ(強引だけどこれくらいしか思いつかなかった)を実現できます。BindBack属性に戻り値を受け取ってプロパティに反映する処理を書きます。BindBackに渡せる関数は引数が1つの関数っぽいです。

例えばこんな感じ。

publicclass MainPageViewModel : BindableBase
{
    privatestring input;

    publicstring Input
    {
        get { returnthis.input; }
        set { this.SetProperty(refthis.input, value); }
    }
    
    publicvoid ToLower(string x)
    {
        this.Input = x?.ToLower();
    }
}

これでXAMLを以下のようにします。

<Page x:Class="App64.MainPage"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:local="using:App64"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"mc:Ignorable="d"><Page.DataContext><local:MainPageViewModel /></Page.DataContext><StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"><TextBox Text="{x:Bind ToUpper(ViewModel.Input), BindBack=ViewModel.ToLower, Mode=TwoWay}" /><TextBlock Text="{x:Bind ViewModel.Input, Mode=OneWay}" /></StackPanel></Page>

BindBackに先ほど作成したメソッドを設定しています。 実行すると以下のようにTextBoxの中身はフォーカスが外れたタイミングで大文字化されますが、VMのInputプロパティの値は小文字がキープされてることがわかります。

f:id:okazuki:20160804221401p:plain

まとめ

個人的に一番アツイ新機能になります。これを使うとかなり柔軟に値の変換と書き戻しが可能になります。がしがし使っていきたいところですが、アニバーサリーアップデート以降というのがネックになりそうですね。まぁ普通のWindows 10ならアップデートはされるはずなので大きな問題にはならないのかな?

あと、困ったことに、よくデザイナが死にます。


Viewing all articles
Browse latest Browse all 1387

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>