The progress spinner can now tell its optimal size required to show the entire status text but overlap as few controls as possible; began implementing a generic version of a multi page view model and matching view with caching

git-svn-id: file:///srv/devel/repo-conversion/nuwi@53 d2e56fa2-650e-0410-a79f-9358c0239efd
This commit is contained in:
Markus Ewald 2019-02-13 21:26:12 +00:00
parent 17ec2d0f69
commit 91432c5209
5 changed files with 390 additions and 3 deletions

View file

@ -0,0 +1,14 @@
using System;
namespace Nuclex.Windows.Forms.ViewModels {
/// <summary>Interface for vew models that can switch between different pages</summary>
public interface IMultiPageViewModel {
/// <summary>Retrieves (and, if needed, creates) the view model for the active page</summary>
/// <returns>A view model for the active page on the multi-page view model</returns>
object GetActivePageViewModel();
}
} // namespace Nuclex.Windows.Forms.ViewModels

View file

@ -19,6 +19,7 @@ License along with this library
#endregion
using System;
using System.Collections.Concurrent;
using Nuclex.Support;
@ -26,8 +27,8 @@ namespace Nuclex.Windows.Forms.ViewModels {
/// <summary>Base class for view models that have multiple child view models</summary>
/// <typeparam name="TPageEnumeration">Enum type by which pages can be indicated</typeparam>
public abstract class MultiPageViewModel<TPageEnumeration> : Observable
where TPageEnumeration : IEquatable<TPageEnumeration> {
public abstract class MultiPageViewModel<TPageEnumeration> :
Observable, IMultiPageViewModel, IDisposable {
/// <summary>Initializes a new multi-page view model</summary>
/// <param name="windowManager">
@ -38,6 +39,25 @@ namespace Nuclex.Windows.Forms.ViewModels {
/// </param>
public MultiPageViewModel(IWindowManager windowManager, bool cachePageViewModels = false) {
this.windowManager = windowManager;
if(cachePageViewModels) {
this.cachedViewModels = new ConcurrentDictionary<TPageEnumeration, object>();
}
}
/// <summary>Immediately releases all resources owned by the instance</summary>
public virtual void Dispose() {
if(this.cachedViewModels != null) {
foreach(object cacheViewModel in this.cachedViewModels.Values) {
disposeIfSupported(cacheViewModel);
}
this.activePageViewModel = null;
this.cachedViewModels.Clear();
this.cachedViewModels = null;
} else if(this.activePageViewModel != null) {
disposeIfSupported(this.activePageViewModel);
this.activePageViewModel = null;
}
}
/// <summary>Child page that is currently being displayed by the view model</summary>
@ -46,11 +66,36 @@ namespace Nuclex.Windows.Forms.ViewModels {
set {
if(!this.activePage.Equals(value)) {
this.activePage = value;
if(this.activePageViewModel != null) {
if(this.cachedViewModels == null) {
disposeIfSupported(this.activePageViewModel);
}
this.activePageViewModel = null;
}
OnPropertyChanged(nameof(ActivePage));
}
}
}
/// <summary>Retrieves (and, if needed, creates) the view model for the active page</summary>
/// <returns>A view model for the active page on the multi-page view model</returns>
public object GetActivePageViewModel() {
if(this.cachedViewModels == null) {
if(this.activePageViewModel == null) {
this.activePageViewModel = CreateViewModelForPage(this.activePage);
}
} else if(this.activePageViewModel == null) {
this.activePageViewModel = this.cachedViewModels.GetOrAdd(
this.activePage,
delegate(TPageEnumeration activePage) {
return CreateViewModelForPage(this.activePage);
}
);
}
return this.activePageViewModel;
}
/// <summary>Windowmanager that can create view models and display other views</summary>
protected IWindowManager WindowManager {
get { return this.windowManager; }
@ -59,13 +104,27 @@ namespace Nuclex.Windows.Forms.ViewModels {
/// <summary>Creates a view model for the specified page</summary>
/// <param name="page">Page for which a view model will be created</param>
/// <returns>The view model for the specified page</returns>
protected abstract object createViewModelForPage(TPageEnumeration page);
protected abstract object CreateViewModelForPage(TPageEnumeration page);
/// <summary>Disposes the specified object if it is disposable</summary>
/// <param name="potentiallyDisposable">Object that will be disposed if supported</param>
private static void disposeIfSupported(object potentiallyDisposable) {
var disposable = potentiallyDisposable as IDisposable;
if(disposable != null) {
disposable.Dispose();
}
}
/// <summary>Page that is currently active in the multi-page view model</summary>
private TPageEnumeration activePage;
/// <summary>Window manager that can be used to display other views</summary>
private IWindowManager windowManager;
/// <summary>View model for the active page</summary>
private object activePageViewModel;
/// <summary>Cached page view models, if caching is enabled</summary>
private ConcurrentDictionary<TPageEnumeration, object> cachedViewModels;
}
} // namespace Nuclex.Windows.Forms.ViewModels