ReactiveUI/Xamarin.MacのNSTextFieldにバインドする

提供: MonoBook
< ReactiveUI
2015年3月9日 (月) 11:14時点における153.220.119.198 (トーク)による版 (ページの作成:「ReactiveUIのビューモデルをXamarin.MacのNSTextFieldにバインドする場合には一筋縄ではいなかいようだ。 単純にReactiveWindowController...」)
(差分) ← 古い版 | 最新版 (差分) | 新しい版 → (差分)
ナビゲーションに移動 検索に移動

ReactiveUIのビューモデルをXamarin.MacのNSTextFieldにバインドする場合には一筋縄ではいなかいようだ。 単純にReactiveWindowControllerクラスのBindメソッドやOneWayBindメソッドでバインドしただけではまったく反応してくれなくて困った。 そんな中キーボードを強打しながらGitHubを徘徊していたところ見事に解決策を発見した[1]

    using System;
    using System.ComponentModel;
    using System.Reactive;
    using System.Reactive.Concurrency;
    using System.Reactive.Linq;
    using System.Reactive.Subjects;
    using Foundation;
    using AppKit;
    using ReactiveUI;

    public partial class MainWindowController : ReactiveWindowController, IViewFor<MainViewModel>
    {
        // 〜〜〜中略〜〜〜

        MainViewModel _viewModel;

        public MainViewModel ViewModel { 
            get { return _viewModel; }
            set { this.RaiseAndSetIfChanged(ref _viewModel, value); }
        }
            
        object IViewFor.ViewModel
        {
            get { return ViewModel; }
            set { ViewModel = (MainViewModel)value; }
        }

        // 〜〜〜ここまではよくある定型〜〜〜

        IObservable<Unit> hookTextField(NSTextField textField)
        {
            var ret = new Subject<Unit>();
            textField.Delegate = new BlockDidChangeTextFieldDelegate(() => ret.OnNext(Unit.Default));
            return ret;
        }

        class BlockDidChangeTextFieldDelegate : NSTextFieldDelegate
        {
            Action block;
            public BlockDidChangeTextFieldDelegate(Action block) { this.block = block; }
            public override void Changed(NSNotification notification) { block(); }
        }

        public override void WindowDidLoad()
        {
            base.WindowDidLoad();

            // ---- バインド ----

            // よくあるこの記法では動かない
            //this.Bind(ViewModel, vm => vm.FirstName, v => v.FirstName.StringValue);

            // hookTextFieldが重要だった
            this.Bind(ViewModel, vm => vm.FirstName, v => v.FirstName.StringValue, hookTextField(FirstName));
            this.Bind(ViewModel, vm => vm.LastName , v => v.LastName.StringValue , hookTextField(LastName));
            this.OneWayBind(ViewModel, vm => vm.FullName, v => v.FullName.StringValue);

            // ---- ビューモデル生成 ----
            ViewModel = new MainViewModel();
        }
    }

なお、このサンプルのビューモデルには「ReactiveUI/ViewModelを作る#WhenAny」にあるものを使っている。

関連項目[編集 | ソースを編集]

参考文献[編集 | ソースを編集]