/// <inheritdoc /> public async Task <bool> ComposeAsync(IViewCompositionContext context) { try { DataContextLoadedCompletion = new TaskCompletionSource <object>(); SetCoordinationArguments(context.Control, context.CoordinationArguments); Log.Debug($"Composition is being configured."); Configure(context); Log.Debug($"Attaching DataContextChanged and Unload events."); context.Control.DataContextChanged -= DataContextChanged; context.Control.DataContextChanged += DataContextChanged; // memory leak countermeasure context.Control.Unloaded += ControlOnUnloaded; Log.Debug($"Finalizing composition."); await FinalizeCompositionAsync(context); await BehaviorRunner.ExecuteAsync(context.DataContext as IBehaviorHost, new ViewComposedBehaviorContext(context, ServiceContext)); await DataContextLoadedCompletion.Task; return(true); } catch (Exception e) { Log.Error(e); return(false); } }
/// <inheritdoc /> protected override void Configure(IViewCompositionContext context) { if (context.Control is Window window) { if (context.DataContext is IWindowViewModel windowViewModel) { window.SizeToContent = windowViewModel.SizeToContent; window.ShowInTaskbar = windowViewModel.ShowInTaskbar; windowViewModel.WhenFocusRequested.Subscribe(o => window.Focus()); windowViewModel.WhenClosingRequested.Subscribe(o => window.Close()); windowViewModel.WhenMinimizeRequested.Subscribe(o => window.WindowState = WindowState.Minimized); windowViewModel.WhenMaximizeRequested.Subscribe(o => window.WindowState = WindowState.Maximized); windowViewModel.WhenNormalizeRequested.Subscribe(o => window.WindowState = WindowState.Normal); window.WhenClosing().Subscribe(args => { if (windowViewModel is IWindowListener listener) { listener.NotifyClosing(args); } }); window.WhenStateChanged().Throttle(TimeSpan.FromMilliseconds(50)).Subscribe(args => { if (windowViewModel is IWindowListener listener) { listener.NotifyWindowStateChange(args); } }); window.WhenLocationChanged().Throttle(TimeSpan.FromMilliseconds(50)).Subscribe(args => { if (windowViewModel is IWindowListener listener) { listener.NotifyLocationChanged(args); } }); window.WhenSizeChanged().Throttle(TimeSpan.FromMilliseconds(50)).Subscribe(args => { if (windowViewModel is IWindowListener listener) { listener.NotifySizeChanged(args); } }); window.WhenClosed().Subscribe(async(args) => { if (windowViewModel is IWindowListener listener) { listener.NotifyClosed(); } await BehaviorRunner.ExecuteAsync(windowViewModel as IBehaviorHost, new WindowClosedContext(windowViewModel, ServiceContext.ServiceProvider, context)); }); } } }
private async void DataContextChanged(object sender, DependencyPropertyChangedEventArgs e) { try { if (sender is FrameworkElement element) { Log.Debug($"DataContext has changed."); element.DataContextChanged -= DataContextChanged; if (element.DataContext is IServiceProviderHolder holder) { Log.Debug($"ServiceProvider set through {nameof(IServiceProviderHolder)}."); holder.ServiceProvider = ServiceContext.ServiceProvider; } if (element.DataContext is IWindowViewModel windowViewModel) { if (windowViewModel.Content is IServiceProviderHolder subHolder) { subHolder.ServiceProvider = ServiceContext.ServiceProvider; } } if (element.DataContext is IDefaultBehaviorProvider behaviourProvider && element.DataContext is IBehaviorHost interactiveBehaviour) { var behaviours = behaviourProvider.GetDefaultBehaviors().ToArray(); if (behaviours.Length > 0) { Log.Debug($"Binding {behaviours.Length} behaviours through {nameof(IDefaultBehaviorProvider)} [{string.Join(".", behaviours.Select(s => s.GetType().ToString()))}]."); } interactiveBehaviour.Behaviors.AddRange(behaviours); } foreach (var hook in ComposerHooks) { Log.Debug($"Executing [{nameof(IViewComposerHook)}] -> [{hook.GetType().ToString()}]"); hook.Execute(element, element.DataContext); } await BehaviorRunner.ExecuteAsync(element.DataContext as IBehaviorHost, new ActivationBehaviorContext(element.DataContext, ServiceContext.ServiceProvider)); var coordinationArguments = GetCoordinationArguments(element); if (element.DataContext is ICompositionListener listener) { listener.Execute(new ViewCompositionContext(element, element.DataContext, coordinationArguments)); } DataContextLoaded(new ViewCompositionContext(element, element.DataContext, coordinationArguments)); } DataContextLoadedCompletion.TrySetResult(true); } catch (Exception exception) { DataContextLoadedCompletion.TrySetException(exception); } }