public void IgnoreInitErrorAndForceNotify() { var rp = new ReactiveProperty <string>(mode: ReactivePropertyMode.Default | ReactivePropertyMode.IgnoreInitialValidationError) .SetValidateNotifyError(x => string.IsNullOrEmpty(x) ? "error" : null); rp.HasErrors.IsFalse(); rp.ForceNotify(); rp.HasErrors.IsTrue(); }
public void ForceNotify() { var rp = new ReactiveProperty <int>(0); var collector = new List <int>(); rp.Subscribe(collector.Add); collector.Is(0); rp.ForceNotify(); collector.Is(0, 0); }
public BaseSetting() { // 通知可能なプロパティを取得し、それらに変更があればSettingChangedを発火させる var notifyProperties = GetType().GetProperties() .Where(x => x.PropertyType.GetInterfaces().Any(y => y == typeof(INotifyPropertyChanged)) && x.Name != nameof(SettingChanged)); foreach (var p in notifyProperties) { var o = p.GetValue(this) as INotifyPropertyChanged; if (o != null) { o.PropertyChanged += (s, e) => _settingChanged.ForceNotify(); } } }
public MainWindowViewModel() { DatabaseValue = new ReactiveProperty <string>(); InitCommand = new ReactiveCommand <string>() .WithSubscribe(isDatabaseEmpty => { _dbValueUpdating.SwitchValue(); using (Disposable.Create(() => _dbValueUpdating.SwitchValue())) { DatabaseValue.Value = bool.Parse(isDatabaseEmpty) ? null : "xxxx"; DatabaseValue.ForceNotify(); } }); InputValue = DatabaseValue.ToReactiveProperty(); CommandText = Observable.Merge( DatabaseValue.Select(x => IsDbValueEmpty(x)).Select(x => x ? "A" : "B"), InputValue.Where(_ => !_dbValueUpdating.Value).Select(_ => "A")) .ToReadOnlyReactiveProperty(); }
internal HandleViewModel(Handle handle, Train train) { HandleType = handle .ToReactivePropertyAsSynchronized(x => x.HandleType) .AddTo(disposable); PowerNotches = handle .ToReactivePropertyAsSynchronized(x => x.PowerNotches, ignoreValidationErrorValue: true) .AddTo(disposable); PowerNotches.Subscribe(_ => train.ApplyPowerNotchesToCar()).AddTo(disposable); BrakeNotches = handle .ToReactivePropertyAsSynchronized(x => x.BrakeNotches, ignoreValidationErrorValue: true) .SetValidateNotifyError(x => { if (x == 0 && train.Device.HoldBrake) { return("BrakeNotches must be at least 1 if HoldBrake is set."); } return(null); }) .AddTo(disposable); BrakeNotches.Subscribe(_ => train.ApplyBrakeNotchesToCar()).AddTo(disposable); PowerNotchReduceSteps = handle .ToReactivePropertyAsSynchronized(x => x.PowerNotchReduceSteps) .AddTo(disposable); HandleBehaviour = handle .ToReactivePropertyAsSynchronized(x => x.HandleBehaviour) .AddTo(disposable); LocoBrake = handle .ToReactivePropertyAsSynchronized(x => x.LocoBrake) .AddTo(disposable); LocoBrakeNotches = handle .ToReactivePropertyAsSynchronized(x => x.LocoBrakeNotches) .AddTo(disposable); LocoBrakeNotches.Subscribe(_ => train.ApplyLocoBrakeNotchesToCar()).AddTo(disposable); DriverPowerNotches = handle .ToReactivePropertyAsSynchronized(x => x.DriverPowerNotches, ignoreValidationErrorValue: true) .AddTo(disposable); DriverBrakeNotches = handle .ToReactivePropertyAsSynchronized(x => x.DriverBrakeNotches, ignoreValidationErrorValue: true) .AddTo(disposable); PowerNotches .SetValidateNotifyError(x => { if (x < DriverPowerNotches.Value) { return("DriverPowerNotches must be less than or equal to PowerNotches."); } return(null); }) .Subscribe(_ => DriverPowerNotches.ForceValidate()) .AddTo(disposable); PowerNotches .ObserveHasErrors .ToReadOnlyReactivePropertySlim(mode: ReactivePropertyMode.DistinctUntilChanged) .Where(x => !x) .Subscribe(_ => PowerNotches.ForceNotify()) .AddTo(disposable); BrakeNotches .SetValidateNotifyError(x => { if (x < DriverBrakeNotches.Value) { return("DriverBrakeNotches must be less than or equal to BrakeNotches."); } return(null); }) .Subscribe(_ => DriverBrakeNotches.ForceValidate()) .AddTo(disposable); BrakeNotches .ObserveHasErrors .ToReadOnlyReactivePropertySlim(mode: ReactivePropertyMode.DistinctUntilChanged) .Where(x => !x) .Subscribe(_ => BrakeNotches.ForceNotify()) .AddTo(disposable); DriverPowerNotches .SetValidateNotifyError(x => { if (x > PowerNotches.Value) { return("DriverPowerNotches must be less than or equal to PowerNotches."); } return(null); }) .Subscribe(_ => PowerNotches.ForceValidate()) .AddTo(disposable); DriverPowerNotches .ObserveHasErrors .ToReadOnlyReactivePropertySlim(mode: ReactivePropertyMode.DistinctUntilChanged) .Where(x => !x) .Subscribe(_ => DriverPowerNotches.ForceNotify()) .AddTo(disposable); DriverBrakeNotches .SetValidateNotifyError(x => { if (x > BrakeNotches.Value) { return("DriverBrakeNotches must be less than or equal to BrakeNotches."); } return(null); }) .Subscribe(_ => BrakeNotches.ForceValidate()) .AddTo(disposable); DriverBrakeNotches .ObserveHasErrors .ToReadOnlyReactivePropertySlim(mode: ReactivePropertyMode.DistinctUntilChanged) .Where(x => !x) .Subscribe(_ => DriverBrakeNotches.ForceNotify()) .AddTo(disposable); }
public void ForceNotify() { var rp = new ReactiveProperty<int>(0); var collecter = new List<int>(); rp.Subscribe(collecter.Add); collecter.Is(0); rp.ForceNotify(); collecter.Is(0, 0); }
void UpdateLoop() { UpdateLogic.ForceNotify(); }
public FeedGroupPageViewModel(HohoemaApp hohoemaApp, PageManager pageManager, Views.Service.ContentSelectDialogService contentSelectDialogService) : base(hohoemaApp, pageManager) { ContentSelectDialogService = contentSelectDialogService; IsDeleted = new ReactiveProperty <bool>(); FeedGroupName = new ReactiveProperty <string>(); MylistFeedSources = new ObservableCollection <FeedItemSourceListItem>(); TagFeedSources = new ObservableCollection <FeedItemSourceListItem>(); UserFeedSources = new ObservableCollection <FeedItemSourceListItem>(); HasMylistFeedSource = MylistFeedSources.ObserveProperty(x => x.Count) .Select(x => x > 0) .ToReadOnlyReactiveProperty(); HasTagFeedSource = TagFeedSources.ObserveProperty(x => x.Count) .Select(x => x > 0) .ToReadOnlyReactiveProperty(); HasUserFeedSource = UserFeedSources.ObserveProperty(x => x.Count) .Select(x => x > 0) .ToReadOnlyReactiveProperty(); MylistFavItems = new ObservableCollection <FollowItemInfo>(); TagFavItems = new ObservableCollection <FollowItemInfo>(); UserFavItems = new ObservableCollection <FollowItemInfo>(); SelectFromFavItems = new ReactiveProperty <bool>(true); SelectedFavInfo = new ReactiveProperty <FollowItemInfo>(); FavItemType = new ReactiveProperty <FollowItemType>(); FeedSourceId = new ReactiveProperty <string>(); FeedSourceItemName = new ReactiveProperty <string>(); ExistFeedSource = new ReactiveProperty <bool>(); IsPublicFeedSource = new ReactiveProperty <bool>(); CanUseFeedSource = Observable.CombineLatest( ExistFeedSource, IsPublicFeedSource ) .Select(x => x.All(y => y)) .ToReactiveProperty(); FavItemType.Subscribe(x => { FeedSourceId.Value = ""; ExistFeedSource.Value = false; FeedSourceItemName.Value = ""; // お気に入りアイテムがある場合は、「お気に入りから選択」をデフォルトに switch (x) { case FollowItemType.Tag: SelectFromFavItems.Value = TagFavItems.Count > 0; break; case FollowItemType.Mylist: SelectFromFavItems.Value = MylistFavItems.Count > 0; break; case FollowItemType.User: SelectFromFavItems.Value = UserFavItems.Count > 0; break; default: break; } }); FeedSourceId.ToUnit() .Subscribe(_ => { ExistFeedSource.Value = false; FeedSourceItemName.Value = ""; }); Observable.Merge( SelectFromFavItems.ToUnit(), SelectedFavInfo.ToUnit(), FavItemType.ToUnit(), FeedSourceId.ToUnit().Throttle(TimeSpan.FromSeconds(1)) ) .Subscribe(async x => { if (SelectFromFavItems.Value) { ExistFeedSource.Value = SelectedFavInfo.Value != null; IsPublicFeedSource.Value = true; FeedSourceItemName.Value = ""; return; } ExistFeedSource.Value = false; if (FavItemType.Value == FollowItemType.Tag) { ExistFeedSource.Value = !string.IsNullOrWhiteSpace(FeedSourceId.Value); IsPublicFeedSource.Value = true; FeedSourceItemName.Value = FeedSourceId.Value; } else { if (string.IsNullOrWhiteSpace(FeedSourceId.Value)) { ExistFeedSource.Value = false; } else { if (FavItemType.Value == FollowItemType.Mylist) { try { var mylistRes = await HohoemaApp.ContentFinder.GetMylistGroupDetail(FeedSourceId.Value); var mylist = mylistRes?.MylistGroup; if (mylist != null) { ExistFeedSource.Value = true; IsPublicFeedSource.Value = mylist.IsPublic; FeedSourceItemName.Value = Mntone.Nico2.StringExtention.DecodeUTF8(mylist.Name); } } catch { ExistFeedSource.Value = false; } } else if (FavItemType.Value == FollowItemType.User) { try { var user = await HohoemaApp.ContentFinder.GetUserDetail(FeedSourceId.Value); if (user != null) { ExistFeedSource.Value = true; IsPublicFeedSource.Value = !user.IsOwnerVideoPrivate; FeedSourceItemName.Value = user.Nickname; } } catch { ExistFeedSource.Value = false; } } if (!ExistFeedSource.Value) { IsPublicFeedSource.Value = false; FeedSourceItemName.Value = ""; } } } }); AddFeedCommand = Observable.CombineLatest( ExistFeedSource, IsPublicFeedSource ) .Select(x => x.All(y => y == true)) .ToReactiveCommand(); AddFeedCommand.Subscribe(_ => { string name = ""; string id = ""; if (SelectFromFavItems.Value) { var favInfo = SelectedFavInfo.Value; name = favInfo.Name; id = favInfo.Id; if (favInfo.FollowItemType != FavItemType.Value) { throw new Exception(); } } else { // idからMylistGroupを引く // 公開されていない場合にはエラー id = FeedSourceId.Value; name = FeedSourceItemName.Value; FeedSourceItemName.Value = ""; FeedSourceId.Value = ""; } var favManager = HohoemaApp.FollowManager; var feedManager = HohoemaApp.FeedManager; IFeedSource feedSource; switch (FavItemType.Value) { case FollowItemType.Tag: feedSource = FeedGroup.AddTagFeedSource(id); if (feedSource != null) { var favInfo = favManager.Tag.FollowInfoItems.SingleOrDefault(x => x.Id == id); if (favInfo != null) { TagFavItems.Remove(favInfo); } TagFeedSources.Add(new FeedItemSourceListItem(feedSource, this)); } break; case FollowItemType.Mylist: feedSource = FeedGroup.AddMylistFeedSource(name, id); if (feedSource != null) { var favInfo = favManager.Mylist.FollowInfoItems.SingleOrDefault(x => x.Id == id); if (favInfo != null) { MylistFavItems.Remove(favInfo); } MylistFeedSources.Add(new FeedItemSourceListItem(feedSource, this)); } break; case FollowItemType.User: feedSource = FeedGroup.AddUserFeedSource(name, id); if (feedSource != null) { var favInfo = favManager.User.FollowInfoItems.SingleOrDefault(x => x.Id == id); if (favInfo != null) { UserFavItems.Remove(favInfo); } UserFeedSources.Add(new FeedItemSourceListItem(feedSource, this)); } break; default: break; } HohoemaApp.FeedManager.SaveOne(FeedGroup); }); RenameApplyCommand = FeedGroupName .Where(x => HohoemaApp.FeedManager != null && x != null) .Select(x => HohoemaApp.FeedManager.CanAddLabel(x)) .ToReactiveCommand(); RenameApplyCommand.Subscribe(async _ => { if (await FeedGroup.Rename(FeedGroupName.Value)) { UpdateTitle(FeedGroup.Label); } FeedGroupName.ForceNotify(); }); }
/// <summary> /// 新しいインスタンスを初期化します。 /// </summary> public MainWindowViewModel() { // set PdfPath = new ReactiveProperty <string>(); Password = new ReactiveProperty <string>(); var isExistsPdf = PdfPath .Select(x => x ?? string.Empty) .Select(x => x.Trim('"')) .Select(x => File.Exists(x)); var hasPassword = Password .Select(x => !string.IsNullOrWhiteSpace(x)); Status = Observable.CombineLatest( isExistsPdf, hasPassword, (x, y) => !x ? "PDF ファイルを選択してください" : !y ? "パスワードを入力してください" : "[ENTER] キーまたは [UNLOCK] ボタンを押してください") .ToReactiveProperty(); SelectFileCommand = new ReactiveCommand(); UnlockCommand = Observable.CombineLatest( isExistsPdf, hasPassword, (x, y) => x && y) .ToReactiveCommand(); // subscribe SelectFileCommand .Subscribe(_ => { var dialog = new OpenFileDialog() { Filter = "PDF (*.pdf)|*.pdf" }; if (dialog.ShowDialog() == true) { PdfPath.Value = dialog.FileName; } }); UnlockCommand .Subscribe(_ => { var trimmedPdfPath = PdfPath.Value.Trim('"'); if (File.Exists(trimmedPdfPath)) { var destinationPath = PathHelper.CreateUniquePath( Path.GetDirectoryName(trimmedPdfPath), Path.ChangeExtension(trimmedPdfPath, null) + "_unlocked.pdf"); try { PdfUnlocker.Unlock(trimmedPdfPath, destinationPath, Password.Value); Password.Value = null; Status.Value = "PDF ファイルのパスワードを解除しました"; PathHelper.OpenExplorerWithSelected(destinationPath); } catch (BadPasswordException) { Password.Value = null; Status.Value = "正しいパスワードを入力してください"; } catch (InvalidPdfException) { Status.Value = "PDF ファイルが開けませんでした"; } } else { PdfPath.ForceNotify(); } }); }