public MainWindowViewModel(ILifetimeScope lifetimeScope, IUIDispatcher dispatcher, AppSettings settings, ITauronEnviroment enviroment, ProfileManager profileManager, CalculationManager calculation, SystemClock clock, IEventAggregator aggregator) : base(lifetimeScope, dispatcher) { SnackBarQueue = RegisterProperty <SnackbarMessageQueue?>(nameof(SnackBarQueue)); dispatcher.InvokeAsync(() => new SnackbarMessageQueue(TimeSpan.FromSeconds(10))) .Subscribe(SnackBarQueue); CurrentProfile = RegisterProperty <string>(nameof(CurrentProfile)); AllProfiles = this.RegisterUiCollection <string>(nameof(AllProfiles)) .BindToList(settings.AllProfiles, out var list); aggregator.ConsumeErrors().Subscribe(ReportError).DisposeWith(this); #region Profile Selection IsProcessable = RegisterProperty <bool>(nameof(IsProcessable)); profileManager.IsProcessable .Subscribe(IsProcessable) .DisposeWith(this); ProfileState = RegisterProperty <string>(nameof(ProfileState)); profileManager.IsProcessable .Select(b => b ? $"{CurrentProfile.Value} Geladen" : "nicht Geladen") .AutoSubscribe(ProfileState, ReportError); var loadTrigger = new Subject <string>(); (from newProfile in CurrentProfile where !list.Items.Contains(newProfile) select newProfile) .Throttle(TimeSpan.FromSeconds(5)) .AutoSubscribe(s => { if (string.IsNullOrWhiteSpace(s)) { return; } settings.AllProfiles = settings.AllProfiles.Add(s); list.Add(s); loadTrigger.OnNext(s); }, ReportError) .DisposeWith(this); (from profile in CurrentProfile where list.Items.Contains(profile) select profile) .Subscribe(loadTrigger) .DisposeWith(this); #endregion Configurate = NewCommad.WithCanExecute(profileManager.IsProcessable) .WithFlow(obs => (from _ in obs from res in this.ShowDialogAsync <ConfigurationDialog, Unit, ConfigurationManager>(() => profileManager.ConfigurationManager) select res) .AutoSubscribe(ReportError)) .ThenRegister(nameof(Configurate)); profileManager.CreateFileLoadPipeline(loadTrigger).DisposeWith(this); HoursAll = RegisterProperty <string>(nameof(HoursAll)); //profileManager.ProcessableData // .Select(pd => pd.AllHours) // .DistinctUntilChanged() // .Select(i => i.ToString()) // .ObserveOn(Scheduler.Default) // .Get(HoursAll).DisposeWith(this); #region Entrys var isHere = false.ToRx().DisposeWith(this); ProfileEntries = this.RegisterUiCollection <UiProfileEntry>(nameof(ProfileEntries)) .BindTo(profileManager.ConnectCache() .Select(entry => new UiProfileEntry(entry, profileManager.ProcessableData, ReportError))); profileManager.ConnectCache() .AutoSubscribe(_ => CheckHere(), aggregator.ReportError) .DisposeWith(this); dispatcher.InvokeAsync(() => { var view = (ListCollectionView)CollectionViewSource.GetDefaultView(ProfileEntries.Property.Value); view.CustomSort = Comparer <UiProfileEntry> .Default; }); (from data in profileManager.ProcessableData.DistinctUntilChanged(pd => pd.Entries) where data.Entries.Count != 0 select Unit.Default) .AutoSubscribe(_ => CheckHere(), ReportError) .DisposeWith(this); Come = NewCommad .WithCanExecute(profileManager.IsProcessable) .WithCanExecute(from here in isHere select !here) .WithParameterFlow <ModiferBox>( obs => profileManager.Come(from box in obs select new ComeParameter(clock.NowDate, box != null && box.Keys.HasFlag(ModifierKeys.Control))) .AutoSubscribe(b => { if (b) { CheckHere(); } else { SnackBarQueue.Value?.Enqueue("Tag Schon eingetragen"); } }, ReportError)) .ThenRegister(nameof(Come)); Go = NewCommad .WithCanExecute(profileManager.IsProcessable) .WithCanExecute(isHere) .WithFlow(() => clock.NowDate, obs => profileManager.Go(obs) .AutoSubscribe(b => { if (b) { CheckHere(); } else { SnackBarQueue.Value?.Enqueue("Tag nicht gefunden"); } }, ReportError)) .ThenRegister(nameof(Go)); void CheckHere() { (from item in profileManager.Entries where item.Start != null && item.Finish == null orderby item.Date select item).FirstOrDefault() .OptionNotNull() .Run(_ => isHere !.Value = true, () => isHere !.Value = false); } Vacation = NewCommad .WithFlow(obs => (from _ in obs from data in profileManager.ProcessableData.Take(1) from result in this.ShowDialogAsync <VacationDialog, DateTime[]?, DateTime>(() => data.CurrentMonth) where result != null from res in profileManager.AddVacation(result) select res) .AutoSubscribe(ReportError)) .WithCanExecute(IsProcessable) .ThenRegister(nameof(Vacation)); #endregion #region Correction CurrentEntry = RegisterProperty <UiProfileEntry?>(nameof(CurrentEntry)); Correct = NewCommad .WithCanExecute(profileManager.IsProcessable) .WithCanExecute(from entry in CurrentEntry select entry != null) .WithFlow(obs => (from _ in obs let oldEntry = CurrentEntry.Value where oldEntry != null from dialogResult in this.ShowDialogAsync <CorrectionDialog, CorrectionResult, ProfileEntry>(() => oldEntry.Entry) from result in dialogResult switch { UpdateCorrectionResult update => profileManager.UpdateEntry(update.Entry, oldEntry.Entry.Date), DeleteCorrectionResult delete => profileManager.DeleteEntry(delete.Key).Select(_ => string.Empty), _ => Observable.Return(string.Empty) } select result) .AutoSubscribe(s => { if (!string.IsNullOrWhiteSpace(s)) { SnackBarQueue.Value?.Enqueue(s); } else { CheckHere(); } }, aggregator.ReportError)) .ThenRegister(nameof(Correct)); AddEntry = NewCommad .WithCanExecute(IsProcessable) .WithFlow(obs => (from _ in obs from data in profileManager.ProcessableData.Take(1) let parameter = new AddEntryParameter(data.Entries.Select(pe => pe.Value.Date.Day).ToHashSet(), data.CurrentMonth) from result in this.ShowDialogAsync <AddEntryDialog, AddEntryResult, AddEntryParameter>(() => parameter) from u in result switch { NewAddEntryResult entry => profileManager.AddEntry(entry.Entry), _ => Observable.Return(Unit.Default) } select u) .AutoSubscribe(_ => CheckHere(), ReportError)) .ThenRegister(nameof(AddEntry)); #endregion #region Calculation Remaining = RegisterProperty <int>(nameof(Remaining)); CurrentState = RegisterProperty <MonthState>(nameof(CurrentState)) .WithDefaultValue(MonthState.Minus); calculation.AllHours .Select(ts => ts.TotalHours) .Select(h => { return(h switch { 0 when InValidConfig() => "Konfiguration!", 0 => string.Empty, _ => h.ToString("F0") }); bool InValidConfig() => profileManager.ConfigurationManager.DailyHours == 0 && profileManager.ConfigurationManager.MonthHours == 0; })