Persist and Restore Forms for larger application with A lot of different forms and all either factory created or dependency injection loaded
FormStateModel
/// <summary>
/// FormStateModel
/// </summary>
public class FormStateModel
{
/// <summary>
/// Gets or sets the name of the form.
/// </summary>
/// <value>
/// The name of the form.
/// </value>
public string FormName { get; set; }
/// <summary>
/// Gets or sets the size of the form.
/// </summary>
/// <value>
/// The size of the form.
/// </value>
public Size FormSize { get; set; }
/// <summary>
/// Gets or sets the form position.
/// </summary>
/// <value>
/// The form position.
/// </value>
public Point FormPosition { get; set; }
/// <summary>
/// Gets or sets the state of the window.
/// </summary>
/// <value>
/// The state of the window.
/// </value>
public FormState WindowState { get; set; }
public bool Equals(FormStateModel other)
{
return FormName == other.FormName &&
FormSize.Height == other.FormSize.Height &&
FormSize.Width == other.FormSize.Width &&
FormPosition.Y == other.FormPosition.Y &&
FormPosition.X == other.FormPosition.X &&
WindowState == other.WindowState;
}
}
/// <summary>
/// FormState
/// </summary>
public enum FormState
{
Normal = 0,
/// <summary>A minimized window.</summary>
Minimized = 1,
/// <summary>A maximized window.</summary>
Maximized = 2
}
FormStateDataModel
/// <summary>
/// FormStateDataModel
/// </summary>
[DataContract(Name = "FormStateDataModel")]
public class FormStateDataModel
{
/// <summary>
/// Gets or sets the name of the form.
/// </summary>
/// <value>
/// The name of the form.
/// </value>
[DataMember(Name = "FormName", Order = 1)]
public string FormName { get; set; }
/// <summary>
/// Gets or sets the size of the form.
/// </summary>
/// <value>
/// The size of the form.
/// </value>
[DataMember(Name = "FormSize", Order = 2)]
public VectorDataModel FormSize { get; set; }
/// <summary>
/// Gets or sets the form position.
/// </summary>
/// <value>
/// The form position.
/// </value>
[DataMember(Name = "FormPosition", Order = 3)]
public PointDataModel FormPosition { get; set; }
/// <summary>
/// Gets or sets the state of the windows.
/// </summary>
/// <value>
/// The state of the windows.
/// </value>
[DataMember(Name = "WindowsState", Order = 4)]
public int WindowsState { get; set; }
}
FormStateManager
public class FormStateManager
{
public static bool RestoreFormState(ApplicationSettingsModel settings, Form form)
{
if (settings.FormStateModels.ContainsKey(form.Name))
{
try
{
var model = settings.FormStateModels[form.Name];
//Validate FormStateModel
if (!ValidateFormStateModel(model))
{
Log.Warning($"The FormStateModel for {form.Name} was invalid. Replacing it with a generic. FormSize={model.FormSize}",
form.Name, model.FormSize);
settings.FormStateModels.Remove(model.FormName);
// Creating a new generic FormState for specified Form and with center screen start
model = new FormStateModel
{
FormName = form.Name,
WindowState = FormState.Normal,
FormSize = form.Bounds.Size,
FormPosition = new Point()
};
if (model.FormSize.IsEmpty)
{
model.FormSize = form.MinimumSize;
}
//model.FormPosition = GetOffsetCenterPointInRect(Screen.PrimaryScreen.Bounds, form.Size);
settings.FormStateModels.Add(form.Name, model);
}
form.Bounds = new Rectangle(model.FormPosition, model.FormSize);
form.WindowState = (FormWindowState) model.WindowState;
return true;
}
catch (Exception exception)
{
Log.Error(exception, "RestoreFormState Exception");
}
}
return false;
}
private static Point GetOffsetCenterPointInRect(Rectangle boundingRect, Size winSize)
{
Point center = new Point(boundingRect.Width / 2, boundingRect.Height / 2);
center.X -= winSize.Width / 2;
center.Y -= winSize.Height / 2;
return center;
}
//Validates that the Form is located on any screen
private static bool ValidateFormStateModel(FormStateModel model)
{
var modelBounds = new Rectangle(model.FormPosition, model.FormSize);
bool intersect = Screen.AllScreens.Any(x => x.Bounds.IntersectsWith(modelBounds));
return intersect;
}
public static void SaveFormState(ApplicationSettingsModel appSettings, Form form)
{
FormStateModel model;
appSettings.FormStateModels ??= new ConcurrentDictionary<string, FormStateModel>();
if (appSettings.FormStateModels.ContainsKey(form.Name))
model = appSettings.FormStateModels[form.Name];
else
{
model = new FormStateModel();
appSettings.FormStateModels.Add(form.Name, model);
}
model.FormName = form.Name;
model.WindowState = (FormState) form.WindowState;
if (form.WindowState == FormWindowState.Normal)
{
model.FormSize = form.Bounds.Size;
model.FormPosition = form.Bounds.Location;
}
else
{
model.FormSize = form.RestoreBounds.Size;
model.FormPosition = form.RestoreBounds.Location;
}
}
}
Implementation
//On Load
// Restore previous form state
var settings= _appSettingsService.Settings;
FormStateManager.RestoreFormState(settings, this);
//On Close
var appSettings = _appSettingsService.Settings;
FormStateManager.SaveFormState(appSettings, this);
_appSettingsService.SaveSettings();
More Data Models Used since the System.Dawing Models cant be serialized
/// <summary>
/// SizeDataModel
/// </summary>
[Serializable, DataContract(Name = "SizeDataModel")]
public class SizeDataModel
{
/// <summary>
/// Gets or sets the width.
/// </summary>
/// <value>
/// The width.
/// </value>
[DataMember(Name = "Width", Order = 1)]
public int Width { get; set; }
/// <summary>
/// Gets or sets the height.
/// </summary>
/// <value>
/// The height.
/// </value>
[DataMember(Name = "Height", Order = 2)]
public int Height { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="SizeDataModel"/> class.
/// </summary>
public SizeDataModel()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="SizeDataModel"/> class.
/// </summary>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
public SizeDataModel(int width, int height)
{
Width = width;
Height = height;
}
/// <summary>
/// To the size.
/// </summary>
/// <returns></returns>
public Size ToSize()
{
return new Size(Width, Height);
}
/// <summary>
/// Creates from size.
/// </summary>
/// <param name="size">The size.</param>
/// <returns></returns>
public static SizeDataModel CreateFromSize(Size size)
{
return new SizeDataModel(size.Width, size.Height);
}
}
/// <summary>
///
/// </summary>
[Serializable, DataContract(Name = "RectangleDataModel")]
public class RectangleDataModel
{
/// <summary>
/// Gets or sets the x.
/// </summary>
/// <value>
/// The x.
/// </value>
[DataMember(Name = "X", Order = 1)]
public int X { get; set; }
/// <summary>
/// Gets or sets the y.
/// </summary>
/// <value>
/// The y.
/// </value>
[DataMember(Name = "Y", Order = 2)]
public int Y { get; set; }
/// <summary>
/// Gets or sets the width.
/// </summary>
/// <value>
/// The width.
/// </value>
[DataMember(Name = "Width", Order = 3)]
public int Width { get; set; }
/// <summary>
/// Gets or sets the height.
/// </summary>
/// <value>
/// The height.
/// </value>
[DataMember(Name = "Height", Order = 4)]
public int Height { get; set; }
public RectangleDataModel()
{
}
public RectangleDataModel(Rectangle rectangle)
{
X = rectangle.X;
Y = rectangle.Y;
Width = rectangle.Width;
Height = rectangle.Height;
}
/// <summary>
/// To the rectangle.
/// </summary>
/// <returns></returns>
public Rectangle ToRectangle()
{
return new Rectangle(X, Y, Width, Height);
}
}
/// <summary>
/// VectorDataModel
/// </summary>
/// <seealso cref="ImageViewer.DataContracts" />
[DataContract(Name = "VectorDataModel")]
public class VectorDataModel : PointDataModel
{
/// <summary>
/// Gets or sets the width.
/// </summary>
/// <value>
/// The width.
/// </value>
[DataMember(Name = "Width", Order = 1)]
public int Width { get; set; }
/// <summary>
/// Gets or sets the height.
/// </summary>
/// <value>
/// The height.
/// </value>
[DataMember(Name = "Height", Order = 2)]
public int Height { get; set; }
}
/// <summary>
///
/// </summary>
[Serializable, DataContract(Name = "PointDataModel")]
public class PointDataModel
{
/// <summary>
/// Gets or sets the x.
/// </summary>
/// <value>
/// The x.
/// </value>
[DataMember(Name = "X", Order = 1)]
public int X { get; set; }
/// <summary>
/// Gets or sets the y.
/// </summary>
/// <value>
/// The y.
/// </value>
[DataMember(Name = "Y", Order = 2)]
public int Y { get; set; }
/// <summary>
/// To the point.
/// </summary>
/// <returns></returns>
public Point ToPoint()
{
return new Point(X, Y);
}
/// <summary>
/// Initializes a new instance of the <see cref="PointDataModel"/> class.
/// </summary>
public PointDataModel()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="PointDataModel"/> class.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
public PointDataModel(int x, int y)
{
X = x;
Y = y;
}
/// <summary>
/// Creates from point.
/// </summary>
/// <param name="point">The point.</param>
/// <returns></returns>
public static PointDataModel CreateFromPoint(Point point)
{
return new PointDataModel {X = point.X, Y = point.Y};
}
}
Misc – Data Mapping
public class AppConfigProfile : Profile
{
public AppConfigProfile()
{
CreateMap<ApplicationSettingsModel, ApplicationSettingsDataModel>()
.ForMember(s => s.AlwaysOntop, o => o.MapFrom(d => d.AlwaysOntop))
.ForMember(s => s.AutoHideCursor, o => o.MapFrom(d => d.AutoHideCursor))
.ForMember(s => s.AutoHideCursorDelay, o => o.MapFrom(d => d.AutoHideCursorDelay))
.ForMember(s => s.AutoRandomizeCollection, o => o.MapFrom(d => d.AutoRandomizeCollection))
.ForMember(s => s.AutomaticUpdateCheck, o => o.MapFrom(d => d.AutomaticUpdateCheck))
.ForMember(s => s.ConfirmApplicationShutdown, o => o.MapFrom(d => d.ConfirmApplicationShutdown))
.ForMember(s => s.DefaultKey, o => o.MapFrom(d => d.DefaultKey))
.ForMember(s => s.EnableAutoLoadFunctionFromMenu, o => o.MapFrom(d => d.EnableAutoLoadFunctionFromMenu))
.ForMember(s => s.ImageCacheSize, o => o.MapFrom(d => d.ImageCacheSize))
.ForMember(s => s.ImageTransitionTime, o => o.MapFrom(d => d.ImageTransitionTime))
.ForMember(s => s.LastFolderLocation, o => o.MapFrom(d => d.LastFolderLocation))
.ForMember(s => s.ShowNextPrevControlsOnEnterWindow, o => o.MapFrom(d => d.ShowNextPrevControlsOnEnterWindow))
.ForMember(s => s.ShowImageViewFormsInTaskBar, o => o.MapFrom(d => d.ShowImageViewFormsInTaskBar))
.ForMember(s => s.LastUsedSearchPaths, o => o.MapFrom(d => d.LastUsedSearchPaths))
.ForMember(s => s.NextImageAnimation, o => o.MapFrom(d => d.NextImageAnimation))
.ForMember(s => s.SlideshowInterval, o => o.MapFrom(d => d.SlideshowInterval))
.ForMember(s => s.PrimaryImageSizeMode, o => o.MapFrom(d => d.PrimaryImageSizeMode))
.ForMember(s => s.ScreenMinXOffset, o => o.MapFrom(d => d.ScreenMinXOffset))
.ForMember(s => s.ScreenWidthOffset, o => o.MapFrom(d => d.ScreenWidthOffset))
.ForMember(s => s.PasswordProtectBookmarks, o => o.MapFrom(d => d.PasswordProtectBookmarks))
.ForMember(s => s.PasswordDerivedString, o => o.MapFrom(d => d.PasswordDerivedString))
.ForMember(s => s.ShowSwitchImageButtons, o => o.MapFrom(d => d.ShowSwitchImageButtons))
.ForMember(s => s.ThumbnailSize, o => o.MapFrom(d => d.ThumbnailSize))
.ForMember(s => s.MaxThumbnails, o => o.MapFrom(d => d.MaxThumbnails))
.ForMember(s => s.MainWindowBackgroundColor, o => o.MapFrom(d => d.MainWindowBackgroundColor))
.ForMember(s => s.LastUpdateCheck, o => o.MapFrom(d => d.LastUpdateCheck))
.ForMember(s => s.ToggleSlideshowWithThirdMouseButton, o => o.MapFrom(d => d.ToggleSlideshowWithThirdMouseButton))
.ForMember(s => s.BookmarksShowOverlayWindow, o => o.MapFrom(d => d.BookmarksShowOverlayWindow))
.ForMember(s => s.BookmarksShowMaximizedImageArea, o => o.MapFrom(d => d.BookmarksShowMaximizedImageArea))
.ForMember(s => s.AppSettingsGuid, o => o.MapFrom(d => d.AppSettingsGuid))
.ForMember(s => s.FormStateDataModels, o => o.MapFrom(d => d.FormStateModels.Values.ToList()))
.ReverseMap()
.ForMember(s => s.FormStateModels, o => o.MapFrom(d => d.FormStateDataModels.ToDictionary(x => x.FormName)));
CreateMap<FormStateModel, FormStateDataModel>()
.ForMember(s => s.FormName, o => o.MapFrom(d => d.FormName))
.ForMember(s => s.FormPosition, o => o.MapFrom(d => d.FormPosition))
.ForMember(s => s.FormSize, o => o.MapFrom(d => d.FormSize))
.ForMember(s => s.WindowsState, o => o.MapFrom(d => d.WindowState))
.ReverseMap();
CreateMap<PointDataModel, Point>()
.ForMember(s => s.X, o => o.MapFrom(d => d.X))
.ForMember(s => s.Y, o => o.MapFrom(d => d.Y))
.ReverseMap()
.ForMember(s => s.X, o => o.MapFrom(d => d.X))
.ForMember(s => s.Y, o => o.MapFrom(d => d.Y));
CreateMap<VectorDataModel, Size>()
.ForMember(s => s.Height, o => o.MapFrom(d => d.Height))
.ForMember(s => s.Width, o => o.MapFrom(d => d.Width))
.ReverseMap()
.ForMember(s => s.Height, o => o.MapFrom(d => d.Height))
.ForMember(s => s.Width, o => o.MapFrom(d => d.Width));
CreateMap<ColorDataModel, Color>()
.ConstructUsing(x => x.ToColor())
.ReverseMap()
.ConvertUsing(x => ColorDataModel.CreateFromColor(x));
}
}