mirror of
https://github.com/wismna/ModernKeePass.git
synced 2025-10-03 15:40:18 -04:00
209 lines
8.6 KiB
C#
209 lines
8.6 KiB
C#
using System;
|
|
using Windows.UI.Xaml;
|
|
using Windows.UI.Xaml.Controls;
|
|
using Windows.UI.Xaml.Data;
|
|
using Windows.UI.Xaml.Navigation;
|
|
using ModernKeePass.Common;
|
|
using ModernKeePass.Interfaces;
|
|
|
|
namespace ModernKeePass.Views.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?.MoveCurrentToFirst();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Restore the previously saved state associated with this page
|
|
if (e.PageState.ContainsKey("SelectedItem"))
|
|
{
|
|
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
|
|
|
|
#region NavigationHelper registration
|
|
|
|
/// The methods provided in this section are simply used to allow
|
|
/// NavigationHelper to respond to the page's navigation methods.
|
|
///
|
|
/// Page specific logic should be placed in event handlers for the
|
|
/// <see cref="Common.NavigationHelper.LoadState"/>
|
|
/// and <see cref="Common.NavigationHelper.SaveState"/>.
|
|
/// The navigation parameter is available in the LoadState method
|
|
/// in addition to page state preserved during an earlier session.
|
|
|
|
protected override void OnNavigatedTo(NavigationEventArgs e)
|
|
{
|
|
NavigationHelper.OnNavigatedTo(e);
|
|
}
|
|
|
|
protected override void OnNavigatedFrom(NavigationEventArgs e)
|
|
{
|
|
NavigationHelper.OnNavigatedFrom(e);
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|