ããŒã2ïŒReactiveUIã®æŠèŠïŒã³ã¬ã¯ã·ã§ã³
ããããã£ã®æäœãããããã£éã®äŸåé¢ä¿ã®æ§ç¯ãã³ã¬ã¯ã·ã§ã³ã®æäœã«é¢é£ããReactiveUIã®æ©èœã«ã€ããŠã¯æ¢ã«èª¬æããŸããã ãããã¯ãReactiveUIã䜿çšããéçºã®åºç€ãšãªãåºæ¬çãªããªããã£ãã®1ã€ã§ãã å¥ã®ãã®ãããªããªããã£ãã¯ããã®éšåã§æ€èšããããŒã ã§ãã ããŒã ã¯ãäœããã®ã€ãã³ãã«å¿ããŠå®è¡ãããã¢ã¯ã·ã§ã³ãã«ãã»ã«åããŸããéåžžãããã¯ãŠãŒã¶ãŒãªã¯ãšã¹ããŸãã¯äœããã®è¿œè·¡ãããå€æŽã§ãã ReactiveUIã®ã³ãã³ãã䜿çšããŠäœãã§ããããåŠç¿ãããããã®äœæ¥ã®æ©èœã«ã€ããŠèª¬æããReactiveUIã®ã³ãã³ããWPFããã³ãã®èŠªfromãã粟éããŠããããŒã ãšã©ã®ããã«ç°ãªããã調ã¹ãŸãã
ãã ããã³ãã³ãã«ç§»ãåã«ããªã¢ã¯ãã£ãããã°ã©ãã³ã°ã«é¢ããããåºç¯ãªãããã¯ãã€ãŸãã¿ã¹ã¯<T>ãšIObservable <T>ã®é¢ä¿ãããã³ãããã·ãŒã±ã³ã¹ãšã³ãŒã«ãã·ãŒã±ã³ã¹ã«ã€ããŠèª¬æããŸãã
ã¿ã¹ã¯å¯Ÿ IObservable
ãããã£ãŠãã¿ã¹ã¯<T>ïŒ+ asyncãawaitãããã ãïŒãšIObservable <T>ã®éã«é¡äŒŒç¹ãæããŸãããã ReactiveUIã§ããŒã ãšé£æºããæ¹æ³ãç解ããããšã¯éèŠã§ããã説æããã¢ãããŒãã¯ããåºç¯ãªã¢ããªã±ãŒã·ã§ã³ãæã¡ãããã«ã€ããŠç¥ãã®ã«å®³ã¯ãããŸããã ãããã£ãŠã ã¿ã¹ã¯<T>ã¯IObservable <T>ã§ãã ãããããããã¯ç¢ºãã«åçã§ã¯ãããŸãããIObservable<T>ã¯ã¯ããã«åºç¯ãªã¿ã¹ã¯ã解決ã§ããŸãã
ãªããšãªãæªããã§ããã æ£ããããŸãããã ããã«äŸãèŠãŠã¿ãŸãããïŒ
Task<string> task = Task.Run(() => { Console.WriteLine(DateTime.Now.ToLongTimeString() + " "); Thread.Sleep(1000); Console.WriteLine(DateTime.Now.ToLongTimeString() + " "); return " "; }); Console.WriteLine(DateTime.Now.ToLongTimeString() + " - "); string result = task.Result; Console.WriteLine(DateTime.Now.ToLongTimeString() + " : " + result);
ã¿ã¹ã¯ãäœæããŸãããéåæã«å®è¡ãããèµ·ååŸããã«å®äºãåŸ ããã«ä»ã®ããšãè¡ãããšã劚ããŸããã çµæã¯äºæž¬å¯èœã§ãïŒ
18:19:47ã¿ã¹ã¯ã®çµæãåŸ ã€åã«äœãããã
18:19:47é·ãã¿ã¹ã¯ãéå§ãã
18:19:48é·ãã¿ã¹ã¯ãå®äºããŸã
18:19:48çµæïŒé·ãã¿ã¹ã¯ã®çµæ
æåã®2è¡ã¯ããã«è¡šç€ºãããã©ãããŒãšããŠå¥ã®é åºã«ãªãå ŽåããããŸãã
ãããŠãIObservable <T>ã§æžãæããŸãïŒ
IObservable<string> task = Observable.Start(() => { Console.WriteLine(DateTime.Now.ToLongTimeString() + " "); Thread.Sleep(1000); Console.WriteLine(DateTime.Now.ToLongTimeString() + " "); return " "; }); Console.WriteLine(DateTime.Now.ToLongTimeString() + " - "); string result = task.Wait(); // Console.WriteLine(DateTime.Now.ToLongTimeString() + " : " + result);
éãã¯2è¡ã§ãïŒTask <string>ã®ä»£ããã«IObservable <string>ãTask.RunïŒïŒã®ä»£ããã«Observable.StartïŒïŒãtask.Resultã®ä»£ããã«task.WaitïŒïŒã äœæ¥ã®çµæã¯ãŸã£ããåãã§ãã
ã¿ã¹ã¯ã®å®äºåŸã«ã¢ã¯ã·ã§ã³ãéå§ããå¥ã®æåãªããªãã¯ãèŠãŠã¿ãŸãããã
//Task task.ContinueWith(t => Console.WriteLine(DateTime.Now.ToLongTimeString() + " : " + t.Result)); //IObservable task.Subscribe(t => Console.WriteLine(DateTime.Now.ToLongTimeString() + " : " + t));
ããã§ããå®è³ªçã«éãã¯ãããŸããã
ã¿ã¹ã¯<T>ã¯IObservable <T>ã§è¡šãããšãã§ãã1ã€ã®èŠçŽ ãšå®äºä¿¡å·ãçæããŸãã ãã®ãããªã¢ãããŒãã®éã«å²åŠçããã³ã¢ãŒããã¯ãã£äžã®å€§ããªéãã¯ãªãã誰ã§ã䜿çšã§ããŸãã async / awaitã§ãäž¡æ¹ã®å Žåã«å©çšã§ããŸããéåæã¡ãœããã§IObservableããçµæãååŸããå ŽåãäŸã®ããã«WaitïŒïŒã¡ãœããã§åŸ æ©ããããã¯ããããšã¯ã§ããŸãããã awaitã䜿çšããŸãã ããã«ãããã2ã€ã®ã¢ãããŒããçµã¿åãããŠã1ã€ã®ãã¥ãŒãå¥ã®ãã¥ãŒã«å€æããäž¡æ¹ã®å©ç¹ã掻çšã§ããŸãã
ãããã·ãŒã±ã³ã¹ãšã³ãŒã«ãã·ãŒã±ã³ã¹
ãªãã¶ãŒããã«ã·ãŒã±ã³ã¹ïŒãªãã¶ãŒããã«ïŒã䜿çšããäœæ¥ã«é¢ãããã1ã€ã®è³ªåã«ã€ããŠèª¬æããŸãã ã³ãŒã«ãïŒã³ãŒã«ãïŒãšãããïŒãããïŒã®2ã€ã®ã¿ã€ãããããŸãã ã³ãŒã«ãã·ãŒã±ã³ã¹ã¯ååçã§ãããèŠæ±ã«å¿ããŠããµãã¹ã¯ã©ã€ãæã«éç¥ãçæãå§ããŸãã ãããã·ãŒã±ã³ã¹ã¯ã¢ã¯ãã£ãã§ããã誰ãããµãã¹ã¯ã©ã€ããããã©ããã«äŸåããŸãããéç¥ã¯ãšã«ããçæãããŸãããããŸã«äœãéä¿¡ãããŸããã
ã¿ã€ããŒãã£ãã¯ãããŠã¹ç§»åã€ãã³ãããããã¯ãŒã¯çµç±ã®ãªã¯ãšã¹ãã¯ãããã·ãŒã±ã³ã¹ã§ãã ããæç¹ã§ãããã«ãµãã¹ã¯ã©ã€ãããããšã«ãããçŸåšã®éç¥ãåä¿¡ãå§ããŸãã 10人ã®ãªãã¶ãŒããŒã賌èªããŸã-éç¥ã¯å šå¡ã«é ä¿¡ãããŸãã ã¿ã€ããŒã®äŸã次ã«ç€ºããŸãã
ã³ãŒã«ãã·ãŒã±ã³ã¹ãšã¯ãããšãã°ãããŒã¿ããŒã¹ãžã®ã¯ãšãªãããã¡ã€ã«ã1è¡ãã€èªã¿åãããšã§ãã ãµãã¹ã¯ãªãã·ã§ã³æã«èŠæ±ãŸãã¯èªã¿åããéå§ãããæ°ããè¡ãåä¿¡ããããã³ã«OnNextïŒïŒãåŒã³åºãããŸãã è¡ãçµäºãããšãOnCompleteïŒïŒãåŒã³åºãããŸãã åãµãã¹ã¯ã©ã€ããããšããã¹ãŠãåã³ç¹°ãè¿ãããŸããããŒã¿ããŒã¹å ã®æ°ããã¯ãšãªãŸãã¯ãã¡ã€ã«ãéããŠããã¹ãŠã®çµæãè¿ããå®äºã·ã°ãã«ãè¿ããŸãã
ã¯ã©ã·ãã¯ããŒã ...
ããã§ã¯ãä»æ¥ã®ãããã¯ã§ããããŒã ã«ç§»ããŸãããã ãã§ã«è¿°ã¹ãããã«ãããŒã ã¯ç¹å®ã®ã€ãã³ãã«å¿ããŠå®è¡ãããã¢ã¯ã·ã§ã³ãã«ãã»ã«åããŸãã ãã®ãããªã€ãã³ãã¯ããŠãŒã¶ãŒããä¿åããã¿ã³ãã¯ãªãã¯ããããšã§ãã ã«ãã»ã«åãããã¢ã¯ã·ã§ã³ã¯ãäœããä¿åããæäœã«ãªããŸãã ãã ããã³ãã³ãã¯ãæ瀺çãªãŠãŒã¶ãŒã¢ã¯ã·ã§ã³ãŸãã¯é¢é£ããéæ¥ã€ãã³ããžã®å¿çãšããŠã ãã§ãªãå®è¡ã§ããŸãã ãŠãŒã¶ãŒã«é¢ä¿ãªãã5åããšã«å®è¡ãããã¿ã€ããŒããã®ä¿¡å·ããåããä¿åãã³ãã³ããéå§ã§ããŸãã ãŸããã³ãã³ãã¯éåžžããŠãŒã¶ãŒãäœããã®æ¹æ³ã§å®è¡ããã¢ã¯ã·ã§ã³ã«å¯ŸããŠæ£ç¢ºã«äœ¿çšãããŸãããä»ã®ã±ãŒã¹ã§ã®äœ¿çšãç¡èŠããªãã§ãã ããã
ãŸããã³ãã³ãã䜿çšãããšãå®è¡ãçŸåšäœ¿çšå¯èœãã©ããã確èªã§ããŸãã ããšãã°ãä¿åãåžžã«äœ¿çšã§ããããã«ããã®ã§ã¯ãªãããã©ãŒã ã®ãã¹ãŠã®å¿ é ãã£ãŒã«ããå ¥åãããã€ã³ã¿ãŒãã§ã€ã¹ã§ãã¿ã³ãã¢ã¯ãã£ããã©ããã¯ã³ãã³ãã®å¯çšæ§ã«äŸåããŸãã
ICommandããŒã ã€ã³ã¿ãŒãã§ã€ã¹ãšã¯äœããèŠãŠã¿ãŸãããã
public interface ICommand { event EventHandler CanExecuteChanged; bool CanExecute(object parameter); void Execute(object parameter); }
å®è¡ã¯æããã«ã³ãã³ããå®è¡ããŸãã ãã©ã¡ãŒã¿ãŒãæž¡ãããšãã§ããŸãããå¿ èŠãªå€ãã³ãã³ãèªäœã®å éšã§ååŸã§ããå ŽåïŒããšãã°ãViewModelããååŸããå ŽåïŒããã®æ©äŒã䜿çšããªãã§ãã ããã ããã«ãã®çç±ãç解ããŸãã ãããããã¡ããããã©ã¡ãŒã¿ãŒãæž¡ãããšãæãåãå ¥ãããããªãã·ã§ã³ã§ããå ŽåããããŸãã
CanExecuteã¯ãã³ãã³ãå®è¡ãçŸåšäœ¿çšå¯èœãã©ããã確èªããŸãã ãã©ã¡ãŒã¿ãŒããããããã§ã¯ãã¹ãŠãExecuteãšåãã§ãã ç¹å®ã®ãã©ã¡ãŒã¿ãŒå€ã䜿çšããCanExecuteããåããã©ã¡ãŒã¿ãŒå€ã®ã¿ã䜿çšããã³ãã³ãã®å®è¡ãèš±å¯ãŸãã¯çŠæ¢ããããšãéèŠã§ããä»ã®å€ã«ã€ããŠã¯ãçµæãç°ãªãå ŽåããããŸãã ãŸããExecuteã¯ãã¢ã¯ã·ã§ã³ãå®è¡ããåã«CanExecuteããã§ãã¯ãããåŒã³åºãã³ãŒãã®ã¿ã¹ã¯ã§ããããšã«æ³šæããŠãã ããã
CanExecuteChangedã€ãã³ãã¯ãå®è¡æ©äŒã®ã¹ããŒã¿ã¹ãå€åãããšãã«çºçãããããCanExecuteãå確èªããå¿ èŠããããŸãã ããšãã°ããã©ãŒã å ã®ãã¹ãŠã®ãã£ãŒã«ãã«å ¥åããŠä¿åã§ããããã«ãªã£ãå Žåãã€ã³ã¿ãŒãã§ã€ã¹ã«ãã¿ã³ãå«ããå¿ èŠããããŸãã ã³ãã³ããæ·»ä»ããããã¿ã³ã¯ããã®æ¹æ³ã§èªèããŸãã
...ãããŠãããã®äœãåé¡ãªã®ã
æåã®åé¡ã¯ãCanExecuteChangedã€ãã³ãããå®è¡ã¹ããŒã¿ã¹ãå€æŽããããã©ã¡ãŒã¿ãŒå€ã瀺ããŠããªãããšã§ãã ããããExecute / CanExecuteãåŒã³åºããšãã®ãã©ã¡ãŒã¿ãŒã®äœ¿çšãé¿ããå¿ èŠãããçç±ã§ãããã©ã¡ãŒã¿ãŒã«é¢ããICommandã€ã³ã¿ãŒãã§ã€ã¹ã¯ç¹ã«äžè²«æ§ããããŸããã äºåŸå¯Ÿå¿åã®ããŒã ã§ã¯ãããããèŠãããã«ããã®ã¢ãããŒãã¯ãŸã£ããããŸããããŸããã§ããã
2çªç®ã®åé¡-ExecuteïŒïŒã¯ãã³ãã³ãã®å®äºåŸã«ã®ã¿å¶åŸ¡ãè¿ããŸãã ã³ãã³ããé·æéå®è¡ããããšããŠãŒã¶ãŒã¯ãã³ã°ããã€ã³ã¿ãŒãã§ã€ã¹ã«çŽé¢ãããããåæºããŸãã
誰ãããã奜ãã«ãªãã§ããããïŒ
ãã®ããã°ã©ã ã«ã¯ãã³ãã³ãèµ·åãã¿ã³ããã°åºåãé²è¡ç¶æ³ããŒããããéåžžã®ç¶æ³ã§ã¯åžžã«ç§»åããã¯ãã§ãã èµ·åæã®ã³ãã³ãã¯ãçŸåšã®æå»ããã°ã«æžã蟌ã¿ã1.5ç§éïŒããšãã°ãããŒã¿ã®èªã¿èŸŒã¿ïŒãå®è¡ããå®äºæå»ãæžã蟌ã¿ãŸãã
é²è¡ç¶æ³ããŒãåæ¢ãããã°ã¯ã³ãã³ãã®æåŸã§ã®ã¿æŽæ°ãããã€ã³ã¿ãŒãã§ãŒã¹ãããªãŒãºããŸãã ããŸããããªãã£ã...
é²è¡ç¶æ³ããŒãåæ¢ãããã°ã¯ã³ãã³ãã®æåŸã§ã®ã¿æŽæ°ãããã€ã³ã¿ãŒãã§ãŒã¹ãããªãŒãºããŸãã ããŸããããªãã£ã...
ç¶æ³ãä¿åããæ¹æ³ã¯ïŒ ãã¡ãããå¥ã®ã¹ã¬ããã§å¿ èŠãªã¢ã¯ã·ã§ã³ã®å®è¡ã®ã¿ãéå§ããå¶åŸ¡ãè¿ãããã«ã³ãã³ããå®è£ ã§ããŸãã ãããããã®åŸãå¥ã®åé¡ãçºçããŸãããŠãŒã¶ãŒã¯ãåã®ãã¿ã³ãå®äºããåã§ãã£ãŠããããäžåºŠãã¿ã³ãã¯ãªãã¯ããŠã³ãã³ããåå®è¡ã§ããŸãã å®è£ ãè€éã«ããŠã¿ãŸããããã¿ã¹ã¯ã®å®è¡äžã«make CanExecuteãfalseãè¿ãããã«ããŸãã ã€ã³ã¿ãŒãã§ãŒã¹ã¯ãã³ã°ãããã³ãã³ãã¯æ°å䞊è¡ããŠéå§ããããç®æšãéæããŸããã ããããããã¯ãã¹ãŠèªåã®æã§è¡ããªããã°ãªããŸããã ãŸããReactiveUIããŒã ã§ã¯ãããããã¹ãŠãã¯ãããšããå€ãã®ããšãæ¢ã«ç¥ã£ãŠããŸãã
ãªã¢ã¯ãã£ãããŒã
ReactiveCommand <T>ã«äŒããŸãã æ··åããªãã§ãã ããïŒReactiveCommandïŒReactiveUI.Legacyåå空éã«ãããæããã«éæšå¥šã§ãïŒãšããåãååã®éãžã§ããªãã¯å®è£ ããŸã ãããŸãã ãã®ãžã§ããªãã¯ãã©ã¡ãŒã¿ãŒã¯ããã©ã¡ãŒã¿ãŒã®ã¿ã€ãã§ã¯ãªããçµæã®ã¿ã€ãã瀺ããŸãããåŸã§ããã«æ»ããŸãã
CanExecuteã«é¢é£ãããã¹ãŠã®ãã®ããå§ããããšãçç¥ããŠãããã«ã³ãã³ããäœæããŠå®è¡ããŠãã ããã éåžžãnewæŒç®åã䜿çšããŠçŽæ¥ã³ãã³ããäœæããã®ã§ã¯ãªããå¿ èŠãªã¡ãœãããæäŸããéçãªReactiveCommandã¯ã©ã¹ã䜿çšããŸãã
var command = ReactiveCommand.Create(); command.Subscribe(_ => { Console.WriteLine(DateTime.Now.ToLongTimeString() + " "); Thread.Sleep(1000); Console.WriteLine(DateTime.Now.ToLongTimeString() + " "); }); command.Execute(null); Console.WriteLine(DateTime.Now.ToLongTimeString() + " "); Console.ReadLine();
ReactiveCommand.CreateïŒïŒã¡ãœããã¯ãReactiveCommand <object>ã¿ã€ãã®åæã¿ã¹ã¯ãäœæããŸãã ExecuteïŒïŒã¯ãäœæ¥ã®å®äºåŸã«ã®ã¿å¶åŸ¡ãè¿ããŸãã
19:01:07é·ãã¿ã¹ã¯ã®éå§
19:01:08é·ãã¿ã¹ã¯ãå®äºããŸã
19:01:08ããŒã ãéå¶ããåŸ
åŸã§éåæã³ãã³ããäœæããæ¹æ³ãèŠãŠãããŸãããããã§ã¯ã³ãã³ããå®è¡ããæ©èœã®å¶åŸ¡ã«ã€ããŠèŠãŠã¿ãŸãããã
ã³ãã³ããå®è¡ããæ©èœ
CanExecuteãšãã®é¢é£æ©èœã«ã€ããŠèª¬æããŸãã æ¢ã«èŠããã®ïŒCanExecuteã¡ãœãããšCanExecuteChangedã€ãã³ãïŒã«å ããŠãReactiveCommandã¯IsExecutingããã³CanExecuteObservableã·ãŒã±ã³ã¹ãæäŸããŸãã
var command = ReactiveCommand.Create(); command.Subscribe(_ => Console.WriteLine(" ")); command.CanExecuteChanged += (o, a) => Console.WriteLine("CanExecuteChanged event: now CanExecute() == {0}", command.CanExecute(null)); command.IsExecuting.Subscribe(isExecuting => Console.WriteLine("IsExecuting: {0}", isExecuting)); command.CanExecuteObservable.Subscribe(canExecute => Console.WriteLine("CanExecuteObservable: {0}", canExecute)); Console.WriteLine(" , ..."); command.Execute(null); Console.WriteLine(" ");
IsExecutingïŒFalse
CanExecuteObservableïŒFalse
CanExecuteObservableïŒTrue
CanExecuteChangedã€ãã³ãïŒCanExecuteïŒïŒ== Trueã«ãªããŸãã
ãã¹ãŠã賌èªããããŒã ãéå¶ããŠ...
IsExecutingïŒTrue
CanExecuteChangedã€ãã³ãïŒçŸåšCanExecuteïŒïŒ== False
CanExecuteObservableïŒFalse
å®è¡äžã®ã³ãã³ã
IsExecutingïŒFalse
CanExecuteChangedã€ãã³ãïŒCanExecuteïŒïŒ== Trueã«ãªããŸãã
CanExecuteObservableïŒTrue
ã³ãã³ããå®è¡ããåŸ
ãµãã¹ã¯ãªãã·ã§ã³ã®çŽåŸãã³ãã³ããèµ·åãããåã«äœãèµ·ããããç¹ã«æ³šæãæãããšã¯ã§ããŸãããããã¯åæåã§ãã å®éããµãã¹ã¯ãªãã·ã§ã³ãçºçãããšããã«çŸåšã®ç¶æ ãè¿ãããŸãïŒæåã®èŠçŽ ã¯ã³ãŒã«ãã«ãªããåŸç¶ã®èŠçŽ ã¯ãããã«ãªããŸãïŒã ãŸããCanExecuteObservableã¯æåã¯falseã«èšå®ãããŠããŸãã ãµãã¹ã¯ã©ã€ããããšããæåã«ãã®å€ãæäŸãã次ã«ããŒã ã¯å¯çšæ§ã決å®ããã¡ã«ããºã ãæäŸããªãã£ããšå€æããããã©ã«ãã§ã³ãã³ãã䜿çšã§ããããã«ããŸãã
ããã°ã©ã ã®åºåããå€æãããšãã³ãã³ãã¯å®è¡äžã«ãã§ã«äœ¿çšã§ããŸããã ããã¯ç¹ã«éåæã³ãã³ãã®å Žåã«åœãŠã¯ãŸããŸãããã®æ¹æ³ã§ã¯ãè€æ°å䞊åå®è¡ãããŸããã ãããã£ãŠãCanExecuteãCanExecuteObservableãããã³CanExecuteChangedã€ãã³ãã¯ãèšç®ã«æäŸãããã®ã ãã§ãªããã³ãã³ããçŸåšå®è¡ãããŠãããã©ããã«ãäŸåããŸãã IsExecutingã¯ãã³ãã³ããçŸåšå®è¡ãããŠãããã©ããã«é¢ããæ£ç¢ºãªæ å ±ãæäŸããŸããããã¯ãããšãã°ãäœããã®é²è¡ç¶æ³ã€ã³ãžã±ãŒã¿ãŒã衚瀺ããããã«äœ¿çšã§ããŸãã
次ã«ããã€å®è¡ã§ãããã«é¢ããæ å ±ãããŒã ã«æäŸããŸãããã ãããè¡ãããã«ãReactiveCommandã¯ã©ã¹ã§ã³ãã³ããäœæããåã¡ãœããã«ã¯ã IObservable <bool> canExecuteãåãå ¥ãããªãŒããŒããŒãããããŸãã ããŒã ã¯ãã®ã·ãŒã±ã³ã¹ã«ãµãã¹ã¯ã©ã€ãããå€æŽãåä¿¡ãããšå®è¡å¯èœæ§ã«é¢ããæ å ±ãæŽæ°ããŸãã ç§ãã¡ã¯èŠãŸãïŒ
var subject = new Subject<bool>(); var command = ReactiveCommand.Create(subject); command.CanExecuteChanged += (o, a) => Console.WriteLine("CanExecuteChanged event: now CanExecute() == {0}", command.CanExecute(null)); command.CanExecuteObservable.Subscribe(canExecute => Console.WriteLine("CanExecuteObservable: {0}", canExecute)); Console.WriteLine(" "); subject.OnNext(true); Console.WriteLine(" "); subject.OnNext(false); Console.WriteLine(" "); subject.OnNext(false);
ããã§ã®äž»é¡ã¯èŠ³å¯å¯èœãªãã®ã§ãããç§ãã¡ã¯ãããèªåã®æã§å¶åŸ¡ããå¿ èŠãªå€ãããŒã ã«æž¡ããŸãã å°ãªããšããããã¯ãã¹ãæã«éåžžã«äŸ¿å©ã§ãã ç§ãã¡ã¯ãã¹ãŠã«ãµãã¹ã¯ã©ã€ãããå®è¡ãå©çšå¯èœã«ããŠããã2åã¢ã¯ã»ã¹ã§ããªããªããŸãã ã©ã®ãããªçµæãåŸãããŸããïŒ
CanExecuteObservableïŒFalse
å®è¡å¯èœã«ãã
CanExecuteChangedã€ãã³ãïŒCanExecuteïŒïŒ== Trueã«ãªããŸãã
CanExecuteObservableïŒTrue
å®è¡ãã¢ã¯ã»ã¹äžèœã«ãã
CanExecuteChangedã€ãã³ãïŒçŸåšCanExecuteïŒïŒ== False
CanExecuteObservableïŒFalse
ããäžåºŠå®è¡ã«ã¢ã¯ã»ã¹ã§ããªãããã«ãã
ãã¹ãŠãæåŸ ãããŠããããã§ãã æåã¯ãå®è¡ã§ããŸããã ãã®åŸãããŒã ã¯ç§ãã¡ãè¡ã£ãŠããå€æŽã«å¯Ÿå¿ãå§ããŸãã ããã§ãåãã¢ã¯ã»ã·ããªãã£ç¶æ ãé£ç¶ããŠæ°åéä¿¡ãããšãããŒã ã¯åè©Šè¡ãç¡èŠããããšã«æ³šæããŠãã ããã ãŸããCanExecuteObservableã¯boolåã®å€ã®ã·ãŒã±ã³ã¹ã«ããããCanExecuteã¡ãœããã«ãã©ã¡ãŒã¿ãŒããããšããäºå®ãšã®éäºææ§ããããŸãã ReactiveCommandã§ã¯ãåã«ç¡èŠãããŸãã
ã³ãã³ããåŒã³åºãæ¹æ³
æ¢ã«ExecuteïŒïŒã¡ãœããã䜿çšããã³ãã³ãã®åŒã³åºããèŠãŠããŸããã ä»ã®æ¹æ³ãèŠãŠã¿ãŸãããïŒ
IObservable <T> ExecuteAsyncïŒãªããžã§ã¯ããã©ã¡ãŒã¿ãŒïŒ
1ã€ã®ç¹åŸŽããããŸããã³ãã³ãã¯ãExecuteAsyncïŒïŒã®çµæã®ãµãã¹ã¯ãªãã·ã§ã³ãå®äºãããŸã§éå§ãããŸããã ç§ãã¡ã¯ããã䜿çšããŸãïŒ
command.ExecuteAsync().Subscribe();
ãã ããåæã³ãã³ãã¯ããããéåæã«ãªããŸããã ãã¡ãããExecuteAsyncïŒïŒã¯ããã«å¶åŸ¡ãè¿ããŸãããå®è¡ã¯ãŸã éå§ãããŠããŸããïŒ ãããŠããããéå§ããSubscribeïŒïŒã¯ãã³ãã³ãã®å®äºåŸã«ã®ã¿å¶åŸ¡ãè¿ããŸãã å®éãExecuteïŒïŒã«çžåœãããã®ãäœæããŸããã ãã ããããã¯åœç¶ã§ããExecuteAsyncïŒïŒã¯ã³ãŒã«ãã·ãŒã±ã³ã¹ãè¿ããããã«ãµãã¹ã¯ã©ã€ããããšãé·ãã¿ã¹ã¯ã®å®è¡ãéå§ãããããã§ãã ãããŠãããã¯çŸåšã®ã¹ã¬ããã§å®è¡ãããŸãã ããã¯ããµãã¹ã¯ã©ã€ãããå Žæãæ瀺çã«ç€ºãããšã§ä¿®æ£ã§ããŸããã
command.ExecuteAsync().SubscribeOn(TaskPoolScheduler.Default).Subscribe();
TPLã¹ã±ãžã¥ãŒã©ãŒã¯ããµãã¹ã¯ãªãã·ã§ã³ãå®äºãã責任ãè² ããŸãã ãããã£ãŠããµãã¹ã¯ãªãã·ã§ã³ã¯Task.RunïŒïŒã®ãããªãã®ã§è¡ããããã¹ãŠãæ£åžžã«æ©èœããŸãã ããããå®éã«ãããè¡ãããšã¯äŸ¡å€ããªãããã®äŸã¯å¯èœæ§ã®1ã€ã ãã瀺ããŠããŸãã å€ãã®ãã©ã³ããŒãããŸããããã€ããã®ãããã¯ã«è§ŠããŸãã
ã¿ã¹ã¯<T> ExecuteAsyncTaskïŒãªããžã§ã¯ããã©ã¡ãŒã¿ãŒïŒ
ExecuteAsyncïŒïŒãšã¯ç°ãªãããã®ã¡ãœããã¯ã³ãã³ããããã«å®è¡ããŸãã ç§éã¯è©Šã¿ãŸãïŒ
command.ExecuteAsyncTask();
ã¿ã¹ã¯<>ãè¿ãããŸãããã人çã«ã¯ãŸã 幞ãããããŸããã ExecuteAsyncTaskïŒïŒã¯ãã³ãã³ããå®äºããåŸã«ã®ã¿å¶åŸ¡ãè¿ããæ¢ã«å®äºããã¿ã¹ã¯ãæäŸããŸãã äœããã®ã»ããã¢ããã
InvokeCommandïŒïŒ
ãã®ã¡ãœããã䜿çšãããšãä¿¡å·ãã·ãŒã±ã³ã¹ã«è¡šç€ºããããšãã«ã³ãã³ãåŒã³åºããç°¡åã«æ§æã§ããŸãïŒããšãã°ãããããã£ã®å€æŽïŒã ãã®ãããªãã®ïŒ
this.WhenAnyValue(x => x.FullName).Where(x => !string.IsNullOrEmpty(x)).InvokeCommand(this.Search); // this.WhenAnyValue(x => x.FullName).Where(x => !string.IsNullOrEmpty(x)).InvokeCommand(this, x => x.Search); // ,
ãããŸã§ã®ãšãããã³ãã³ããéåæã«å®è¡ããæ¹æ³ã¯èŠã€ãã£ãŠããŸããã ãã¡ãããExecuteAsyncïŒïŒã¡ãœããã䜿çšããŠããµãã¹ã¯ãªãã·ã§ã³ãå®è¡ããã¹ã±ãžã¥ãŒã©ãŒãå²ãåœãŠãããšãã§ããŸãããããã¯æŸèæã§ãã ããã«ãWPFã¯ãã®ã¡ãœãããèªèããŠããªããããExecuteïŒïŒã®åŒã³åºããç¶ããŠé»è©±ãåããŸãã
éåæãªã¢ã¯ãã£ãã³ãã³ã
åæã³ãã³ãã¯ãã¢ã¯ã·ã§ã³ãè¿ éã«å®è¡ããããšãã«æå³ããããç©äºãè€éã«ããããšã¯æå³ããããŸããã ãŸããé·ãã¿ã¹ã¯ã«ã¯éåæã³ãã³ããå¿ èŠã§ãã ããã«ã¯ãReactiveCommand.CreateAsyncObservableïŒïŒãšReactiveCommand.CreateAsyncTaskïŒïŒã®2ã€ã®ã¡ãœããããããŸãã ãããã®éãã¯ãã¢ã¯ã·ã§ã³ãã©ã®ããã«è¡šçŸããããã ãã§ãã ãã®èšäºã®æåã®ã»ã¯ã·ã§ã³ãšéåæã¿ã¹ã¯ã®æ瀺æ¹æ³ã«æ»ããŸãã
CreateAsyncObservableãèŠãŠã¿ãŸãããïŒ
var action = new Action(() => { Console.WriteLine(DateTime.Now.ToLongTimeString() + " "); Thread.Sleep(1000); Console.WriteLine(DateTime.Now.ToLongTimeString() + " "); }); var command = ReactiveCommand.CreateAsyncObservable(_ => Observable.Start(action)); Console.WriteLine(DateTime.Now.ToLongTimeString() + " ..."); command.Execute(42); Console.WriteLine(DateTime.Now.ToLongTimeString() + " "); Console.ReadLine();
2:33:50ããŒã ãéå§ããŸã...
2:33:50ã³ãã³ãå®è¡åŸ
2:33:50é·ãã¿ã¹ã¯ã®éå§
2:33:51é·ãã¿ã¹ã¯ãå®äºãã
ãã£ãïŒ ã³ãã³ããå®äºãããŸã§å®è¡ã¯ãããã¯ãããªããªããã€ã³ã¿ãŒãã§ã€ã¹ã¯ãã³ã°ããŸããã ExecuteAsyncãšExecuteAsyncTaskã®å Žåããã¹ãŠã䌌ãŠããŸããããã¯ã¯ãããŸããã
ä»createAsyncTaskïŒ
var command = ReactiveCommand.CreateAsyncTask(_ => Task.Run(action)); var command = ReactiveCommand.CreateAsyncTask(_ => doSomethingAsync()); // Task<T> var command = ReactiveCommand.CreateAsyncTask(async _ => await doSomethingAsync());
説æãããŠããäž¡æ¹ã®ã¡ãœããã«ã¯ãCanExecuteObservableã®åãæž¡ãããã£ã³ã»ã«æ©èœããµããŒããããªãŒããŒããŒããå€æ°ãããŸãã
ããã«ãéåæã³ãã³ãããçµæãè¿ãããšãã§ããŸãã ReactiveCommand <T>ããã®æ±çšãã©ã¡ãŒã¿ãŒTã¯ãã³ãã³ãã®çµæã®ã¿ã€ãã«ãããŸããã
ReactiveCommand<int> command = ReactiveCommand.CreateAsyncTask(_ => Task.Run(() => 42)); var result = await command.ExecuteAsync(); // result == 42
ãããŠãããªãã¯ããã«ãããã©ããã«åããããšãã§ããŸãïŒ
var command = ReactiveCommand.CreateAsyncTask(_ => Task.Run(() => 42)); command.Subscribe(result => _logger.Log(result)); _answer = command.ToProperty(this, this.Answer); // (ObservableToPropertyHelper)
çµæãUIã¹ããªãŒã ã§è¿ãããããšãä¿èšŒãããŠããŸãã ãããã£ãŠãã¡ãªã¿ã«ãã³ãã³ãã®å®è¡ã«å¯Ÿããåå¿ãšããŠSubscribeã§ããã€ãã®é·ãã¢ã¯ã·ã§ã³ãå®è¡ããããšã¯çŠå¿ã§ãã åæã³ãã³ãã®å Žåãç¬èªã®çµæãè¿ãããšã¯ã§ããŸãããã³ãã³ãã®ã¿ã€ãã¯ReactiveCommand <object>ã§ãããã³ãã³ãã®å®è¡ã«äœ¿çšãããå€ãè¿ãããŸãã
ããŒã ãäœæ¥ãããšãã«çºçããäŸå€ããã£ããããŸã
ã³ãã³ãã®æäœã®äŸå€ã¯ãç¹ã«äœããã®çš®é¡ã®ããŒã¿ã®èªã¿èŸŒã¿ã«é¢ããŠã¯åžžã«çºçããå¯èœæ§ããããŸãã ãããã£ãŠããããããã£ããããŠåŠçããæ¹æ³ãåŠç¿ããå¿ èŠããããŸãã ã©ãã§ã©ã®ããã«ãããè¡ãã®ã§ããïŒ
åæã³ãã³ã
var command = ReactiveCommand.Create(); command.Subscribe(_ => { throw new InvalidOperationException(); }); command.ThrownExceptions.Subscribe(e => Console.WriteLine(e.Message)); command.Execute(null); // command.ExecuteAsync().Subscribe(); // InvalidOperationException await command.ExecuteAsyncTask(); // InvalidOperationException
ãã¹ãŠã®ã¡ãœããã®åŒã³åºãã¯åæçã§ãããããäŸå€ãã¹ããŒãããããšãäºæ³ãããŸãã ããããããã¯ããã»ã©åçŽã§ã¯ãããŸããã ExecuteïŒïŒã¯å®éã«ã¯äŸå€ãã¹ããŒããŸããã ãã¹ãŠã®äŸå€ãåçŽã«åã蟌ãŸãããããªæ¹æ³ã§å®è£ ãããŸãã ä»ã®2ã€ã®ã¡ãœããã¯ãæåŸ ã©ããã«äžåºŠã«äŸå€ãã¹ããŒããŸãã
éåæã³ãã³ãã䜿çšãããšããã¹ãŠãã¯ããã«èå³æ·±ããã®ã«ãªããŸãã
ReactiveCommandã¯ãéåæã³ãã³ãã®å®è¡æã«äŸå€ãã¹ããŒãããThrownExceptionã®ã·ãŒã±ã³ã¹ãæäŸããŸãã ObservableãšTaskã«åºã¥ãããŒã ã«éãã¯ãããŸããã å®éšçšã®ããŒã ãäœæããŸãããïŒ
var command = ReactiveCommand.CreateAsyncTask(_ => Task.Run(() => { throw new InvalidOperationException(); })); /* 1 */ var command = ReactiveCommand.CreateAsyncObservable(_ => Observable.Start(() => { throw new InvalidOperationException(); })); /* 2 */ command.ThrownExceptions.Subscribe(e => Console.WriteLine(e.Message));
ãããŠãã³ãã³ããåŒã³åºãããŸããŸãªæ¹æ³ãè©ŠããŠãã ããïŒ
command.Execute(null); // ThrownExceptions command.ExecuteAsyncTask(); // InvalidOperationException - (Task ) command.ExecuteAsync().Subscribe(); // InvalidOperationException - , Task await command.ExecuteAsync(); // InvalidOperationException ThrownExceptions await command.ExecuteAsyncTask(); // InvalidOperationException ThrownExceptions var subj = new Subject<Unit>(); subj.InvokeCommand(command); subj.OnNext(Unit.Default); // ThrownExceptions
ã³ãã³ãèªäœïŒããšãã°ãcommand.ToPropertyïŒ...ïŒïŒãäœããã®æ¹æ³ã§ãµãã¹ã¯ã©ã€ãããå ŽåãäŸå€ãçºçãããšãOnErrorïŒïŒã³ãã³ãã¯éä¿¡ãããŸããã
ãã®äŸã§ã¯ãäŸå€ããäžåºŠãçºçããäŸã¯å¥åŠã«èŠããŸãã TPLã§ã¯ãããã¯ãã£ãããããªãã£ãäŸå€ããã¬ãŒã¹ãªãã§æ¶ããªãããã«ããããã«å¿ èŠã§ããã ããã«ãThrownExceptionsãä»ããŠãããã転éãããå°æ¥ãã¹ããŒããªãããã«ããããšãã§ããŸããã ããããããã¯å®è£ ã§ãããReactiveUIã®æ¬¡ã®ããŒãžã§ã³ã§ã¯ããã®ç¹ã§äœããå€ããããã§ãã
éåæã³ãã³ãããã£ã³ã»ã«
é·æéå®è¡ã§ããã³ãã³ãã¯ãã£ã³ã»ã«ã§ããŸãã ãããè¡ãã«ã¯å€ãã®æ¹æ³ããããŸãã ãã£ã³ã»ã«ããããŸã§ã¡ãã»ãŒãžãã«ãŒãã§è¡šç€ºããéåæã³ãã³ããäœæããŸãããã
var command = ReactiveCommand.CreateAsyncTask(async (a, t) => { while (!t.IsCancellationRequested) { Console.WriteLine(""); await Task.Delay(300); } Console.WriteLine(""); });
ãã£ã³ã»ã«ããæåã®æ¹æ³ã¯ãExecuteAsyncïŒïŒã«åºã¥ããŠäœæããããµãã¹ã¯ãªãã·ã§ã³ããã£ã³ã»ã«ããããšã§ãã
var disposable = command.ExecuteAsync().Subscribe(); Thread.Sleep(1000); disposable.Dispose();
2çªç®ã®æ¹æ³ã¯ãExecuteAsyncTaskïŒïŒã«ããããŒã¯ã³è»¢éã§ãã
var source = new CancellationTokenSource(); command.ExecuteAsyncTask(ct: source.Token); Thread.Sleep(1000); source.Cancel();
ããããExecuteïŒïŒã¡ãœããã«ãã£ãŠãã€ãŸãWPFèªäœãªã©ããåŒã³åºããããšãã«èµ·åãããã³ãã³ãããã£ã³ã»ã«ãããå Žåã¯ã©ãã§ããããããããç°¡åã§ãããã®ãããIObservableã§Taskãã©ããããTakeUntilïŒïŒã¡ãœããã䜿çšããå¿ èŠããããŸããå¥ã®ã³ãã³ããåŒã³åºããŠãã£ã³ã»ã«ããäŸã瀺ããŸãã
Func<CancellationToken, Task> action = async (ct) => { while (!ct.IsCancellationRequested) { Console.WriteLine(""); await Task.Delay(300); } Console.WriteLine(""); }; IReactiveCommand<object> cancelCommand = null; var runCommand = ReactiveCommand.CreateAsyncObservable(_ => Observable.StartAsync(action).TakeUntil(cancelCommand)); cancelCommand = ReactiveCommand.Create(runCommand.IsExecuting); runCommand.Execute(null); Thread.Sleep(1000); cancelCommand.Execute(null);
ã³ãã³ãã¯ãcancelCommandã·ãŒã±ã³ã¹ã«æ¬¡ã®éç¥ã衚瀺ããããŸã§å®è¡ãããŸããå®éãcancelCommandã®ä»£ããã«ãã³ãã³ãããªããŠãã芳å¯ãããã·ãŒã±ã³ã¹ãããå ŽåããããŸãã
ãããã®ãã¹ãŠã®æ¹æ³ã«ã¯ã埮åŠãªç¹ã1ã€ãããŸãããã£ã³ã»ã«ãéå§ãããšãã³ãã³ãã¯ããã«å®äºããŠåå®è¡å¯èœãšèŠãªãããŸããããã£ã³ã»ã«ããŒã¯ã³ãã¿ã¹ã¯ã«ãã£ãŠç¡èŠãããå Žåãäžéšã®ã¢ã¯ã·ã§ã³ã¯å éšã§ç¶è¡ã§ããŸããããŒã ããã£ã³ã»ã«ãããå Žåããããæ€èšãã䟡å€ããããŸããããã¯ãã¿ã¹ã¯<T>ããŸã£ãããªãã³ãã³ãããã£ã³ã»ã«ããå Žåã«ç¹ã«åœãŠã¯ãŸããŸãã
Action action = () => { ... }; var runCommand = ReactiveCommand.CreateAsyncObservable(_ => Observable.Start(action).TakeUntil(cancelCommand));
ããã§ã¯ãå®è¡ããã£ã³ã»ã«ããåŸã§ãã¢ã¯ã·ã§ã³ãå®è¡ãããã³ãã³ããåã³åŒã³åºãããšãã§ããŸããããã ããã«ãŒãã³ã®åŸãã§èµ·ãããéåžžã«äºæããªãçµæã«ã€ãªããå¯èœæ§ããããŸãã
ããŒã çµ±å
ä»ã®ã³ãã³ããåŒã³åºãã³ãã³ããç°¡åã«äœæã§ããŸãã
RefreshAll = ReactiveCommand.CreateCombined(RefreshNotifications, RefreshMessages);
ãã®å Žåãéä¿¡ãããã»ããã®ãã¹ãŠã®ã³ãã³ããå®è¡å¯èœã§ããã°ãã³ãã³ãã¯å®è¡å¯èœã§ãããŸããå¥ã®canExecuteãæž¡ããŠãã³ãã³ãããã€å®è¡ã§ãããã瀺ãããšãã§ãããªãŒããŒããŒãããããŸãããã®å Žåãåã³ãã³ããå®è¡ããæ©èœãšæž¡ããããã©ã¡ãŒã¿ãŒãèæ ®ãããŸãã
ããŒã ãšã®é£æºã®äŸ
ã³ãã³ãã®äœ¿çšã瀺ãå°ããªäŸãæžããŠã¿ãŸãããã
æ€çŽ¢ãè¡ããŸãããŸããæ¡ä»¶ä»ãæ€çŽ¢ãå®éã1.5ç§éã¢ã¯ãã£ããã£ãã·ãã¥ã¬ãŒãããçµæãšããŠããã€ãã®ã¯ãšãªå€æŽã®ã³ã¬ã¯ã·ã§ã³ãè¿ããŸãããŸããæ€çŽ¢ã®ãã£ã³ã»ã«ãæ°ããæ€çŽ¢ãéå§ãããšãã«å€ãçµæãã¯ãªã¢ããããšãããã³å ¥åããŒã¿ãå€æŽããããšãã«èªåçã«æ€çŽ¢ãå®è¡ããæ©èœããµããŒãããŸãã
ãã¥ãŒã¢ãã«ãèŠãŸãïŒ
public class SearchViewModel : ReactiveObject { [Reactive] public string SearchQuery { get; set; } [Reactive] public bool AutoSearch { get; set; } private readonly ObservableAsPropertyHelper<ICollection<string>> _searchResult; public ICollection<string> SearchResult => _searchResult.Value; public IReactiveCommand<ICollection<string>> Search { get; } public IReactiveCommand<object> CancelSearch { get; } public SearchViewModel() { Search = ReactiveCommand.CreateAsyncObservable( this.WhenAnyValue(vm => vm.SearchQuery).Select(q => !string.IsNullOrEmpty(q)), _ => Observable.StartAsync(ct => SearchAsync(SearchQuery, ct)).TakeUntil(CancelSearch) ); CancelSearch = ReactiveCommand.Create(Search.IsExecuting); Observable.Merge( Search, Search.IsExecuting.Where(e => e).Select(_ => new List<string>())) .ToProperty(this, vm => vm.SearchResult, out _searchResult); this.WhenAnyValue(vm => vm.SearchQuery) .Where(x => AutoSearch) .Throttle(TimeSpan.FromSeconds(0.3), RxApp.MainThreadScheduler) .InvokeCommand(Search); } private async Task<ICollection<string>> SearchAsync(string query, CancellationToken token) { await Task.Delay(1500, token); return new List<string>() { query, query.ToUpper(), new string(query.Reverse().ToArray()) }; } }
ãã¡ãããããã«ã¯æ¬ é¥ããããŸãããããã®1ã€ã¯èªåæ€çŽ¢ã§ãããŠãŒã¶ãŒãæ€çŽ¢äžã«ã¯ãšãªãå€æŽããå ŽåãçŸåšã®æ€çŽ¢ã¯åæ¢ããããæåã«å®äºããŠãããæ°ããã¯ãšãªãæ€çŽ¢ãããŸãããã ãããããä¿®æ£ããã«ã¯æ°è¡ã®åé¡ããããŸãããŸãã¯ããŠãŒã¶ãŒãã¯ãšãªå šäœãæ¶å»ãããšãã«æ€çŽ¢çµæãã¯ãªã¢ããªãã®ã¯å¥åŠã§ãããããããã®ãããªè€éãªäŸã¯æ¬¡ã®éšåã«ä»»ããŸãããä»ã®ãšããã¯æ¢åã®ããžãã¯ã«éå®ããŸããç¹°ãè¿ãã«ãªããŸãããäžè¬ã«ãæ€çŽ¢ãšã³ãžã³ã®æãåå§çãªåäœã§ã¯ãªããéåžžã«ç°¡æœãã€æ確ã«èª¬æãããŠãããšããäºå®ã«æ³šæãåããŸãã
XAMLãèŠãŠã¿ãŸãããã
<Grid DataContext="{Binding ViewModel, ElementName=Window}"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <StackPanel> <Label>Search query:</Label> <TextBox Margin="10, 5" Text="{Binding SearchQuery, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /> </StackPanel> <ListBox Grid.Row="1" ItemsSource="{Binding SearchResult}"/> <Grid Grid.Row="2"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"></ColumnDefinition> <ColumnDefinition Width="Auto"></ColumnDefinition> </Grid.ColumnDefinitions> <ProgressBar Margin="10" x:Name="SearchExecutingProgressBar" /> <StackPanel Orientation="Horizontal" Grid.Column="1"> <CheckBox VerticalAlignment="Center" IsChecked="{Binding AutoSearch, Mode=TwoWay}">Auto search</CheckBox> <Button Margin="10" Command="{Binding Search}">Run</Button> <Button Margin="10" Command="{Binding CancelSearch}">Cancel</Button> </StackPanel> </Grid> </Grid>
ããã§ã®è³ªåã¯ProgressBarãåŒãèµ·ããå¯èœæ§ããããŸããæ€çŽ¢ããã»ã¹ã«å«ããããšãæãã§ããŸããããã ããSearchã³ãã³ãã§ã¯ãIsExecutingããããã£ã¯ããŒã«ã§ã¯ãªããã·ãŒã±ã³ã¹ã§ãããXAMLã§ã®ãã€ã³ãã¯æ©èœããŸããããããã£ãŠããã¥ãŒã®ã³ã³ã¹ãã©ã¯ã¿ãŒã§ãã€ã³ãããŸãã
public partial class MainWindow : Window { public SearchViewModel ViewModel { get; } public MainWindow() { ViewModel = new SearchViewModel(); InitializeComponent(); this.WhenAnyObservable(w => w.ViewModel.Search.IsExecuting).BindTo(SearchExecutingProgressBar, pb => pb.IsIndeterminate); } }
ã¯ããReactiveUIã¯ãã®ãããªãã€ã³ãã£ã³ã°ããµããŒãããŠãããçè«çã«ã¯ãã®æ¹æ³ã§ãã¹ãŠãè¡ãããšãã§ããŸãããããããã€ã³ãã£ã³ã°ã«ã€ããŠã¯å¥ã®æ©äŒã«è©±ãããŸãããä»ã®ãšãããç§ã¯èªåããªããŠã¯ãªããªãããšã ãã«å¶éããŠããŸãã
çµæãèŠãŠã¿ãŸããã
ãã£ãïŒããã¯æ£åžžã«æ©èœããæ€çŽ¢äžã«ã€ã³ã¿ãŒãã§ã€ã¹ããã³ã°ããããã£ã³ã»ã«ãåäœããèªåæ€çŽ¢ãåäœã
次ã®ãšããœãŒãã§
ããã§ãå°ãèŠçŽããŸãããã®ããŒãã§ã¯ãã¿ã¹ã¯<T>ãšIObservable <T>ã®é¢ä¿ã調ã¹ãŸããããããã·ãŒã±ã³ã¹ãšã³ãŒã«ãã·ãŒã±ã³ã¹ãæ¯èŒããŸãããããããç§ãã¡ã®äž»ãªãããã¯ã¯ããŒã ã§ãããåæã³ãã³ããšéåæã³ãã³ããäœæããããããç°ãªãæ¹æ³ã§åŒã³åºãæ¹æ³ãåŠã³ãŸãããããããå®è¡ããæ©èœãæå¹ãŸãã¯ç¡å¹ã«ããæ¹æ³ãããã³éåæã³ãã³ãã§ãšã©ãŒããã£ããããæ¹æ³ãèŠã€ããŸãããããã«ãéåæã³ãã³ãããã£ã³ã»ã«ããæ¹æ³ãèŠã€ããŸããã
ãã®éšåã§ã¯ããã¥ãŒã¢ãã«ã®ãã¹ãã«è§Šãããã£ãã®ã§ãããã©ãããããããããŒã ããã®ãããªã·ãŒãã«æ¡åŒµããããšã¯èšç®ããŸããã§ããããããã£ãŠãä»åã¯ããã§ã¯ãããŸããã次ã®ããŒãã§ã¯ããã€ã³ãã£ã³ã°ãŸãã¯ãã¹ããšãã©ã³ããŒã®ãããããæ€èšããŸãã
åãæ¿ããªãã§ãã ããïŒ