public IObservable<bool> GetActivationForView(IActivatable view) { var control = view as Control; if (control == null) { // Show a friendly warning in the log that this view will never be activated this.Log().Warn("Expected a view of type System.Windows.Forms.Control but it is {0}.\r\nYou need to implement your own IActivationForViewFetcher for {0}.", view.GetType()); return Observable.Empty<bool>(); } // Create an observable stream of booleans // true representing the control is active, false representing the control is not active // by using DistinctUntilChanged, a control can either be active or not active // This should also fix #610 for winforms var controlVisible = Observable.FromEventPattern(control, "VisibleChanged").Select(_ => control.Visible); var handleDestroyed = Observable.FromEventPattern(control, "HandleDestroyed").Select(_ => false); var handleCreated = Observable.FromEventPattern(control, "HandleCreated").Select(_ => true); var controlActive = Observable.Merge(controlVisible, handleDestroyed, handleCreated) .DistinctUntilChanged(); var form = view as Form; if (form != null) { var formActive = Observable.FromEventPattern(form, "Closed").Select(_ => false); return controlActive.Merge(formActive).DistinctUntilChanged(); } return controlActive; }
/// <summary> /// WhenActivated allows you to register a Func to be called when a /// View is Activated. /// </summary> /// <param name="block">The method to be called when the corresponding /// View is activated. It returns a list of Disposables that will be /// cleaned up when the View is deactivated.</param> /// <returns>A Disposable that deactivates this registration.</returns> public static IDisposable WhenActivated(this IActivatable This, Func <IEnumerable <IDisposable> > block) { var activationFetcher = activationFetcherCache.Get(This.GetType()); if (activationFetcher == null) { var msg = "Don't know how to detect when {0} is activated/deactivated, you may need to implement IActivationForViewFetcher"; throw new ArgumentException(String.Format(msg, This.GetType().FullName)); } var activationEvents = activationFetcher.GetActivationForView(This); var vmDisposable = Disposable.Empty; if (This is IViewFor) { vmDisposable = handleViewModelActivation(This as IViewFor, activationEvents); } var viewDisposable = handleViewActivation(block, activationEvents); return(new CompositeDisposable(vmDisposable, viewDisposable)); }
/// <summary> /// WhenActivated allows you to register a Func to be called when a /// View is Activated. /// </summary> /// <param name="this">Object that supports activation.</param> /// <param name="block"> /// The method to be called when the corresponding /// View is activated. It returns a list of Disposables that will be /// cleaned up when the View is deactivated. /// </param> /// <param name="view"> /// The IActivatable will ordinarily also host the View /// Model, but in the event it is not, a class implementing <see cref="IViewFor" /> /// can be supplied here. /// </param> /// <returns>A Disposable that deactivates this registration.</returns> public static IDisposable WhenActivated(this IActivatable @this, Func <IEnumerable <IDisposable> > block, IViewFor view) { var activationFetcher = activationFetcherCache.Get(@this.GetType()); if (activationFetcher == null) { const string msg = "Don't know how to detect when {0} is activated/deactivated, you may need to implement IActivationForViewFetcher"; throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, msg, @this.GetType().FullName)); } var activationEvents = activationFetcher.GetActivationForView(@this); var vmDisposable = Disposable.Empty; if ((view ?? @this) is IViewFor v) { vmDisposable = HandleViewModelActivation(v, activationEvents); } var viewDisposable = HandleViewActivation(block, activationEvents); return(new CompositeDisposable(vmDisposable, viewDisposable)); }
/// <inheritdoc/> public IObservable <bool> GetActivationForView(IActivatable view) { // Startup: Control.HandleCreated > Control.BindingContextChanged > Form.Load > Control.VisibleChanged > Form.Activated > Form.Shown // Shutdown: Form.Closing > Form.FormClosing > Form.Closed > Form.FormClosed > Form.Deactivate // https://docs.microsoft.com/en-us/dotnet/framework/winforms/order-of-events-in-windows-forms if (view is Control control) { if (GetCachedIsDesignMode(control)) { return(Observable <bool> .Empty); } var handleDestroyed = Observable.FromEventPattern(control, "HandleDestroyed").Select(_ => false); var handleCreated = Observable.FromEventPattern(control, "HandleCreated").Select(_ => true); var visibleChanged = Observable.FromEventPattern(control, "VisibleChanged").Select(_ => control.Visible); var controlActivation = Observable.Merge(handleDestroyed, handleCreated, visibleChanged) .DistinctUntilChanged(); if (view is Form form) { var formClosed = Observable.FromEventPattern(form, "FormClosed").Select(_ => false); controlActivation = controlActivation.Merge(formClosed) .DistinctUntilChanged(); } return(controlActivation); } // Show a friendly warning in the log that this view will never be activated this.Log().Warn( CultureInfo.InvariantCulture, "Expected a view of type System.Windows.Forms.Control but it is {0}.\r\nYou need to implement your own IActivationForViewFetcher for {0}.", view?.GetType()); return(Observable <bool> .Empty); }
public IObservable <bool> GetActivationForView(IActivatable view) { var control = view as Control; if (control == null) { // Show a friendly warning in the log that this view will never be activated this.Log().Warn("Expected a view of type System.Windows.Forms.Control but it is {0}.\r\nYou need to implement your own IActivationForViewFetcher for {0}.", view.GetType()); return(Observable <bool> .Empty); } // Create an observable stream of booleans // true representing the control is active, false representing the control is not active // by using DistinctUntilChanged, a control can either be active or not active // This should also fix #610 for winforms var controlVisible = Observable.FromEventPattern(control, "VisibleChanged").Select(_ => control.Visible); var handleDestroyed = Observable.FromEventPattern(control, "HandleDestroyed").Select(_ => false); var handleCreated = Observable.FromEventPattern(control, "HandleCreated").Select(_ => true); var controlActive = Observable.Merge(controlVisible, handleDestroyed, handleCreated) .DistinctUntilChanged(); var form = view as Form; if (form != null) { var formActive = Observable.FromEventPattern(form, "Closed").Select(_ => false); return(controlActive.Merge(formActive).DistinctUntilChanged()); } return(controlActive); }