mirror of
https://github.com/wismna/ModernKeePass.git
synced 2025-10-03 23:50:18 -04:00
Major changes in MainPage: now is layout dependant (with a base, to prepare for Settings)
Main sub pages also changed to better work with Main (but needs improvement) Added a Settings Page stub
This commit is contained in:
184
ModernKeePass/Pages/BasePages/LayoutAwarePageBase.cs
Normal file
184
ModernKeePass/Pages/BasePages/LayoutAwarePageBase.cs
Normal file
@@ -0,0 +1,184 @@
|
||||
using System;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Data;
|
||||
using ModernKeePass.Common;
|
||||
using ModernKeePass.Interfaces;
|
||||
|
||||
namespace ModernKeePass.Pages.BasePages
|
||||
{
|
||||
public class LayoutAwarePageBase: Page
|
||||
{
|
||||
/// <summary>
|
||||
/// NavigationHelper is used on each page to aid in navigation and
|
||||
/// process lifetime management
|
||||
/// </summary>
|
||||
public NavigationHelper NavigationHelper { get; }
|
||||
|
||||
public virtual ListView ListView { get; set; }
|
||||
public virtual CollectionViewSource ListViewSource { get; set; }
|
||||
public virtual IHasSelectableObject Model { get; set; }
|
||||
|
||||
public LayoutAwarePageBase()
|
||||
{
|
||||
// Setup the navigation helper
|
||||
NavigationHelper = new NavigationHelper(this);
|
||||
NavigationHelper.LoadState += navigationHelper_LoadState;
|
||||
NavigationHelper.SaveState += navigationHelper_SaveState;
|
||||
|
||||
// Setup the logical page navigation components that allow
|
||||
// the page to only show one pane at a time.
|
||||
NavigationHelper.GoBackCommand = new RelayCommand(() => GoBack(), () => CanGoBack());
|
||||
|
||||
// Start listening for Window size changes
|
||||
// to change from showing two panes to showing a single pane
|
||||
Window.Current.SizeChanged += Window_SizeChanged;
|
||||
InvalidateVisualState();
|
||||
}
|
||||
|
||||
protected void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
// Invalidate the view state when logical page navigation is in effect, as a change
|
||||
// in selection may cause a corresponding change in the current logical page. When
|
||||
// an item is selected this has the effect of changing from displaying the item list
|
||||
// to showing the selected item's details. When the selection is cleared this has the
|
||||
// opposite effect.
|
||||
if (!UsingLogicalPageNavigation()) return;
|
||||
NavigationHelper.GoBackCommand.RaiseCanExecuteChanged();
|
||||
InvalidateVisualState();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Populates the page with content passed during navigation. Any saved state is also
|
||||
/// provided when recreating a page from a prior session.
|
||||
/// </summary>
|
||||
/// <param name="sender">
|
||||
/// The source of the event; typically <see cref="Common.NavigationHelper"/>
|
||||
/// </param>
|
||||
/// <param name="e">Event data that provides both the navigation parameter passed to
|
||||
/// <see cref="Frame.Navigate(Type, Object)"/> when this page was initially requested and
|
||||
/// a dictionary of state preserved by this page during an earlier
|
||||
/// session. The state will be null the first time a page is visited.</param>
|
||||
protected void navigationHelper_LoadState(object sender, LoadStateEventArgs e)
|
||||
{
|
||||
// TODO: Assign a bindable group to Me.DefaultViewModel("Group")
|
||||
// TODO: Assign a collection of bindable items to Me.DefaultViewModel("Items")
|
||||
|
||||
if (e.PageState == null)
|
||||
{
|
||||
// When this is a new page, select the first item automatically unless logical page
|
||||
// navigation is being used (see the logical page navigation #region below.)
|
||||
if (!UsingLogicalPageNavigation() && ListViewSource.View != null)
|
||||
{
|
||||
ListViewSource.View.MoveCurrentToFirst();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Restore the previously saved state associated with this page
|
||||
if (e.PageState.ContainsKey("SelectedItem") && ListViewSource.View != null)
|
||||
{
|
||||
ListViewSource.View.MoveCurrentTo(e.PageState["SelectedItem"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Preserves state associated with this page in case the application is suspended or the
|
||||
/// page is discarded from the navigation cache. Values must conform to the serialization
|
||||
/// requirements of <see cref="Common.SuspensionManager.SessionState"/>.
|
||||
/// </summary>
|
||||
/// <param name="sender">The source of the event; typically <see cref="Common.NavigationHelper"/></param>
|
||||
/// <param name="e">Event data that provides an empty dictionary to be populated with
|
||||
/// serializable state.</param>
|
||||
protected void navigationHelper_SaveState(object sender, SaveStateEventArgs e)
|
||||
{
|
||||
if (ListViewSource.View != null)
|
||||
{
|
||||
e.PageState["SelectedItem"] = Model?.SelectedItem;
|
||||
}
|
||||
}
|
||||
|
||||
#region Logical page navigation
|
||||
|
||||
// The split page is designed so that when the Window does have enough space to show
|
||||
// both the list and the details, only one pane will be shown at at time.
|
||||
//
|
||||
// This is all implemented with a single physical page that can represent two logical
|
||||
// pages. The code below achieves this goal without making the user aware of the
|
||||
// distinction.
|
||||
|
||||
protected const int MinimumWidthForSupportingTwoPanes = 768;
|
||||
|
||||
/// <summary>
|
||||
/// Invoked to determine whether the page should act as one logical page or two.
|
||||
/// </summary>
|
||||
/// <returns>True if the window should show act as one logical page, false
|
||||
/// otherwise.</returns>
|
||||
protected bool UsingLogicalPageNavigation()
|
||||
{
|
||||
return Window.Current.Bounds.Width < MinimumWidthForSupportingTwoPanes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoked with the Window changes size
|
||||
/// </summary>
|
||||
/// <param name="sender">The current Window</param>
|
||||
/// <param name="e">Event data that describes the new size of the Window</param>
|
||||
protected void Window_SizeChanged(object sender, Windows.UI.Core.WindowSizeChangedEventArgs e)
|
||||
{
|
||||
InvalidateVisualState();
|
||||
}
|
||||
|
||||
protected bool CanGoBack()
|
||||
{
|
||||
if (UsingLogicalPageNavigation() && ListView.SelectedItem != null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return NavigationHelper.CanGoBack();
|
||||
}
|
||||
protected void GoBack()
|
||||
{
|
||||
if (UsingLogicalPageNavigation() && ListView.SelectedItem != null)
|
||||
{
|
||||
// When logical page navigation is in effect and there's a selected item that
|
||||
// item's details are currently displayed. Clearing the selection will return to
|
||||
// the item list. From the user's point of view this is a logical backward
|
||||
// navigation.
|
||||
ListView.SelectedItem = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
NavigationHelper.GoBack();
|
||||
}
|
||||
}
|
||||
|
||||
protected void InvalidateVisualState()
|
||||
{
|
||||
var visualState = DetermineVisualState();
|
||||
VisualStateManager.GoToState(this, visualState, false);
|
||||
NavigationHelper.GoBackCommand.RaiseCanExecuteChanged();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoked to determine the name of the visual state that corresponds to an application
|
||||
/// view state.
|
||||
/// </summary>
|
||||
/// <returns>The name of the desired visual state. This is the same as the name of the
|
||||
/// view state except when there is a selected item in portrait and snapped views where
|
||||
/// this additional logical page is represented by adding a suffix of _Detail.</returns>
|
||||
protected string DetermineVisualState()
|
||||
{
|
||||
if (!UsingLogicalPageNavigation())
|
||||
return "PrimaryView";
|
||||
|
||||
// Update the back button's enabled state when the view state changes
|
||||
var logicalPageBack = UsingLogicalPageNavigation() && ListView?.SelectedItem != null;
|
||||
|
||||
return logicalPageBack ? "SinglePane_Detail" : "SinglePane";
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user