やりたいこと
今まで使ったことがなかったReactiveProperty
を使う必要が出てきた。
取り合えず小難しいことはおいておいて、最低限値の表示、ボタン押下時の処理の記述だけやり方メモっておきたい。
今回試した前提
★全然ReactivePropertyを全然知らない状態からとにかく明日まずは使いたいので、ネットのサンプルをかき集め、自分用に保存する。(ので、間違いあるかも)
- 使用したもの
- WinUI3
- NET6
- C#
サンプルアプリ
「カウントUPボタン」を押すと、Cmdが発火し、その中でCounterを++する。
そのCmdとCounterを、ReactivePropertyで作る。
サンプルコード
■画面
<Window x:Class="ReactiveRenshuu.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:ReactiveRenshuu" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center"> <TextBlock Text = "{x:Bind DC.Counter.Value, Mode=OneWay}" /> <Button Content = "カウントUPボタン" Command="{x:Bind DC.Cmd}"/> </StackPanel> </Window>
■ViewModelなど
using Microsoft.UI.Xaml; using Reactive.Bindings; using System; using System.ComponentModel; using System.Diagnostics; using System.Reactive.Linq; namespace ReactiveRenshuu { public sealed partial class MainWindow : Window { public MainWindowViewModel DC = new MainWindowViewModel(); public MainWindow() => this.InitializeComponent(); } public class MainWindowViewModel : INotifyPropertyChanged { // ReactivePropertyでは本来INotifyPropertyChangedを実装しなくてよいが、 // 実装しておかないとメモリリークするらしい(WinUI3でどうなるかは不明) // https://qiita.com/YSRKEN/items/5a36fb8071104a989fb8#q-%E3%81%82%E3%82%8Creactiveproperty%E3%81%A0%E3%81%A8inotifypropertychanged%E8%A6%81%E3%82%89%E3%81%AA%E3%81%84%E3%82%93%E3%81%98%E3%82%83%E3%81%AA%E3%81%8B%E3%81%A3%E3%81%9F%E3%81%A3%E3%81%91 public event PropertyChangedEventHandler PropertyChanged; public void OnPropertyChanged(string propertyName) => this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); // --------------------------------- // ボタン押下時コマンド public ReactiveCommand Cmd { get; set; } = new ReactiveCommand(); // ボタン押下時にカウントUPするカウンタ public ReactiveProperty<int> Counter { get; set; } = new ReactiveProperty<int>(); public MainWindowViewModel() { Counter.Subscribe(_ => Debug.WriteLine("カウンター 変化")); Cmd.Subscribe(_ => { Counter.Value++; Debug.WriteLine("ボタン押下コマンド {0}", Counter.Value); }); } } }
■別解
C#コードの部分を下記のようにしても動いた。(xamlは同じものを使用)
ViewModelを書くのがめんどくさい場合などは、これでもよいのかも。
using Microsoft.UI.Xaml; using Reactive.Bindings; using System; using System.ComponentModel; using System.Diagnostics; using System.Reactive.Linq; namespace ReactiveRenshuu { public sealed partial class MainWindow : Window, INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; public void OnPropertyChanged(string propertyName) => this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); // --------------------------------- public ReactiveCommand Cmd { get; set; } = new ReactiveCommand(); public ReactiveProperty<int> Counter { get; set; } = new ReactiveProperty<int>(); public MainWindow DC; public MainWindow() { this.InitializeComponent(); DC = this; Counter.Subscribe(_ => Debug.WriteLine("カウンター 変化")); Cmd.Subscribe(_ => { Counter.Value++; Debug.WriteLine("ボタン押下コマンド {0}", Counter.Value); }); } } }
気づいたこと
WindowsクラスにDataContext
がない!
→バインドするときに、VMのフィールド名.プロパティ名.Value
とする。
バインディングするときの書き方が{x:Bind プロパティ名}
→WinUI3じゃないWPFのときの{Binding プロパティ名}
とすると、値が表示されなかった。