Windows Forms

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));
        }
    }

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.