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:
@@ -17,7 +17,7 @@ namespace ModernKeePass
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Provides application-specific behavior to supplement the default Application class.
|
/// Provides application-specific behavior to supplement the default Application class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
sealed partial class App : Application
|
sealed partial class App
|
||||||
{
|
{
|
||||||
public DatabaseHelper Database { get; set; } = new DatabaseHelper();
|
public DatabaseHelper Database { get; set; } = new DatabaseHelper();
|
||||||
public Dictionary<string, IPwEntity> PendingDeleteEntities = new Dictionary<string, IPwEntity>();
|
public Dictionary<string, IPwEntity> PendingDeleteEntities = new Dictionary<string, IPwEntity>();
|
||||||
@@ -87,7 +87,7 @@ namespace ModernKeePass
|
|||||||
// When the navigation stack isn't restored navigate to the first page,
|
// When the navigation stack isn't restored navigate to the first page,
|
||||||
// configuring the new page by passing required information as a navigation
|
// configuring the new page by passing required information as a navigation
|
||||||
// parameter
|
// parameter
|
||||||
rootFrame.Navigate(typeof(MainPage), lauchActivatedEventArgs.Arguments);
|
rootFrame.Navigate(typeof(Pages.MainPage), lauchActivatedEventArgs.Arguments);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -140,7 +140,7 @@ namespace ModernKeePass
|
|||||||
base.OnFileActivated(args);
|
base.OnFileActivated(args);
|
||||||
var rootFrame = new Frame();
|
var rootFrame = new Frame();
|
||||||
Database.DatabaseFile = args.Files[0] as StorageFile;
|
Database.DatabaseFile = args.Files[0] as StorageFile;
|
||||||
rootFrame.Navigate(typeof(MainPage), args);
|
rootFrame.Navigate(typeof(Pages.MainPage), args);
|
||||||
Window.Current.Content = rootFrame;
|
Window.Current.Content = rootFrame;
|
||||||
Window.Current.Activate();
|
Window.Current.Activate();
|
||||||
}
|
}
|
||||||
|
7
ModernKeePass/Interfaces/IHasSelectableObject.cs
Normal file
7
ModernKeePass/Interfaces/IHasSelectableObject.cs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
namespace ModernKeePass.Interfaces
|
||||||
|
{
|
||||||
|
public interface IHasSelectableObject
|
||||||
|
{
|
||||||
|
ISelectableModel SelectedItem { get; set; }
|
||||||
|
}
|
||||||
|
}
|
7
ModernKeePass/Interfaces/ISelectableModel.cs
Normal file
7
ModernKeePass/Interfaces/ISelectableModel.cs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
namespace ModernKeePass.Interfaces
|
||||||
|
{
|
||||||
|
public interface ISelectableModel
|
||||||
|
{
|
||||||
|
bool IsSelected { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@@ -119,7 +119,10 @@
|
|||||||
<Compile Include="Common\RelayCommand.cs" />
|
<Compile Include="Common\RelayCommand.cs" />
|
||||||
<Compile Include="Common\SuspensionManager.cs" />
|
<Compile Include="Common\SuspensionManager.cs" />
|
||||||
<Compile Include="Common\ToastNotificationHelper.cs" />
|
<Compile Include="Common\ToastNotificationHelper.cs" />
|
||||||
<Compile Include="Controls\FirstItemDataTemplateSelector.cs" />
|
<Compile Include="Interfaces\IHasSelectableObject.cs" />
|
||||||
|
<Compile Include="Interfaces\ISelectableModel.cs" />
|
||||||
|
<Compile Include="Pages\BasePages\LayoutAwarePageBase.cs" />
|
||||||
|
<Compile Include="TemplateSelectors\FirstItemDataTemplateSelector.cs" />
|
||||||
<Compile Include="Controls\ListViewWithDisable.cs" />
|
<Compile Include="Controls\ListViewWithDisable.cs" />
|
||||||
<Compile Include="Controls\OpenDatabaseUserControl.xaml.cs">
|
<Compile Include="Controls\OpenDatabaseUserControl.xaml.cs">
|
||||||
<DependentUpon>OpenDatabaseUserControl.xaml</DependentUpon>
|
<DependentUpon>OpenDatabaseUserControl.xaml</DependentUpon>
|
||||||
@@ -140,13 +143,16 @@
|
|||||||
<DependentUpon>MainPage.xaml</DependentUpon>
|
<DependentUpon>MainPage.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Mappings\PwIconToSegoeMapping.cs" />
|
<Compile Include="Mappings\PwIconToSegoeMapping.cs" />
|
||||||
<Compile Include="Pages\AboutPage.xaml.cs">
|
<Compile Include="Pages\MainPageFrames\AboutPage.xaml.cs">
|
||||||
<DependentUpon>AboutPage.xaml</DependentUpon>
|
<DependentUpon>AboutPage.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Pages\NewDatabasePage.xaml.cs">
|
<Compile Include="Pages\MainPageFrames\NewDatabasePage.xaml.cs">
|
||||||
<DependentUpon>NewDatabasePage.xaml</DependentUpon>
|
<DependentUpon>NewDatabasePage.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Pages\WelcomePage.xaml.cs">
|
<Compile Include="Pages\SettingsPage.xaml.cs">
|
||||||
|
<DependentUpon>SettingsPage.xaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Pages\MainPageFrames\WelcomePage.xaml.cs">
|
||||||
<DependentUpon>WelcomePage.xaml</DependentUpon>
|
<DependentUpon>WelcomePage.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="ViewModels\AboutVm.cs" />
|
<Compile Include="ViewModels\AboutVm.cs" />
|
||||||
@@ -158,13 +164,13 @@
|
|||||||
<Compile Include="Pages\GroupDetailPage.xaml.cs">
|
<Compile Include="Pages\GroupDetailPage.xaml.cs">
|
||||||
<DependentUpon>GroupDetailPage.xaml</DependentUpon>
|
<DependentUpon>GroupDetailPage.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Pages\OpenDatabasePage.xaml.cs">
|
<Compile Include="Pages\MainPageFrames\OpenDatabasePage.xaml.cs">
|
||||||
<DependentUpon>OpenDatabasePage.xaml</DependentUpon>
|
<DependentUpon>OpenDatabasePage.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Pages\RecentDatabasesPage.xaml.cs">
|
<Compile Include="Pages\MainPageFrames\RecentDatabasesPage.xaml.cs">
|
||||||
<DependentUpon>RecentDatabasesPage.xaml</DependentUpon>
|
<DependentUpon>RecentDatabasesPage.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Pages\SaveDatabasePage.xaml.cs">
|
<Compile Include="Pages\MainPageFrames\SaveDatabasePage.xaml.cs">
|
||||||
<DependentUpon>SaveDatabasePage.xaml</DependentUpon>
|
<DependentUpon>SaveDatabasePage.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
@@ -202,7 +208,7 @@
|
|||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</Page>
|
</Page>
|
||||||
<Page Include="Pages\AboutPage.xaml">
|
<Page Include="Pages\MainPageFrames\AboutPage.xaml">
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
</Page>
|
</Page>
|
||||||
@@ -214,23 +220,27 @@
|
|||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
</Page>
|
</Page>
|
||||||
<Page Include="Pages\NewDatabasePage.xaml">
|
<Page Include="Pages\MainPageFrames\NewDatabasePage.xaml">
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
</Page>
|
</Page>
|
||||||
<Page Include="Pages\OpenDatabasePage.xaml">
|
<Page Include="Pages\MainPageFrames\OpenDatabasePage.xaml">
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
</Page>
|
</Page>
|
||||||
<Page Include="Pages\RecentDatabasesPage.xaml">
|
<Page Include="Pages\MainPageFrames\RecentDatabasesPage.xaml">
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
</Page>
|
</Page>
|
||||||
<Page Include="Pages\SaveDatabasePage.xaml">
|
<Page Include="Pages\MainPageFrames\SaveDatabasePage.xaml">
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
</Page>
|
</Page>
|
||||||
<Page Include="Pages\WelcomePage.xaml">
|
<Page Include="Pages\SettingsPage.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
</Page>
|
||||||
|
<Page Include="Pages\MainPageFrames\WelcomePage.xaml">
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
</Page>
|
</Page>
|
||||||
@@ -320,6 +330,9 @@
|
|||||||
<Name>ModernKeePassLib</Name>
|
<Name>ModernKeePassLib</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="Pages\SettingsPageFrames\" />
|
||||||
|
</ItemGroup>
|
||||||
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' < '12.0' ">
|
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' < '12.0' ">
|
||||||
<VisualStudioVersion>12.0</VisualStudioVersion>
|
<VisualStudioVersion>12.0</VisualStudioVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
@@ -379,7 +379,9 @@
|
|||||||
</core:EventTriggerBehavior>
|
</core:EventTriggerBehavior>
|
||||||
</interactivity:Interaction.Behaviors>
|
</interactivity:Interaction.Behaviors>
|
||||||
</AppBarButton>
|
</AppBarButton>
|
||||||
<AppBarButton Icon="Setting" Label="Settings" />
|
<AppBarButton Icon="Setting" Label="Settings">
|
||||||
|
<core:NavigateToPageAction TargetPage="ModernKeePass.Pages.SettingsPage" />
|
||||||
|
</AppBarButton>
|
||||||
</CommandBar.SecondaryCommands>
|
</CommandBar.SecondaryCommands>
|
||||||
<AppBarToggleButton Icon="Edit" Label="Edit" IsChecked="{Binding IsEditMode, Mode=TwoWay}">
|
<AppBarToggleButton Icon="Edit" Label="Edit" IsChecked="{Binding IsEditMode, Mode=TwoWay}">
|
||||||
<interactivity:Interaction.Behaviors>
|
<interactivity:Interaction.Behaviors>
|
||||||
|
@@ -5,10 +5,10 @@
|
|||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:viewModels="using:ModernKeePass.ViewModels"
|
xmlns:viewModels="using:ModernKeePass.ViewModels"
|
||||||
xmlns:converters="using:ModernKeePass.Converters"
|
xmlns:converters="using:ModernKeePass.Converters"
|
||||||
xmlns:local="using:ModernKeePass.Controls"
|
|
||||||
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
|
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
|
||||||
xmlns:core="using:Microsoft.Xaml.Interactions.Core"
|
xmlns:core="using:Microsoft.Xaml.Interactions.Core"
|
||||||
xmlns:actions="using:ModernKeePass.Actions"
|
xmlns:actions="using:ModernKeePass.Actions"
|
||||||
|
xmlns:templateSelectors="using:ModernKeePass.TemplateSelectors"
|
||||||
x:Name="PageRoot"
|
x:Name="PageRoot"
|
||||||
x:Class="ModernKeePass.Pages.GroupDetailPage"
|
x:Class="ModernKeePass.Pages.GroupDetailPage"
|
||||||
mc:Ignorable="d" >
|
mc:Ignorable="d" >
|
||||||
@@ -32,7 +32,9 @@
|
|||||||
</core:EventTriggerBehavior>
|
</core:EventTriggerBehavior>
|
||||||
</interactivity:Interaction.Behaviors>
|
</interactivity:Interaction.Behaviors>
|
||||||
</AppBarButton>
|
</AppBarButton>
|
||||||
<AppBarButton Icon="Setting" Label="Settings" />
|
<AppBarButton Icon="Setting" Label="Settings">
|
||||||
|
<core:NavigateToPageAction TargetPage="ModernKeePass.Pages.SettingsPage" />
|
||||||
|
</AppBarButton>
|
||||||
</CommandBar.SecondaryCommands>
|
</CommandBar.SecondaryCommands>
|
||||||
<AppBarToggleButton Icon="Edit" Label="Edit" IsChecked="{Binding IsEditMode, Mode=TwoWay}">
|
<AppBarToggleButton Icon="Edit" Label="Edit" IsChecked="{Binding IsEditMode, Mode=TwoWay}">
|
||||||
<interactivity:Interaction.Behaviors>
|
<interactivity:Interaction.Behaviors>
|
||||||
@@ -139,7 +141,7 @@
|
|||||||
<viewModels:EntryVm/>
|
<viewModels:EntryVm/>
|
||||||
</GridView.DataContext>
|
</GridView.DataContext>
|
||||||
<GridView.ItemTemplateSelector>
|
<GridView.ItemTemplateSelector>
|
||||||
<local:FirstItemDataTemplateSelector
|
<templateSelectors:FirstItemDataTemplateSelector
|
||||||
FirstItem="{StaticResource GroupFirstItem}"
|
FirstItem="{StaticResource GroupFirstItem}"
|
||||||
OtherItem="{StaticResource GroupOtherItem}" />
|
OtherItem="{StaticResource GroupOtherItem}" />
|
||||||
</GridView.ItemTemplateSelector>
|
</GridView.ItemTemplateSelector>
|
||||||
|
@@ -1,16 +1,14 @@
|
|||||||
<Page
|
<basePages:LayoutAwarePageBase
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:viewModels="using:ModernKeePass.ViewModels"
|
xmlns:viewModels="using:ModernKeePass.ViewModels"
|
||||||
xmlns:controls="using:ModernKeePass.Controls"
|
xmlns:controls="using:ModernKeePass.Controls"
|
||||||
x:Class="ModernKeePass.MainPage"
|
xmlns:basePages="using:ModernKeePass.Pages.BasePages"
|
||||||
mc:Ignorable="d"
|
x:Class="ModernKeePass.Pages.MainPage"
|
||||||
Background="{StaticResource ApplicationPageBackgroundThemeBrush}" >
|
x:Name="PageRoot"
|
||||||
<Page.DataContext>
|
mc:Ignorable="d">
|
||||||
<viewModels:MainVm />
|
|
||||||
</Page.DataContext>
|
|
||||||
<Page.Resources>
|
<Page.Resources>
|
||||||
<CollectionViewSource
|
<CollectionViewSource
|
||||||
x:Name="MenuItemsSource"
|
x:Name="MenuItemsSource"
|
||||||
@@ -18,49 +16,136 @@
|
|||||||
IsSourceGrouped="True" />
|
IsSourceGrouped="True" />
|
||||||
</Page.Resources>
|
</Page.Resources>
|
||||||
|
|
||||||
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}" >
|
<Page.Background>
|
||||||
|
<StaticResource ResourceKey="ApplicationPageBackgroundThemeBrush"/>
|
||||||
|
</Page.Background>
|
||||||
|
<Page.DataContext>
|
||||||
|
<viewModels:MainVm />
|
||||||
|
</Page.DataContext>
|
||||||
|
|
||||||
|
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
|
||||||
|
<Grid.ChildrenTransitions>
|
||||||
|
<TransitionCollection>
|
||||||
|
<EntranceThemeTransition/>
|
||||||
|
</TransitionCollection>
|
||||||
|
</Grid.ChildrenTransitions>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="70"/>
|
||||||
|
<RowDefinition Height="*"/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="Auto" />
|
<ColumnDefinition x:Name="PrimaryColumn" Width="350" />
|
||||||
<ColumnDefinition Width="50" />
|
<ColumnDefinition x:Name="SecondaryColumn" Width="*" />
|
||||||
<ColumnDefinition Width="Auto" />
|
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<controls:ListViewWithDisable Grid.Column="0"
|
|
||||||
|
<!-- Back button and page title -->
|
||||||
|
<Grid x:Name="TitlePanel" Background="{ThemeResource AppBarBackgroundThemeBrush}">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Button x:Name="BackButton" Margin="39,20,0,0" Command="{Binding NavigationHelper.GoBackCommand, ElementName=PageRoot}"
|
||||||
|
Style="{StaticResource NavigationBackButtonNormalStyle}"
|
||||||
|
Visibility="Collapsed"
|
||||||
|
VerticalAlignment="Top"
|
||||||
|
AutomationProperties.Name="Back"
|
||||||
|
AutomationProperties.AutomationId="BackButton"
|
||||||
|
AutomationProperties.ItemType="Navigation Button"/>
|
||||||
|
<TextBlock x:Name="TitleTextBox" Text="{Binding Name}" Grid.Column="1" FontSize="24" Margin="20" />
|
||||||
|
</Grid>
|
||||||
|
<controls:ListViewWithDisable
|
||||||
|
Grid.Column="0"
|
||||||
|
Grid.Row="1"
|
||||||
x:Name="MenuListView"
|
x:Name="MenuListView"
|
||||||
RequestedTheme="Dark"
|
SelectionChanged="MenuListView_SelectionChanged"
|
||||||
SelectionChanged="ListView_SelectionChanged"
|
Background="{ThemeResource AppBarBackgroundThemeBrush}"
|
||||||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
|
|
||||||
ItemsSource="{Binding Source={StaticResource MenuItemsSource}}"
|
ItemsSource="{Binding Source={StaticResource MenuItemsSource}}"
|
||||||
SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
|
SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
|
||||||
IsSynchronizedWithCurrentItem="False">
|
IsSynchronizedWithCurrentItem="False">
|
||||||
<ListView.Header>
|
<controls:ListViewWithDisable.ItemTemplate>
|
||||||
<TextBlock Text="{Binding Name}" FontWeight="Bold" FontSize="36" Margin="20" />
|
|
||||||
</ListView.Header>
|
|
||||||
<ListView.ItemTemplate>
|
|
||||||
<DataTemplate >
|
<DataTemplate >
|
||||||
<StackPanel Orientation="Horizontal">
|
<StackPanel Orientation="Horizontal">
|
||||||
<SymbolIcon Symbol="{Binding SymbolIcon}" />
|
<SymbolIcon Symbol="{Binding SymbolIcon}" />
|
||||||
<TextBlock Text="{Binding Title}" Margin="10,5,0,0" />
|
<TextBlock Text="{Binding Title}" Margin="10,5,0,0" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ListView.ItemTemplate>
|
</controls:ListViewWithDisable.ItemTemplate>
|
||||||
<ListView.ItemContainerStyle>
|
<controls:ListViewWithDisable.ItemContainerStyle>
|
||||||
<Style TargetType="ListViewItem">
|
<Style TargetType="ListViewItem">
|
||||||
<Setter Property="Padding" Value="20,5,0,0" />
|
<Setter Property="Padding" Value="20,5,0,0" />
|
||||||
<Setter Property="Margin" Value="0" />
|
<Setter Property="Margin" Value="0" />
|
||||||
</Style>
|
</Style>
|
||||||
</ListView.ItemContainerStyle>
|
</controls:ListViewWithDisable.ItemContainerStyle>
|
||||||
<ListView.GroupStyle>
|
<controls:ListViewWithDisable.GroupStyle>
|
||||||
<GroupStyle HidesIfEmpty="True">
|
<GroupStyle HidesIfEmpty="True">
|
||||||
<GroupStyle.HeaderTemplate>
|
<GroupStyle.HeaderTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate>
|
||||||
<Grid Background="DarkGray" Margin="20,0,0,0">
|
<Grid Background="DarkGray" Margin="20,0,0,0">
|
||||||
<Border Height="1" Width="240" HorizontalAlignment="Stretch"/>
|
<Border Height="1" Width="300" HorizontalAlignment="Stretch"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</GroupStyle.HeaderTemplate>
|
</GroupStyle.HeaderTemplate>
|
||||||
</GroupStyle>
|
</GroupStyle>
|
||||||
</ListView.GroupStyle>
|
</controls:ListViewWithDisable.GroupStyle>
|
||||||
</controls:ListViewWithDisable>
|
</controls:ListViewWithDisable>
|
||||||
<Frame Grid.Column="2" Name="MenuFrame" Width="auto" Margin="0,60,0,0" />
|
<Frame x:Name="MenuFrame" Grid.Column="1" Grid.Row="0" Grid.RowSpan="2" Width="auto" Margin="30,60,0,0" />
|
||||||
|
|
||||||
|
<VisualStateManager.VisualStateGroups>
|
||||||
|
<!-- Visual states reflect the application's view state -->
|
||||||
|
<VisualStateGroup x:Name="ViewStates">
|
||||||
|
<VisualState x:Name="PrimaryView" />
|
||||||
|
<VisualState x:Name="SinglePane">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PrimaryColumn" Storyboard.TargetProperty="Width">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="*"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SecondaryColumn" Storyboard.TargetProperty="Width">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="0"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="MenuFrame" Storyboard.TargetProperty="Visibility">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="MenuListView" Storyboard.TargetProperty="Padding">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="120,0,90,60"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<!--
|
||||||
|
When an item is selected and only one pane is shown the details display requires more extensive changes:
|
||||||
|
* Hide the master list and the column it was in
|
||||||
|
* Move item details down a row to make room for the title
|
||||||
|
* Move the title directly above the details
|
||||||
|
* Adjust padding for details
|
||||||
|
-->
|
||||||
|
<VisualState x:Name="SinglePane_Detail">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PrimaryColumn" Storyboard.TargetProperty="Width">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="0"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="MenuListView" Storyboard.TargetProperty="Visibility">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="MenuFrame" Storyboard.TargetProperty="(Grid.Row)">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="MenuFrame" Storyboard.TargetProperty="(Grid.RowSpan)">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TitlePanel" Storyboard.TargetProperty="(Grid.Column)">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackButton" Storyboard.TargetProperty="Visibility">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TitleTextBox" Storyboard.TargetProperty="Visibility">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="MenuFrame" Storyboard.TargetProperty="Margin">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="10,0,0,0"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateManager.VisualStateGroups>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Page>
|
</basePages:LayoutAwarePageBase>
|
@@ -1,34 +1,56 @@
|
|||||||
using Windows.UI.Xaml.Controls;
|
using System;
|
||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
using Windows.UI.Xaml.Navigation;
|
using Windows.UI.Xaml.Navigation;
|
||||||
using ModernKeePass.Pages;
|
|
||||||
using ModernKeePass.ViewModels;
|
using ModernKeePass.ViewModels;
|
||||||
|
|
||||||
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
|
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
|
||||||
|
|
||||||
namespace ModernKeePass
|
namespace ModernKeePass.Pages
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An empty page that can be used on its own or navigated to within a Frame.
|
/// An empty page that can be used on its own or navigated to within a Frame.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed partial class MainPage
|
public sealed partial class MainPage
|
||||||
{
|
{
|
||||||
public MainVm Model => (MainVm)DataContext;
|
public new MainVm Model => (MainVm)DataContext;
|
||||||
|
|
||||||
public MainPage()
|
public MainPage()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
ListView = MenuListView;
|
||||||
|
ListViewSource = MenuItemsSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void MenuListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
ListView_SelectionChanged(sender, e);
|
||||||
|
var selectedItem = Model.SelectedItem as MainMenuItemVm;
|
||||||
|
selectedItem?.Destination.Navigate(selectedItem.PageType, selectedItem.Parameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
#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)
|
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||||
{
|
{
|
||||||
base.OnNavigatedTo(e);
|
NavigationHelper.OnNavigatedTo(e);
|
||||||
DataContext = new MainVm(Frame, MenuFrame);
|
DataContext = new MainVm(Frame, MenuFrame);
|
||||||
if (Model.SelectedItem == null) MenuFrame.Navigate(typeof(WelcomePage));
|
if (Model.SelectedItem == null) MenuFrame.Navigate(typeof(WelcomePage));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
protected override void OnNavigatedFrom(NavigationEventArgs e)
|
||||||
{
|
{
|
||||||
Model.SelectedItem?.Destination.Navigate(Model.SelectedItem.PageType, Model.SelectedItem.Parameter);
|
NavigationHelper.OnNavigatedFrom(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -12,7 +12,7 @@
|
|||||||
</Page.DataContext>
|
</Page.DataContext>
|
||||||
|
|
||||||
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||||
<TextBlock Style="{StaticResource HeaderTextBlockStyle}" Margin="0,-20,0,20">
|
<TextBlock Style="{StaticResource HeaderTextBlockStyle}" Margin="80,-60,0,20" FontSize="36">
|
||||||
<Run Text="About"/>
|
<Run Text="About"/>
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
<TextBlock Style="{StaticResource BodyTextBlockStyle}">
|
<TextBlock Style="{StaticResource BodyTextBlockStyle}">
|
@@ -19,7 +19,9 @@
|
|||||||
</Page.DataContext>
|
</Page.DataContext>
|
||||||
|
|
||||||
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||||
<TextBlock Style="{StaticResource HeaderTextBlockStyle}" Margin="0,-20,0,20">New</TextBlock>
|
<TextBlock Style="{StaticResource HeaderTextBlockStyle}" Margin="80,-60,0,20" FontSize="36">
|
||||||
|
<Run Text="New"></Run>
|
||||||
|
</TextBlock>
|
||||||
<HyperlinkButton Content="Create new..." Click="ButtonBase_OnClick" />
|
<HyperlinkButton Content="Create new..." Click="ButtonBase_OnClick" />
|
||||||
<TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="15,0,0,30">Create a new password database to the location of your chosing.</TextBlock>
|
<TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="15,0,0,30">Create a new password database to the location of your chosing.</TextBlock>
|
||||||
<Border HorizontalAlignment="Left" BorderThickness="1" BorderBrush="AliceBlue" Width="550" Visibility="{Binding ShowPasswordBox, Converter={StaticResource BooleanToVisibilityConverter}}">
|
<Border HorizontalAlignment="Left" BorderThickness="1" BorderBrush="AliceBlue" Width="550" Visibility="{Binding ShowPasswordBox, Converter={StaticResource BooleanToVisibilityConverter}}">
|
@@ -17,7 +17,9 @@
|
|||||||
</Page.DataContext>
|
</Page.DataContext>
|
||||||
|
|
||||||
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||||
<TextBlock Style="{StaticResource HeaderTextBlockStyle}" Margin="0,-20,0,20">Open</TextBlock>
|
<TextBlock Style="{StaticResource HeaderTextBlockStyle}" Margin="80,-60,0,20" FontSize="36">
|
||||||
|
<Run Text="Open"></Run>
|
||||||
|
</TextBlock>
|
||||||
<HyperlinkButton Content="Browse files..." Click="ButtonBase_OnClick" />
|
<HyperlinkButton Content="Browse files..." Click="ButtonBase_OnClick" />
|
||||||
<TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="15,0,0,30">Open an existing password database from your PC.</TextBlock>
|
<TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="15,0,0,30">Open an existing password database from your PC.</TextBlock>
|
||||||
<HyperlinkButton Content="From Url..." IsEnabled="False" />
|
<HyperlinkButton Content="From Url..." IsEnabled="False" />
|
@@ -17,7 +17,7 @@
|
|||||||
<viewModels:RecentVm/>
|
<viewModels:RecentVm/>
|
||||||
</Page.DataContext>
|
</Page.DataContext>
|
||||||
<StackPanel Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
|
<StackPanel Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
|
||||||
<TextBlock Style="{StaticResource HeaderTextBlockStyle}" Margin="0,-20,0,20">
|
<TextBlock Style="{StaticResource HeaderTextBlockStyle}" Margin="80,-60,0,20" FontSize="36">
|
||||||
<Run Text="Recent"/>
|
<Run Text="Recent"/>
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
<ListView
|
<ListView
|
@@ -11,7 +11,9 @@
|
|||||||
</Page.DataContext>
|
</Page.DataContext>
|
||||||
|
|
||||||
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||||
<TextBlock Style="{StaticResource HeaderTextBlockStyle}" Margin="0,-20,0,20">Save</TextBlock>
|
<TextBlock Style="{StaticResource HeaderTextBlockStyle}" Margin="80,-60,0,20" FontSize="36">
|
||||||
|
<Run Text="Save"></Run>
|
||||||
|
</TextBlock>
|
||||||
<HyperlinkButton Content="Save and close" Click="SaveButton_OnClick" />
|
<HyperlinkButton Content="Save and close" Click="SaveButton_OnClick" />
|
||||||
<TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="15,0,0,30">This will save and close the currently opened database.</TextBlock>
|
<TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="15,0,0,30">This will save and close the currently opened database.</TextBlock>
|
||||||
<HyperlinkButton Content="Save as..." Click="SaveAsButton_OnClick" />
|
<HyperlinkButton Content="Save as..." Click="SaveAsButton_OnClick" />
|
181
ModernKeePass/Pages/SettingsPage.xaml
Normal file
181
ModernKeePass/Pages/SettingsPage.xaml
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
<Page
|
||||||
|
x:Name="pageRoot"
|
||||||
|
x:Class="ModernKeePass.Pages.SettingsPage"
|
||||||
|
DataContext="{Binding DefaultViewModel, RelativeSource={RelativeSource Self}}"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:local="using:ModernKeePass.Pages"
|
||||||
|
xmlns:common="using:ModernKeePass.Common"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
mc:Ignorable="d">
|
||||||
|
|
||||||
|
<Page.Resources>
|
||||||
|
<!-- Collection of items displayed by this page -->
|
||||||
|
<CollectionViewSource
|
||||||
|
x:Name="itemsViewSource"
|
||||||
|
Source="{Binding Items}"/>
|
||||||
|
</Page.Resources>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
This grid acts as a root panel for the page that defines two rows:
|
||||||
|
* Row 0 contains the back button and page title
|
||||||
|
* Row 1 contains the rest of the page layout
|
||||||
|
-->
|
||||||
|
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||||
|
<Grid.ChildrenTransitions>
|
||||||
|
<TransitionCollection>
|
||||||
|
<EntranceThemeTransition/>
|
||||||
|
</TransitionCollection>
|
||||||
|
</Grid.ChildrenTransitions>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="140"/>
|
||||||
|
<RowDefinition Height="*"/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition x:Name="primaryColumn" Width="420"/>
|
||||||
|
<ColumnDefinition x:Name="secondaryColumn" Width="*"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<!-- Back button and page title -->
|
||||||
|
<Grid x:Name="titlePanel">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="120"/>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Button x:Name="backButton" Margin="39,59,39,0" Command="{Binding NavigationHelper.GoBackCommand, ElementName=pageRoot}"
|
||||||
|
Style="{StaticResource NavigationBackButtonNormalStyle}"
|
||||||
|
VerticalAlignment="Top"
|
||||||
|
AutomationProperties.Name="Back"
|
||||||
|
AutomationProperties.AutomationId="BackButton"
|
||||||
|
AutomationProperties.ItemType="Navigation Button"/>
|
||||||
|
<TextBlock x:Name="pageTitle" Text="{Binding Title}" Style="{StaticResource HeaderTextBlockStyle}" Grid.Column="1"
|
||||||
|
IsHitTestVisible="false" TextWrapping="NoWrap" VerticalAlignment="Bottom" Margin="0,0,0,40"/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<!-- Vertical scrolling item list -->
|
||||||
|
<ListView
|
||||||
|
x:Name="itemListView"
|
||||||
|
AutomationProperties.AutomationId="ItemsListView"
|
||||||
|
AutomationProperties.Name="Items"
|
||||||
|
TabIndex="1"
|
||||||
|
Grid.Row="1"
|
||||||
|
Margin="-10,-10,0,0"
|
||||||
|
Padding="120,0,0,60"
|
||||||
|
ItemsSource="{Binding Source={StaticResource itemsViewSource}}"
|
||||||
|
IsSwipeEnabled="False"
|
||||||
|
SelectionChanged="ItemListView_SelectionChanged">
|
||||||
|
<ListView.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<Grid Margin="6">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Border Background="{ThemeResource ListViewItemPlaceholderBackgroundThemeBrush}" Width="60" Height="60">
|
||||||
|
<Image Source="{Binding ImagePath}" Stretch="UniformToFill" AutomationProperties.Name="{Binding Title}"/>
|
||||||
|
</Border>
|
||||||
|
<StackPanel Grid.Column="1" Margin="10,0,0,0">
|
||||||
|
<TextBlock Text="{Binding Title}" Style="{StaticResource TitleTextBlockStyle}" TextWrapping="NoWrap" MaxHeight="40"/>
|
||||||
|
<TextBlock Text="{Binding Subtitle}" Style="{StaticResource CaptionTextBlockStyle}" TextWrapping="NoWrap"/>
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
</DataTemplate>
|
||||||
|
</ListView.ItemTemplate>
|
||||||
|
<ListView.ItemContainerStyle>
|
||||||
|
<Style TargetType="FrameworkElement">
|
||||||
|
<Setter Property="Margin" Value="0,0,0,10"/>
|
||||||
|
</Style>
|
||||||
|
</ListView.ItemContainerStyle>
|
||||||
|
</ListView>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Details for selected item -->
|
||||||
|
<ScrollViewer
|
||||||
|
x:Name="itemDetail"
|
||||||
|
AutomationProperties.AutomationId="ItemDetailScrollViewer"
|
||||||
|
Grid.Column="1"
|
||||||
|
Grid.RowSpan="2"
|
||||||
|
Padding="60,0,66,0"
|
||||||
|
DataContext="{Binding SelectedItem, ElementName=itemListView}"
|
||||||
|
HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto"
|
||||||
|
ScrollViewer.HorizontalScrollMode="Disabled" ScrollViewer.VerticalScrollMode="Enabled"
|
||||||
|
ScrollViewer.ZoomMode="Disabled">
|
||||||
|
|
||||||
|
<Grid x:Name="itemDetailGrid" Margin="0,60,0,50">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="*"/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<Image Grid.Row="1" Margin="0,0,20,0" Width="180" Height="180" Source="{Binding ImagePath}" Stretch="UniformToFill" AutomationProperties.Name="{Binding Title}"/>
|
||||||
|
<StackPanel x:Name="itemDetailTitlePanel" Grid.Row="1" Grid.Column="1">
|
||||||
|
<TextBlock x:Name="itemTitle" Margin="0,-10,0,0" Text="{Binding Title}" Style="{StaticResource SubheaderTextBlockStyle}"/>
|
||||||
|
<TextBlock x:Name="itemSubtitle" Margin="0,0,0,20" Text="{Binding Subtitle}" Style="{StaticResource SubtitleTextBlockStyle}"/>
|
||||||
|
</StackPanel>
|
||||||
|
<TextBlock Grid.Row="2" Grid.ColumnSpan="2" Margin="0,20,0,0" Text="{Binding Content}" Style="{StaticResource BodyTextBlockStyle}"/>
|
||||||
|
</Grid>
|
||||||
|
</ScrollViewer>
|
||||||
|
|
||||||
|
<VisualStateManager.VisualStateGroups>
|
||||||
|
|
||||||
|
<!-- Visual states reflect the application's view state -->
|
||||||
|
<VisualStateGroup x:Name="ViewStates">
|
||||||
|
<VisualState x:Name="PrimaryView" />
|
||||||
|
<VisualState x:Name="SinglePane">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="primaryColumn" Storyboard.TargetProperty="Width">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="*"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="secondaryColumn" Storyboard.TargetProperty="Width">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="0"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemDetail" Storyboard.TargetProperty="Visibility">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemListView" Storyboard.TargetProperty="Padding">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="120,0,90,60"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<!--
|
||||||
|
When an item is selected and only one pane is shown the details display requires more extensive changes:
|
||||||
|
* Hide the master list and the column it was in
|
||||||
|
* Move item details down a row to make room for the title
|
||||||
|
* Move the title directly above the details
|
||||||
|
* Adjust padding for details
|
||||||
|
-->
|
||||||
|
<VisualState x:Name="SinglePane_Detail">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="primaryColumn" Storyboard.TargetProperty="Width">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="0"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemListView" Storyboard.TargetProperty="Visibility">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemDetail" Storyboard.TargetProperty="(Grid.Row)">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemDetail" Storyboard.TargetProperty="(Grid.RowSpan)">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="titlePanel" Storyboard.TargetProperty="(Grid.Column)">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemDetailGrid" Storyboard.TargetProperty="Margin">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="0,0,0,60"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemDetail" Storyboard.TargetProperty="Padding">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="120,0,90,0"/>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateManager.VisualStateGroups>
|
||||||
|
</Grid>
|
||||||
|
</Page>
|
255
ModernKeePass/Pages/SettingsPage.xaml.cs
Normal file
255
ModernKeePass/Pages/SettingsPage.xaml.cs
Normal file
@@ -0,0 +1,255 @@
|
|||||||
|
using ModernKeePass.Common;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices.WindowsRuntime;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using Windows.Foundation;
|
||||||
|
using Windows.Foundation.Collections;
|
||||||
|
using Windows.UI.ViewManagement;
|
||||||
|
using Windows.UI.Xaml;
|
||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
|
using Windows.UI.Xaml.Controls.Primitives;
|
||||||
|
using Windows.UI.Xaml.Data;
|
||||||
|
using Windows.UI.Xaml.Input;
|
||||||
|
using Windows.UI.Xaml.Media;
|
||||||
|
using Windows.UI.Xaml.Navigation;
|
||||||
|
|
||||||
|
// The Split Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234234
|
||||||
|
|
||||||
|
namespace ModernKeePass.Pages
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A page that displays a group title, a list of items within the group, and details for
|
||||||
|
/// the currently selected item.
|
||||||
|
/// </summary>
|
||||||
|
public sealed partial class SettingsPage : Page
|
||||||
|
{
|
||||||
|
private NavigationHelper navigationHelper;
|
||||||
|
private ObservableDictionary defaultViewModel = new ObservableDictionary();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This can be changed to a strongly typed view model.
|
||||||
|
/// </summary>
|
||||||
|
public ObservableDictionary DefaultViewModel
|
||||||
|
{
|
||||||
|
get { return this.defaultViewModel; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// NavigationHelper is used on each page to aid in navigation and
|
||||||
|
/// process lifetime management
|
||||||
|
/// </summary>
|
||||||
|
public NavigationHelper NavigationHelper
|
||||||
|
{
|
||||||
|
get { return this.navigationHelper; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public SettingsPage()
|
||||||
|
{
|
||||||
|
this.InitializeComponent();
|
||||||
|
|
||||||
|
// Setup the navigation helper
|
||||||
|
this.navigationHelper = new NavigationHelper(this);
|
||||||
|
this.navigationHelper.LoadState += navigationHelper_LoadState;
|
||||||
|
this.navigationHelper.SaveState += navigationHelper_SaveState;
|
||||||
|
|
||||||
|
// Setup the logical page navigation components that allow
|
||||||
|
// the page to only show one pane at a time.
|
||||||
|
this.navigationHelper.GoBackCommand = new ModernKeePass.Common.RelayCommand(() => this.GoBack(), () => this.CanGoBack());
|
||||||
|
this.itemListView.SelectionChanged += itemListView_SelectionChanged;
|
||||||
|
|
||||||
|
// Start listening for Window size changes
|
||||||
|
// to change from showing two panes to showing a single pane
|
||||||
|
Window.Current.SizeChanged += Window_SizeChanged;
|
||||||
|
this.InvalidateVisualState();
|
||||||
|
}
|
||||||
|
|
||||||
|
void itemListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (this.UsingLogicalPageNavigation())
|
||||||
|
{
|
||||||
|
this.navigationHelper.GoBackCommand.RaiseCanExecuteChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <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>
|
||||||
|
private 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 (!this.UsingLogicalPageNavigation() && this.itemsViewSource.View != null)
|
||||||
|
{
|
||||||
|
this.itemsViewSource.View.MoveCurrentToFirst();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Restore the previously saved state associated with this page
|
||||||
|
if (e.PageState.ContainsKey("SelectedItem") && this.itemsViewSource.View != null)
|
||||||
|
{
|
||||||
|
// TODO: Invoke Me.itemsViewSource.View.MoveCurrentTo() with the selected
|
||||||
|
// item as specified by the value of 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>
|
||||||
|
private void navigationHelper_SaveState(object sender, SaveStateEventArgs e)
|
||||||
|
{
|
||||||
|
if (this.itemsViewSource.View != null)
|
||||||
|
{
|
||||||
|
// TODO: Derive a serializable navigation parameter and assign it to
|
||||||
|
// pageState("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.
|
||||||
|
|
||||||
|
private 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>
|
||||||
|
private 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>
|
||||||
|
private void Window_SizeChanged(object sender, Windows.UI.Core.WindowSizeChangedEventArgs e)
|
||||||
|
{
|
||||||
|
this.InvalidateVisualState();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invoked when an item within the list is selected.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender">The GridView displaying the selected item.</param>
|
||||||
|
/// <param name="e">Event data that describes how the selection was changed.</param>
|
||||||
|
private void ItemListView_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 (this.UsingLogicalPageNavigation()) this.InvalidateVisualState();
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool CanGoBack()
|
||||||
|
{
|
||||||
|
if (this.UsingLogicalPageNavigation() && this.itemListView.SelectedItem != null)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return this.navigationHelper.CanGoBack();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void GoBack()
|
||||||
|
{
|
||||||
|
if (this.UsingLogicalPageNavigation() && this.itemListView.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.
|
||||||
|
this.itemListView.SelectedItem = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.navigationHelper.GoBack();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InvalidateVisualState()
|
||||||
|
{
|
||||||
|
var visualState = DetermineVisualState();
|
||||||
|
VisualStateManager.GoToState(this, visualState, false);
|
||||||
|
this.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>
|
||||||
|
private string DetermineVisualState()
|
||||||
|
{
|
||||||
|
if (!UsingLogicalPageNavigation())
|
||||||
|
return "PrimaryView";
|
||||||
|
|
||||||
|
// Update the back button's enabled state when the view state changes
|
||||||
|
var logicalPageBack = this.UsingLogicalPageNavigation() && this.itemListView.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
|
||||||
|
}
|
||||||
|
}
|
@@ -1,7 +1,7 @@
|
|||||||
using Windows.UI.Xaml;
|
using Windows.UI.Xaml;
|
||||||
using Windows.UI.Xaml.Controls;
|
using Windows.UI.Xaml.Controls;
|
||||||
|
|
||||||
namespace ModernKeePass.Controls
|
namespace ModernKeePass.TemplateSelectors
|
||||||
{
|
{
|
||||||
public class FirstItemDataTemplateSelector: DataTemplateSelector
|
public class FirstItemDataTemplateSelector: DataTemplateSelector
|
||||||
{
|
{
|
@@ -5,7 +5,7 @@ using ModernKeePass.Interfaces;
|
|||||||
|
|
||||||
namespace ModernKeePass.ViewModels
|
namespace ModernKeePass.ViewModels
|
||||||
{
|
{
|
||||||
public class MainMenuItemVm: NotifyPropertyChangedBase, IIsEnabled
|
public class MainMenuItemVm: NotifyPropertyChangedBase, IIsEnabled, ISelectableModel
|
||||||
{
|
{
|
||||||
private bool _isSelected;
|
private bool _isSelected;
|
||||||
|
|
||||||
|
@@ -5,11 +5,13 @@ using Windows.Storage.AccessCache;
|
|||||||
using Windows.UI.Xaml;
|
using Windows.UI.Xaml;
|
||||||
using Windows.UI.Xaml.Controls;
|
using Windows.UI.Xaml.Controls;
|
||||||
using ModernKeePass.Common;
|
using ModernKeePass.Common;
|
||||||
|
using ModernKeePass.Interfaces;
|
||||||
using ModernKeePass.Pages;
|
using ModernKeePass.Pages;
|
||||||
|
using ModernKeePass.Pages.BasePages;
|
||||||
|
|
||||||
namespace ModernKeePass.ViewModels
|
namespace ModernKeePass.ViewModels
|
||||||
{
|
{
|
||||||
public class MainVm : NotifyPropertyChangedBase
|
public class MainVm : NotifyPropertyChangedBase, IHasSelectableObject
|
||||||
{
|
{
|
||||||
private IOrderedEnumerable<IGrouping<int, MainMenuItemVm>> _mainMenuItems;
|
private IOrderedEnumerable<IGrouping<int, MainMenuItemVm>> _mainMenuItems;
|
||||||
private MainMenuItemVm _selectedItem;
|
private MainMenuItemVm _selectedItem;
|
||||||
@@ -22,7 +24,7 @@ namespace ModernKeePass.ViewModels
|
|||||||
set { SetProperty(ref _mainMenuItems, value); }
|
set { SetProperty(ref _mainMenuItems, value); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public MainMenuItemVm SelectedItem
|
public ISelectableModel SelectedItem
|
||||||
{
|
{
|
||||||
get { return _selectedItem; }
|
get { return _selectedItem; }
|
||||||
set
|
set
|
||||||
@@ -33,7 +35,7 @@ namespace ModernKeePass.ViewModels
|
|||||||
_selectedItem.IsSelected = false;
|
_selectedItem.IsSelected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetProperty(ref _selectedItem, value);
|
SetProperty(ref _selectedItem, (MainMenuItemVm)value);
|
||||||
|
|
||||||
if (_selectedItem != null)
|
if (_selectedItem != null)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user