diff --git a/Source/Views/MultiPageViewForm.cs b/Source/Views/MultiPageViewForm.cs index 4c3a034..61c55d8 100644 --- a/Source/Views/MultiPageViewForm.cs +++ b/Source/Views/MultiPageViewForm.cs @@ -140,7 +140,7 @@ namespace Nuclex.Windows.Forms.Views { /// Discovers the container control used to host the child views /// The container control is which the child views will be hosted /// - /// This is supposed to be overriden by the user, simply returning the container + /// This is supposed to be overridden by the user, simply returning the container /// control that should host the page views. If it isn't, however, we use some /// heuristics to figure out the most likely candidate: it should be a container, /// and it should cover most of the window's client area. diff --git a/Source/Views/ViewControl.cs b/Source/Views/ViewControl.cs index 329f673..7b39b6b 100644 --- a/Source/Views/ViewControl.cs +++ b/Source/Views/ViewControl.cs @@ -85,12 +85,23 @@ namespace Nuclex.Windows.Forms.Views { } } } +#else + /// Called when the control's data context has changed + /// Not used + protected override void OnDataContextChanged(EventArgs arguments) { + object oldDataContext = this.dataContext; + this.dataContext = base.DataContext; + + if(this.dataContext != oldDataContext) { + OnDataContextChanged(this, oldDataContext, this.dataContext); + } + } #endif -#if !NET8_0_OR_GREATER + // NOTE: Careful! On .NET 8.0, the Control class has its own DataContext, + // but this one will be used to be able to report the previous one. /// Active data binding target, can be null private object dataContext; -#endif /// Delegate for the OnViewModelPropertyChanged() method private PropertyChangedEventHandler onViewModelPropertyChangedDelegate; diff --git a/Source/Views/ViewForm.cs b/Source/Views/ViewForm.cs index db8d242..d09c407 100644 --- a/Source/Views/ViewForm.cs +++ b/Source/Views/ViewForm.cs @@ -42,20 +42,6 @@ namespace Nuclex.Windows.Forms.Views { this.onViewModelPropertyChangedDelegate = OnViewModelPropertyChanged; } -#if !NET8_0_OR_GREATER - /// Provides the data binding target for the view - public object DataContext { - get { return this.dataContext; } - set { - if(value != this.dataContext) { - object oldDataContext = this.dataContext; - this.dataContext = value; - OnDataContextChanged(this, oldDataContext, value); - } - } - } -#endif - /// Called when the window's data context is changed /// Window whose data context was changed /// Data context that was previously used @@ -88,9 +74,34 @@ namespace Nuclex.Windows.Forms.Views { ) { } #if !NET8_0_OR_GREATER + /// Provides the data binding target for the view + public object DataContext { + get { return this.dataContext; } + set { + if(value != this.dataContext) { + object oldDataContext = this.dataContext; + this.dataContext = value; + OnDataContextChanged(this, oldDataContext, value); + } + } + } +#else + /// Called when the control's data context has changed + /// Not used + protected override void OnDataContextChanged(EventArgs arguments) { + object oldDataContext = this.dataContext; + this.dataContext = base.DataContext; + + if(this.dataContext != oldDataContext) { + OnDataContextChanged(this, oldDataContext, this.dataContext); + } + } +#endif + + // NOTE: Careful! On .NET 8.0, the Control class has its own DataContext, + // but this one will be used to be able to report the previous one. /// Active data binding target, can be null private object dataContext; -#endif /// Delegate for the OnViewModelPropertyChanged() method private PropertyChangedEventHandler onViewModelPropertyChangedDelegate; diff --git a/Source/WindowManager.cs b/Source/WindowManager.cs index b83c448..76ae42b 100644 --- a/Source/WindowManager.cs +++ b/Source/WindowManager.cs @@ -363,14 +363,20 @@ namespace Nuclex.Windows.Forms { return Activator.CreateInstance(type); } - /// Creates an instance of the specified type in a new scope - /// Type an instance will be created of - /// The created instance and the scope in which it lives + /// Creates a new scope in which window-specific instances live + /// + /// A new scope in which scoped services requested by the window's view model + /// will live + /// /// - /// This is identical to but, if used together - /// with a dependency injector, should also create a service scope. This way, - /// an implicit service scope will cover the lifetime of a view model and - /// any non-singleton services will use new instances, avoiding, for example, + /// If you do not override this method, services will be constructed through + /// the normal method (which actually may not + /// work without managing your own service scope in case your dependency + /// injector supports scopes and some of your services are scoped). By + /// overriding this method, you can automatically cause a new scope to be + /// created for each window or dialog. That way, an implicit service scope + /// will cover the lifetime of each window and its view model and any + /// non-singleton services will use new instances, avoiding, for example, /// that multiple dialogs access the same database connection simultaneously. /// protected virtual IWindowScope CreateWindowScope() { @@ -464,6 +470,9 @@ namespace Nuclex.Windows.Forms { /// /// Control that will dispose a scope when it is itself disposed /// + /// + /// Scope that will be disposed together with the control + /// private void setupScopeDisposal(Control control, IWindowScope scope) { if(!ReferenceEquals(scope, this.windowManagerAsScope)) { IDisposable disposableScope = scope as IDisposable;