Page switching now with 100% less flickering; page switching to a null view model is allowed now

git-svn-id: file:///srv/devel/repo-conversion/nuwi@54 d2e56fa2-650e-0410-a79f-9358c0239efd
This commit is contained in:
Markus Ewald 2019-02-13 22:07:48 +00:00
parent 91432c5209
commit b69488f9a6

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Nuclex.Support;
@ -13,6 +14,51 @@ namespace Nuclex.Windows.Forms.Views {
/// <summary>Special view form that can display different child views</summary>
public class MultiPageViewForm : ViewForm {
#region struct RedrawLockScope
/// <summary>Prevents controls from redrawing themselves for a while</summary>
private struct RedrawLockScope : IDisposable {
/// <summary>Window message that enables or disables control redraw</summary>
private const int WM_SETREDRAW = 11;
/// <summary>Sends a window message to the specified window</summary>
/// <param name="windowHandle">Window a message will be sent to</param>
/// <param name="messageId">ID of the message that will be sent</param>
/// <param name="firstArgument">First argument to the window procedure</param>
/// <param name="secondArgument">Second argument to the window procedure</param>
/// <returns>The return value of the window procedure</returns>
[DllImport("user32")]
public static extern int SendMessage(
IntPtr windowHandle, int messageId, bool firstArgument, int secondArgument
);
/// <summary>Stops redrawing the specified control</summary>
/// <param name="control">Control to stop redrawing</param>
public RedrawLockScope(Control control) {
if(Environment.OSVersion.Platform == PlatformID.Win32NT) {
SendMessage(control.Handle, WM_SETREDRAW, false, 0);
this.control = control;
} else {
this.control = null;
}
}
/// <summary>Enables redrawing again when the lock scope is disposed</summary>
public void Dispose() {
if(this.control != null) {
SendMessage(this.control.Handle, WM_SETREDRAW, true, 0);
this.control.Invalidate(true);
}
}
/// <summary>Control that has been stopped from redrawing itself</summary>
private Control control;
}
#endregion // struct RedrawLockScope
/// <summary>Initializes a new multi page view window</summary>
/// <param name="windowManager">
/// Window manager that is used to set up the child views
@ -191,15 +237,20 @@ namespace Nuclex.Windows.Forms.Views {
// Worst, but usual, case: the new page view model might require
// a different view. Create or look up the new view and put it in the container
{
if(pageViewModel == null) {
disableActivePageView();
} else {
Control pageViewContainer = getPageViewContainer();
using(new RedrawLockScope(pageViewContainer)) {
disableActivePageView();
this.activePageView = getOrCreatePageView(pageViewModel);
Control pageViewContainer = getPageViewContainer();
pageViewContainer.Controls.Add(this.activePageView);
this.activePageView.Dock = DockStyle.Fill;
}
}
}
}
/// <summary>Gets the cached child view or creates a new one if not cached</summary>
/// <param name="viewModel">View model for which a child view will be returned</param>