Lots of code refactoring to use XAML behaviors instead of code-behind

New Save button in the AppBar
EntryPage now uses the same AppBar as GroupPage (but not shared...)
Some new Symbol mappings
This commit is contained in:
2017-10-25 18:29:50 +02:00
committed by BONNEVILLE Geoffroy
parent 8cd3801897
commit 46c8429cde
26 changed files with 241 additions and 179 deletions

View File

@@ -1,17 +0,0 @@
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Microsoft.Xaml.Interactivity;
namespace ModernKeePass.Actions
{
public class CloseFlyoutAction : DependencyObject, IAction
{
public object Execute(object sender, object parameter)
{
var flyout = sender as Flyout;
flyout?.Hide();
return null;
}
}
}

View File

@@ -1,4 +1,6 @@
using Windows.UI.Xaml; using System.Threading.Tasks;
using Windows.UI.Core;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls;
using Microsoft.Xaml.Interactivity; using Microsoft.Xaml.Interactivity;
@@ -13,11 +15,13 @@ namespace ModernKeePass.Actions
} }
public static readonly DependencyProperty TargetObjectProperty = public static readonly DependencyProperty TargetObjectProperty =
DependencyProperty.Register("TargetObject", typeof(Control), typeof(SetupFocusAction), new PropertyMetadata(0)); DependencyProperty.Register("TargetObject", typeof(Control), typeof(SetupFocusAction), new PropertyMetadata(null));
public object Execute(object sender, object parameter) public object Execute(object sender, object parameter)
{ {
return TargetObject?.Focus(FocusState.Programmatic); return Task.Factory.StartNew(
() => Dispatcher.RunAsync(CoreDispatcherPriority.Low,
() => TargetObject?.Focus(FocusState.Programmatic)));
} }
} }
} }

View File

@@ -33,7 +33,12 @@ namespace ModernKeePass.Common
} }
} }
/// <summary>
/// Open a KeePass database
/// </summary>
/// <param name="password">The database password</param>
/// <param name="createNew">True to create a new database before opening it</param>
/// <returns>An error message, if any</returns>
public string Open(string password, bool createNew = false) public string Open(string password, bool createNew = false)
{ {
var key = new CompositeKey(); var key = new CompositeKey();
@@ -65,6 +70,10 @@ namespace ModernKeePass.Common
return string.Empty; return string.Empty;
} }
/// <summary>
/// Save the current database to another file and open it
/// </summary>
/// <param name="file">The new database file</param>
internal void Save(StorageFile file) internal void Save(StorageFile file)
{ {
DatabaseFile = file; DatabaseFile = file;
@@ -72,12 +81,18 @@ namespace ModernKeePass.Common
Status = DatabaseStatus.Opened; Status = DatabaseStatus.Opened;
} }
/// <summary>
/// Commit the changes to the currently opened database to file
/// </summary>
public void Save() public void Save()
{ {
if (_pwDatabase != null && _pwDatabase.IsOpen) if (_pwDatabase != null && _pwDatabase.IsOpen)
_pwDatabase.Save(new NullStatusLogger()); _pwDatabase.Save(new NullStatusLogger());
} }
/// <summary>
/// Close the currently opened database
/// </summary>
public void Close() public void Close()
{ {
_pwDatabase?.Close(); _pwDatabase?.Close();

View File

@@ -0,0 +1,35 @@
using System;
using Windows.UI.Popups;
using Windows.UI.Xaml.Controls;
using ModernKeePass.Interfaces;
using ModernKeePass.ViewModels;
namespace ModernKeePass.Common
{
public static class MessageDialogHelper
{
public static async void ShowDeleteConfirmationDialog(string text, IPwEntity model, Frame backFrame)
{
// Create the message dialog and set its content
var messageDialog = new MessageDialog(text);
// Add commands and set their callbacks; both buttons use the same callback function instead of inline event handlers
messageDialog.Commands.Add(new UICommand("Delete", delete =>
{
ToastNotificationHelper.ShowUndoToast(model);
model.MarkForDelete();
if (backFrame.CanGoBack) backFrame.GoBack();
}));
messageDialog.Commands.Add(new UICommand("Cancel"));
// Set the command that will be invoked by default
messageDialog.DefaultCommandIndex = 1;
// Set the command to be invoked when escape is pressed
messageDialog.CancelCommandIndex = 1;
// Show the message dialog
await messageDialog.ShowAsync();
}
}
}

View File

@@ -4,12 +4,13 @@ using Windows.Data.Xml.Dom;
using Windows.UI.Notifications; using Windows.UI.Notifications;
using Windows.UI.Xaml; using Windows.UI.Xaml;
using ModernKeePass.Interfaces; using ModernKeePass.Interfaces;
using ModernKeePass.ViewModels;
namespace ModernKeePass.Common namespace ModernKeePass.Common
{ {
public static class ToastNotificationHelper public static class ToastNotificationHelper
{ {
public static /*async*/ void ShowUndoToast(string entityType, IPwEntity entity) public static /*async*/ void ShowUndoToast(IPwEntity entity)
{ {
// This is for Windows 10 // This is for Windows 10
// Construct the visuals of the toast // Construct the visuals of the toast
@@ -64,6 +65,8 @@ namespace ModernKeePass.Common
var toast = new ToastNotification(toastXml) {ExpirationTime = DateTime.Now.AddSeconds(5)}; var toast = new ToastNotification(toastXml) {ExpirationTime = DateTime.Now.AddSeconds(5)};
toast.Dismissed += Toast_Dismissed; toast.Dismissed += Toast_Dismissed;
*/ */
var entityType = entity is GroupVm ? "Group" : "Entry";
var notificationXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText02); var notificationXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText02);
var toastElements = notificationXml.GetElementsByTagName("text"); var toastElements = notificationXml.GetElementsByTagName("text");
toastElements[0].AppendChild(notificationXml.CreateTextNode($"{entityType} {entity.Name} deleted")); toastElements[0].AppendChild(notificationXml.CreateTextNode($"{entityType} {entity.Name} deleted"));

View File

@@ -13,5 +13,7 @@ namespace ModernKeePass.Interfaces
void CommitDelete(); void CommitDelete();
void UndoDelete(); void UndoDelete();
void Save();
void MarkForDelete();
} }
} }

View File

@@ -10,18 +10,19 @@ namespace ModernKeePass.Mappings
switch (icon) switch (icon)
{ {
case PwIcon.Key: return Symbol.Permissions; case PwIcon.Key: return Symbol.Permissions;
case PwIcon.WorldSocket:
case PwIcon.World: return Symbol.World; case PwIcon.World: return Symbol.World;
case PwIcon.Warning: return Symbol.Important; case PwIcon.Warning: return Symbol.Important;
case PwIcon.WorldComputer: case PwIcon.WorldComputer:
case PwIcon.Drive:
case PwIcon.DriveWindows: case PwIcon.DriveWindows:
case PwIcon.NetworkServer: return Symbol.MapDrive; case PwIcon.NetworkServer: return Symbol.MapDrive;
//case PwIcon.MarkedDirectory: return Symbol.; case PwIcon.MarkedDirectory: return Symbol.Map;
case PwIcon.UserCommunication: return Symbol.ContactInfo; case PwIcon.UserCommunication: return Symbol.ContactInfo;
//case PwIcon.Parts: return Symbol.; case PwIcon.Parts: return Symbol.ViewAll;
case PwIcon.Notepad: return Symbol.Document; case PwIcon.Notepad: return Symbol.Document;
//case PwIcon.WorldScoket: return Symbol.;
case PwIcon.Identity: return Symbol.Contact2; case PwIcon.Identity: return Symbol.Contact2;
//case PwIcon.PaperReady: return Symbol.; case PwIcon.PaperReady: return Symbol.SyncFolder;
case PwIcon.Digicam: return Symbol.Camera; case PwIcon.Digicam: return Symbol.Camera;
case PwIcon.IRCommunication: return Symbol.View; case PwIcon.IRCommunication: return Symbol.View;
case PwIcon.Energy: return Symbol.ZeroBars; case PwIcon.Energy: return Symbol.ZeroBars;
@@ -36,17 +37,16 @@ namespace ModernKeePass.Mappings
case PwIcon.Screen: return Symbol.GoToStart; case PwIcon.Screen: return Symbol.GoToStart;
case PwIcon.EnergyCareful: return Symbol.FourBars; case PwIcon.EnergyCareful: return Symbol.FourBars;
case PwIcon.Disk: return Symbol.Save; case PwIcon.Disk: return Symbol.Save;
//case PwIcon.Drive: return Symbol.;
//case PwIcon.PaperQ: return Symbol.; //case PwIcon.PaperQ: return Symbol.;
//case PwIcon.TerminalEncrypted: return Symbol.; //case PwIcon.TerminalEncrypted: return Symbol.;
//case PwIcon.Console: return Symbol.; case PwIcon.Console: return Symbol.SlideShow;
//case PwIcon.Printer: return Symbol.; case PwIcon.Printer: return Symbol.Scan;
case PwIcon.ProgramIcons: return Symbol.GoToStart; case PwIcon.ProgramIcons: return Symbol.GoToStart;
//case PwIcon.Run: return Symbol.; //case PwIcon.Run: return Symbol.;
case PwIcon.Settings: case PwIcon.Settings:
case PwIcon.Tool: return Symbol.Repair; case PwIcon.Tool: return Symbol.Repair;
//case PwIcon.Archive: return Symbol.; case PwIcon.Archive: return Symbol.Crop;
case PwIcon.Count: return Symbol.MapDrive; case PwIcon.Count: return Symbol.Calculator;
case PwIcon.Clock: return Symbol.Clock; case PwIcon.Clock: return Symbol.Clock;
case PwIcon.EMailSearch: return Symbol.Find; case PwIcon.EMailSearch: return Symbol.Find;
case PwIcon.PaperFlag: return Symbol.Flag; case PwIcon.PaperFlag: return Symbol.Flag;
@@ -72,10 +72,10 @@ namespace ModernKeePass.Mappings
//case PwIcon.Feather: return Symbol.; //case PwIcon.Feather: return Symbol.;
//case PwIcon.Apple: return Symbol.; //case PwIcon.Apple: return Symbol.;
//case PwIcon.Wiki: return Symbol.; //case PwIcon.Wiki: return Symbol.;
//case PwIcon.Money: return Symbol.; case PwIcon.Money: return Symbol.Shop;
case PwIcon.Certificate: return Symbol.PreviewLink; case PwIcon.Certificate: return Symbol.PreviewLink;
case PwIcon.BlackBerry: return Symbol.CellPhone; case PwIcon.BlackBerry: return Symbol.CellPhone;
default: return Symbol.More; default: return Symbol.Stop;
} }
} }
} }

View File

@@ -107,12 +107,12 @@
<Prefer32Bit>true</Prefer32Bit> <Prefer32Bit>true</Prefer32Bit>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Actions\CloseFlyoutAction.cs" />
<Compile Include="Actions\SetupFocusAction.cs" /> <Compile Include="Actions\SetupFocusAction.cs" />
<Compile Include="App.xaml.cs"> <Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon> <DependentUpon>App.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Common\DatabaseHelper.cs" /> <Compile Include="Common\DatabaseHelper.cs" />
<Compile Include="Common\MessageDialogHelper.cs" />
<Compile Include="Common\NavigationHelper.cs" /> <Compile Include="Common\NavigationHelper.cs" />
<Compile Include="Common\NotifyPropertyChangedBase.cs" /> <Compile Include="Common\NotifyPropertyChangedBase.cs" />
<Compile Include="Common\ObservableDictionary.cs" /> <Compile Include="Common\ObservableDictionary.cs" />
@@ -136,7 +136,7 @@
<Compile Include="Events\PasswordEventArgs.cs" /> <Compile Include="Events\PasswordEventArgs.cs" />
<Compile Include="Interfaces\IIsEnabled.cs" /> <Compile Include="Interfaces\IIsEnabled.cs" />
<Compile Include="Interfaces\IPwEntity.cs" /> <Compile Include="Interfaces\IPwEntity.cs" />
<Compile Include="MainPage.xaml.cs"> <Compile Include="Pages\MainPage.xaml.cs">
<DependentUpon>MainPage.xaml</DependentUpon> <DependentUpon>MainPage.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Mappings\PwIconToSegoeMapping.cs" /> <Compile Include="Mappings\PwIconToSegoeMapping.cs" />
@@ -198,7 +198,7 @@
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
</Page> </Page>
<Page Include="MainPage.xaml"> <Page Include="Pages\MainPage.xaml">
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Page> </Page>

View File

@@ -15,7 +15,11 @@
<TextBlock Style="{StaticResource HeaderTextBlockStyle}" Margin="0,-20,0,20"> <TextBlock Style="{StaticResource HeaderTextBlockStyle}" Margin="0,-20,0,20">
<Run Text="About"/> <Run Text="About"/>
</TextBlock> </TextBlock>
<TextBlock Style="{StaticResource BodyTextBlockStyle}" Text="{Binding Version}" /> <TextBlock Style="{StaticResource BodyTextBlockStyle}">
<Run Text="{Binding Name}"/>
<Run Text="version"/>
<Run Text="{Binding Version}" />
</TextBlock>
<TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="20,0,0,0"> <TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="20,0,0,0">
<Run Text="A modern password manager for the Windows Store"/> <Run Text="A modern password manager for the Windows Store"/>
</TextBlock> </TextBlock>

View File

@@ -6,12 +6,12 @@
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:local="using:ModernKeePass.Controls"
xmlns:Interactivity="using:Microsoft.Xaml.Interactivity" xmlns:Core="using:Microsoft.Xaml.Interactions.Core" xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
xmlns:Actions="using:ModernKeePass.Actions" xmlns:core="using:Microsoft.Xaml.Interactions.Core"
xmlns:actions="using:ModernKeePass.Actions"
x:Name="PageRoot" x:Name="PageRoot"
x:Class="ModernKeePass.Pages.EntryDetailPage" x:Class="ModernKeePass.Pages.EntryDetailPage"
mc:Ignorable="d"> mc:Ignorable="d">
<Page.Resources> <Page.Resources>
<converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/> <converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
<converters:InverseBooleanToVisibilityConverter x:Key="InverseBooleanToVisibilityConverter"/> <converters:InverseBooleanToVisibilityConverter x:Key="InverseBooleanToVisibilityConverter"/>
@@ -327,15 +327,17 @@
FontSize="{TemplateBinding FontSize}" FontSize="{TemplateBinding FontSize}"
VerticalAlignment="Stretch" > VerticalAlignment="Stretch" >
<Button.Flyout> <Button.Flyout>
<Flyout x:Name="GenerateButtonFlyout"> <Flyout>
<Interactivity:Interaction.Behaviors> <interactivity:Interaction.Behaviors>
<Core:DataTriggerBehavior Binding="{Binding Password}" ComparisonCondition="NotEqual" Value="" > <core:DataTriggerBehavior Binding="{Binding Password}" ComparisonCondition="NotEqual" Value="" >
<Actions:CloseFlyoutAction /> <!--<actions:CloseFlyoutAction />-->
</Core:DataTriggerBehavior> <core:CallMethodAction MethodName="Hide" />
</Interactivity:Interaction.Behaviors> </core:DataTriggerBehavior>
</interactivity:Interaction.Behaviors>
<StackPanel> <StackPanel>
<TextBlock> <TextBlock>
<Run Text="Password Length:"/> <Run Text="Password Length: "/>
<Run Text="{Binding PasswordLength}" />
</TextBlock> </TextBlock>
<Slider Value="{Binding PasswordLength, Mode=TwoWay}" Margin="0,-10,0,-20" /> <Slider Value="{Binding PasswordLength, Mode=TwoWay}" Margin="0,-10,0,-20" />
<CheckBox IsChecked="{Binding UpperCasePatternSelected, Mode=TwoWay}" Content="Upper case (A, B, C, ...)"/> <CheckBox IsChecked="{Binding UpperCasePatternSelected, Mode=TwoWay}" Content="Upper case (A, B, C, ...)"/>
@@ -346,9 +348,14 @@
<CheckBox IsChecked="{Binding SpacePatternSelected, Mode=TwoWay}" Content="Space ( )"/> <CheckBox IsChecked="{Binding SpacePatternSelected, Mode=TwoWay}" Content="Space ( )"/>
<CheckBox IsChecked="{Binding SpecialPatternSelected, Mode=TwoWay}" Content="Special (!, $, %, ...)"/> <CheckBox IsChecked="{Binding SpecialPatternSelected, Mode=TwoWay}" Content="Special (!, $, %, ...)"/>
<CheckBox IsChecked="{Binding BracketsPatternSelected, Mode=TwoWay}" Content="Brackets ([], {}, (), ...)"/> <CheckBox IsChecked="{Binding BracketsPatternSelected, Mode=TwoWay}" Content="Brackets ([], {}, (), ...)"/>
<Button Click="PasswordGenerationButton_Click" Content="Generate"/> <Button Content="Generate">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Click">
<core:CallMethodAction TargetObject="{Binding}" MethodName="GeneratePassword"/>
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</Button>
</StackPanel> </StackPanel>
</Flyout> </Flyout>
</Button.Flyout> </Button.Flyout>
</Button> </Button>
@@ -358,11 +365,32 @@
</Setter> </Setter>
</Style> </Style>
</Page.Resources> </Page.Resources>
<Page.DataContext> <Page.DataContext>
<viewModels:EntryVm/> <viewModels:EntryVm/>
</Page.DataContext> </Page.DataContext>
<Page.BottomAppBar>
<CommandBar x:Name="CommandBar" VerticalAlignment="Center">
<CommandBar.SecondaryCommands>
<AppBarButton Icon="Save" Label="Save">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Click">
<core:CallMethodAction TargetObject="{Binding}" MethodName="Save"/>
<core:ChangePropertyAction TargetObject="{Binding ElementName=CommandBar}" PropertyName="IsOpen" Value="False" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</AppBarButton>
<AppBarButton Icon="Setting" Label="Settings" />
</CommandBar.SecondaryCommands>
<AppBarToggleButton Icon="Edit" Label="Edit" IsChecked="{Binding IsEditMode, Mode=TwoWay}">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Click">
<core:ChangePropertyAction TargetObject="{Binding ElementName=CommandBar}" PropertyName="IsOpen" Value="False" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</AppBarToggleButton>
<AppBarButton Icon="Delete" Label="Delete" Click="DeleteButton_Click" />
</CommandBar>
</Page.BottomAppBar>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.ChildrenTransitions> <Grid.ChildrenTransitions>
<TransitionCollection> <TransitionCollection>
@@ -374,7 +402,7 @@
<RowDefinition Height="*"/> <RowDefinition Height="*"/>
</Grid.RowDefinitions> </Grid.RowDefinitions>
<StackPanel Grid.Row="1" Margin="20,0,0,0" > <StackPanel x:Name="stackPanel" Grid.Row="1" Margin="20,0,0,0" >
<StackPanel.Resources> <StackPanel.Resources>
<Style TargetType="TextBlock"> <Style TargetType="TextBlock">
<Setter Property="Margin" Value="0,20,0,0"/> <Setter Property="Margin" Value="0,20,0,0"/>
@@ -429,11 +457,13 @@
TextWrapping="NoWrap" TextWrapping="NoWrap"
VerticalAlignment="Center" VerticalAlignment="Center"
Margin="0,0,30,0" Margin="0,0,30,0"
PlaceholderText="New entry name..."/> PlaceholderText="New entry name...">
<CommandBar Grid.Column="2" Background="Transparent" IsOpen="True" VerticalAlignment="Center" Margin="0,20,0,0"> <interactivity:Interaction.Behaviors>
<AppBarToggleButton Icon="Edit" Label="Edit" IsChecked="{Binding IsEditMode, Mode=TwoWay}" /> <core:DataTriggerBehavior Binding="{Binding IsEditMode}" Value="True">
<AppBarButton Icon="Delete" Label="Delete" Click="AppBarButton_Click" /> <actions:SetupFocusAction TargetObject="{Binding ElementName=TitleTextBox}" />
</CommandBar> </core:DataTriggerBehavior>
</interactivity:Interaction.Behaviors>
</TextBox>
</Grid> </Grid>
</Grid> </Grid>
</Page> </Page>

View File

@@ -64,10 +64,6 @@ namespace ModernKeePass.Pages
navigationHelper.OnNavigatedTo(e); navigationHelper.OnNavigatedTo(e);
if (!(e.Parameter is EntryVm)) return; if (!(e.Parameter is EntryVm)) return;
DataContext = (EntryVm)e.Parameter; DataContext = (EntryVm)e.Parameter;
if (Model.IsEditMode)
Task.Factory.StartNew(
() => Dispatcher.RunAsync(CoreDispatcherPriority.Low,
() => TitleTextBox.Focus(FocusState.Programmatic)));
} }
protected override void OnNavigatedFrom(NavigationEventArgs e) protected override void OnNavigatedFrom(NavigationEventArgs e)
@@ -77,28 +73,9 @@ namespace ModernKeePass.Pages
#endregion #endregion
private async void AppBarButton_Click(object sender, RoutedEventArgs e) private void DeleteButton_Click(object sender, RoutedEventArgs e)
{ {
// Create the message dialog and set its content MessageDialogHelper.ShowDeleteConfirmationDialog("Are you sure you want to delete this entry?", Model, Frame);
var messageDialog = new MessageDialog("Are you sure you want to delete this entry?");
// Add commands and set their callbacks; both buttons use the same callback function instead of inline event handlers
messageDialog.Commands.Add(new UICommand("Delete", delete =>
{
ToastNotificationHelper.ShowUndoToast("Entry", Model);
Model.MarkForDelete();
if (Frame.CanGoBack) Frame.GoBack();
}));
messageDialog.Commands.Add(new UICommand("Cancel"));
// Set the command that will be invoked by default
messageDialog.DefaultCommandIndex = 1;
// Set the command to be invoked when escape is pressed
messageDialog.CancelCommandIndex = 1;
// Show the message dialog
await messageDialog.ShowAsync();
} }
private async void UrlButton_Click(object sender, RoutedEventArgs e) private async void UrlButton_Click(object sender, RoutedEventArgs e)
@@ -113,10 +90,5 @@ namespace ModernKeePass.Pages
// TODO: Show some error // TODO: Show some error
} }
} }
private void PasswordGenerationButton_Click(object sender, RoutedEventArgs e)
{
Model.GeneratePassword();
}
} }
} }

View File

@@ -8,6 +8,7 @@
xmlns:local="using:ModernKeePass.Controls" 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"
x:Name="PageRoot" x:Name="PageRoot"
x:Class="ModernKeePass.Pages.GroupDetailPage" x:Class="ModernKeePass.Pages.GroupDetailPage"
mc:Ignorable="d" > mc:Ignorable="d" >
@@ -21,15 +22,29 @@
<viewModels:GroupVm /> <viewModels:GroupVm />
</Page.DataContext> </Page.DataContext>
<Page.BottomAppBar> <Page.BottomAppBar>
<CommandBar VerticalAlignment="Center" > <CommandBar x:Name="CommandBar" VerticalAlignment="Center">
<AppBarToggleButton Icon="Edit" Label="Edit" IsChecked="{Binding IsEditMode, Mode=TwoWay}" Click="EditButton_Click" />
<AppBarButton Icon="Delete" Label="Delete" IsEnabled="{Binding IsNotRoot}" Click="DeleteButton_Click" />
<CommandBar.SecondaryCommands> <CommandBar.SecondaryCommands>
<AppBarButton Icon="Save" Label="Save">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Click">
<core:CallMethodAction TargetObject="{Binding}" MethodName="Save"/>
<core:ChangePropertyAction TargetObject="{Binding ElementName=CommandBar}" PropertyName="IsOpen" Value="False" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</AppBarButton>
<AppBarButton Icon="Setting" Label="Settings" /> <AppBarButton Icon="Setting" Label="Settings" />
</CommandBar.SecondaryCommands> </CommandBar.SecondaryCommands>
<AppBarToggleButton Icon="Edit" Label="Edit" IsChecked="{Binding IsEditMode, Mode=TwoWay}">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Click">
<core:ChangePropertyAction TargetObject="{Binding ElementName=CommandBar}" PropertyName="IsOpen" Value="False" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</AppBarToggleButton>
<AppBarButton Icon="Delete" Label="Delete" IsEnabled="{Binding IsNotRoot}" Click="DeleteButton_Click" />
</CommandBar> </CommandBar>
</Page.BottomAppBar> </Page.BottomAppBar>
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}"> <Grid>
<Grid.Resources> <Grid.Resources>
<CollectionViewSource <CollectionViewSource
x:Name="GroupsViewSource" x:Name="GroupsViewSource"
@@ -41,6 +56,9 @@
x:Name="EntriesZoomedOutViewSource" x:Name="EntriesZoomedOutViewSource"
Source="{Binding EntriesZoomedOut}" IsSourceGrouped="True"/> Source="{Binding EntriesZoomedOut}" IsSourceGrouped="True"/>
</Grid.Resources> </Grid.Resources>
<Grid.Background>
<StaticResource ResourceKey="ApplicationPageBackgroundThemeBrush"/>
</Grid.Background>
<Grid.ChildrenTransitions> <Grid.ChildrenTransitions>
<TransitionCollection> <TransitionCollection>
<EntranceThemeTransition/> <EntranceThemeTransition/>
@@ -61,6 +79,11 @@
IsSwipeEnabled="false" IsSwipeEnabled="false"
SelectionChanged="entries_SelectionChanged" SelectionChanged="entries_SelectionChanged"
IsSynchronizedWithCurrentItem="False"> IsSynchronizedWithCurrentItem="False">
<interactivity:Interaction.Behaviors>
<core:DataTriggerBehavior Binding="{Binding IsEditMode}" Value="False">
<actions:SetupFocusAction TargetObject="{Binding ElementName=GridView}" />
</core:DataTriggerBehavior>
</interactivity:Interaction.Behaviors>
<GridView.Resources> <GridView.Resources>
<DataTemplate x:Name="GroupFirstItem"> <DataTemplate x:Name="GroupFirstItem">
<Border <Border
@@ -147,7 +170,7 @@
<DataTemplate x:Name="Expanded"> <DataTemplate x:Name="Expanded">
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<SymbolIcon Symbol="{Binding IconSymbol}" /> <SymbolIcon Symbol="{Binding IconSymbol}" />
<TextBlock Text="{Binding Name}" FontWeight="{Binding FontWeight}" TextWrapping="NoWrap" VerticalAlignment="Center" Margin="30,0,20,0" FontStyle="{Binding Name, Converter={StaticResource TextToFontStyleConverter}, ConverterParameter=Recycle\ Bin}" /> <TextBlock Text="{Binding Name}" FontWeight="{Binding FontWeight}" TextWrapping="NoWrap" VerticalAlignment="Center" Margin="30,0,20,0" FontStyle="{Binding Name, ConverterParameter=Recycle Bin, Converter={StaticResource TextToFontStyleConverter}}" />
<!--<TextBlock Text="{Binding EntryCount}" HorizontalAlignment="Right" VerticalAlignment="Center" />--> <!--<TextBlock Text="{Binding EntryCount}" HorizontalAlignment="Right" VerticalAlignment="Center" />-->
</StackPanel> </StackPanel>
</DataTemplate> </DataTemplate>
@@ -164,17 +187,21 @@
</ListView.ItemContainerStyle> </ListView.ItemContainerStyle>
<ListView.HeaderTemplate> <ListView.HeaderTemplate>
<DataTemplate> <DataTemplate>
<ToggleButton IsChecked="{Binding IsLeftPaneOpen, Mode=TwoWay}" Style="{StaticResource HamburgerToggleButton}" Margin="0" /> <ToggleButton Style="{StaticResource HamburgerToggleButton}" Margin="0" >
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Loaded">
<core:ChangePropertyAction PropertyName="ItemTemplate" Value="{StaticResource Collapsed}" TargetObject="{Binding ElementName=LeftListView}"/>
</core:EventTriggerBehavior>
<core:EventTriggerBehavior EventName="Checked">
<core:ChangePropertyAction PropertyName="ItemTemplate" Value="{StaticResource Expanded}" TargetObject="{Binding ElementName=LeftListView}"/>
</core:EventTriggerBehavior>
<core:EventTriggerBehavior EventName="Unchecked">
<core:ChangePropertyAction PropertyName="ItemTemplate" Value="{StaticResource Collapsed}" TargetObject="{Binding ElementName=LeftListView}"/>
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</ToggleButton>
</DataTemplate> </DataTemplate>
</ListView.HeaderTemplate> </ListView.HeaderTemplate>
<interactivity:Interaction.Behaviors>
<core:DataTriggerBehavior Binding="{Binding IsLeftPaneOpen}" Value="True">
<core:ChangePropertyAction PropertyName="ItemTemplate" Value="{StaticResource Expanded}"/>
</core:DataTriggerBehavior>
<core:DataTriggerBehavior Binding="{Binding IsLeftPaneOpen}" Value="False">
<core:ChangePropertyAction PropertyName="ItemTemplate" Value="{StaticResource Collapsed}"/>
</core:DataTriggerBehavior>
</interactivity:Interaction.Behaviors>
</ListView> </ListView>
</GridView.Header> </GridView.Header>
</GridView> </GridView>
@@ -237,9 +264,15 @@
IsHitTestVisible="{Binding IsEditMode}" IsHitTestVisible="{Binding IsEditMode}"
TextWrapping="NoWrap" TextWrapping="NoWrap"
VerticalAlignment="Center" VerticalAlignment="Center"
Margin="0,0,30,0" Margin="0,0,30,5"
PlaceholderText="New group name..."/> PlaceholderText="New group name...">
<SearchBox Grid.Column="2" PlaceholderText="Search..." Width="350" Height="40" SuggestionsRequested="SearchBox_OnSuggestionsRequested" SearchHistoryEnabled="False" ResultSuggestionChosen="SearchBox_OnResultSuggestionChosen" /> <interactivity:Interaction.Behaviors>
<core:DataTriggerBehavior Binding="{Binding IsEditMode}" Value="True">
<actions:SetupFocusAction TargetObject="{Binding ElementName=TitleTextBox}" />
</core:DataTriggerBehavior>
</interactivity:Interaction.Behaviors>
</TextBox>
<SearchBox Grid.Column="2" PlaceholderText="Search..." Width="350" Height="40" FontSize="18" SuggestionsRequested="SearchBox_OnSuggestionsRequested" SearchHistoryEnabled="False" ResultSuggestionChosen="SearchBox_OnResultSuggestionChosen" />
</Grid> </Grid>
</Grid> </Grid>
</Page> </Page>

View File

@@ -8,6 +8,7 @@ using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation; using Windows.UI.Xaml.Navigation;
using ModernKeePass.Common; using ModernKeePass.Common;
using ModernKeePass.Events;
using ModernKeePass.ViewModels; using ModernKeePass.ViewModels;
// The Group Detail Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234229 // The Group Detail Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234229
@@ -62,12 +63,10 @@ namespace ModernKeePass.Pages
{ {
NavigationHelper.OnNavigatedTo(e); NavigationHelper.OnNavigatedTo(e);
if (!(e.Parameter is GroupVm)) return; if (e.Parameter is PasswordEventArgs)
DataContext = (GroupVm) e.Parameter; DataContext = ((PasswordEventArgs) e.Parameter).RootGroup;
if (Model.IsEditMode) else if (e.Parameter is GroupVm)
Task.Factory.StartNew( DataContext = (GroupVm) e.Parameter;
() => Dispatcher.RunAsync(CoreDispatcherPriority.Low,
() => TitleTextBox.Focus(FocusState.Programmatic)));
} }
protected override void OnNavigatedFrom(NavigationEventArgs e) protected override void OnNavigatedFrom(NavigationEventArgs e)
@@ -114,28 +113,9 @@ namespace ModernKeePass.Pages
Frame.Navigate(typeof(EntryDetailPage), entry); Frame.Navigate(typeof(EntryDetailPage), entry);
} }
private async void DeleteButton_Click(object sender, RoutedEventArgs e) private void DeleteButton_Click(object sender, RoutedEventArgs e)
{ {
// Create the message dialog and set its content MessageDialogHelper.ShowDeleteConfirmationDialog("Are you sure you want to delete the whole group and all its entries?", Model, Frame);
var messageDialog = new MessageDialog("Are you sure you want to delete the whole group and all its entries?");
// Add commands and set their callbacks; both buttons use the same callback function instead of inline event handlers
messageDialog.Commands.Add(new UICommand("Delete", delete =>
{
ToastNotificationHelper.ShowUndoToast("Group", Model);
Model.MarkForDelete();
if (Frame.CanGoBack) Frame.GoBack();
}));
messageDialog.Commands.Add(new UICommand("Cancel"));
// Set the command that will be invoked by default
messageDialog.DefaultCommandIndex = 1;
// Set the command to be invoked when escape is pressed
messageDialog.CancelCommandIndex = 1;
// Show the message dialog
await messageDialog.ShowAsync();
} }
private void SemanticZoom_ViewChangeStarted(object sender, SemanticZoomViewChangedEventArgs e) private void SemanticZoom_ViewChangeStarted(object sender, SemanticZoomViewChangedEventArgs e)
@@ -164,22 +144,5 @@ namespace ModernKeePass.Pages
} }
#endregion #endregion
private void EditButton_Click(object sender, RoutedEventArgs e)
{
BottomAppBar.IsOpen = false;
if (Model.IsEditMode)
{
Task.Factory.StartNew(
() => Dispatcher.RunAsync(CoreDispatcherPriority.Low,
() => TitleTextBox.Focus(FocusState.Programmatic)));
}
else
{
Task.Factory.StartNew(
() => Dispatcher.RunAsync(CoreDispatcherPriority.Low,
() => PageRoot.Focus(FocusState.Programmatic)));
}
}
} }
} }

View File

@@ -33,7 +33,7 @@
SelectedItem="{Binding SelectedItem, Mode=TwoWay}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
IsSynchronizedWithCurrentItem="False"> IsSynchronizedWithCurrentItem="False">
<ListView.Header> <ListView.Header>
<TextBlock Text="ModernKeePass" FontWeight="Bold" FontSize="36" Margin="20" /> <TextBlock Text="{Binding Name}" FontWeight="Bold" FontSize="36" Margin="20" />
</ListView.Header> </ListView.Header>
<ListView.ItemTemplate> <ListView.ItemTemplate>
<DataTemplate > <DataTemplate >

View File

@@ -7,6 +7,7 @@
xmlns:local="using:ModernKeePass.Controls" xmlns:local="using:ModernKeePass.Controls"
xmlns:converters="using:ModernKeePass.Converters" xmlns:converters="using:ModernKeePass.Converters"
xmlns:viewModels="using:ModernKeePass.ViewModels" xmlns:viewModels="using:ModernKeePass.ViewModels"
xmlns:interactivity="using:Microsoft.Xaml.Interactivity" xmlns:Core="using:Microsoft.Xaml.Interactions.Core"
mc:Ignorable="d"> mc:Ignorable="d">
<Page.Resources> <Page.Resources>
<converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/> <converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
@@ -21,12 +22,18 @@
<TextBlock Style="{StaticResource HeaderTextBlockStyle}" Margin="0,-20,0,20">New</TextBlock> <TextBlock Style="{StaticResource HeaderTextBlockStyle}" Margin="0,-20,0,20">New</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="350" Visibility="{Binding ShowPasswordBox, Converter={StaticResource BooleanToVisibilityConverter}}"> <Border HorizontalAlignment="Left" BorderThickness="1" BorderBrush="AliceBlue" Width="550" Visibility="{Binding ShowPasswordBox, Converter={StaticResource BooleanToVisibilityConverter}}">
<StackPanel> <StackPanel>
<TextBlock Margin="25,10,0,10" Text="{Binding Name}" /> <TextBlock Margin="25,10,0,10" Text="{Binding Name}" />
<local:OpenDatabaseUserControl Password="{Binding Password, Mode=TwoWay}" CreateNew="True" ValidationChecked="PasswordUserControl_PasswordChecked" /> <local:OpenDatabaseUserControl Password="{Binding Password, Mode=TwoWay}" CreateNew="True" >
<interactivity:Interaction.Behaviors>
<Core:EventTriggerBehavior EventName="ValidationChecked">
<Core:NavigateToPageAction TargetPage="ModernKeePass.Pages.GroupDetailPage" />
</Core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</local:OpenDatabaseUserControl>
<TextBlock Margin="25,0,0,10">Password complexity</TextBlock> <TextBlock Margin="25,0,0,10">Password complexity</TextBlock>
<ProgressBar Margin="25,0,0,10" Value="{Binding PasswordComplexityIndicator, ConverterParameter=0\,128, Converter={StaticResource ProgressBarLegalValuesConverter}}" Maximum="128" Width="300" HorizontalAlignment="Left" Foreground="{Binding PasswordComplexityIndicator, ConverterParameter=128, Converter={StaticResource DoubleToForegroungBrushComplexityConverter}}" /> <ProgressBar Margin="25,0,0,10" Value="{Binding PasswordComplexityIndicator, ConverterParameter=0\,128, Converter={StaticResource ProgressBarLegalValuesConverter}}" Maximum="128" Width="500" HorizontalAlignment="Left" Foreground="{Binding PasswordComplexityIndicator, ConverterParameter=128, Converter={StaticResource DoubleToForegroungBrushComplexityConverter}}" />
</StackPanel> </StackPanel>
</Border> </Border>
</StackPanel> </StackPanel>

View File

@@ -44,10 +44,5 @@ namespace ModernKeePass.Pages
if (file == null) return; if (file == null) return;
Model.OpenFile(file); Model.OpenFile(file);
} }
private void PasswordUserControl_PasswordChecked(object sender, PasswordEventArgs e)
{
_mainFrame.Navigate(typeof(GroupDetailPage), e.RootGroup);
}
} }
} }

View File

@@ -6,6 +6,7 @@
xmlns:viewModels="using:ModernKeePass.ViewModels" xmlns:viewModels="using:ModernKeePass.ViewModels"
xmlns:local="using:ModernKeePass.Controls" xmlns:local="using:ModernKeePass.Controls"
xmlns:converters="using:ModernKeePass.Converters" xmlns:converters="using:ModernKeePass.Converters"
xmlns:interactivity="using:Microsoft.Xaml.Interactivity" xmlns:Core="using:Microsoft.Xaml.Interactions.Core"
x:Class="ModernKeePass.Pages.OpenDatabasePage" x:Class="ModernKeePass.Pages.OpenDatabasePage"
mc:Ignorable="d"> mc:Ignorable="d">
<Page.Resources> <Page.Resources>
@@ -24,7 +25,13 @@
<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}}">
<StackPanel> <StackPanel>
<TextBlock Margin="25,10,0,10" Text="{Binding Name}" /> <TextBlock Margin="25,10,0,10" Text="{Binding Name}" />
<local:OpenDatabaseUserControl ValidationChecked="PasswordUserControl_PasswordChecked" /> <local:OpenDatabaseUserControl>
<interactivity:Interaction.Behaviors>
<Core:EventTriggerBehavior EventName="ValidationChecked">
<Core:NavigateToPageAction TargetPage="ModernKeePass.Pages.GroupDetailPage" />
</Core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</local:OpenDatabaseUserControl>
</StackPanel> </StackPanel>
</Border> </Border>
</StackPanel> </StackPanel>

View File

@@ -45,10 +45,5 @@ namespace ModernKeePass.Pages
if (file == null) return; if (file == null) return;
Model.OpenFile(file); Model.OpenFile(file);
} }
private void PasswordUserControl_PasswordChecked(object sender, PasswordEventArgs e)
{
_mainFrame.Navigate(typeof(GroupDetailPage), e.RootGroup);
}
} }
} }

View File

@@ -6,6 +6,7 @@
xmlns:viewModels="using:ModernKeePass.ViewModels" xmlns:viewModels="using:ModernKeePass.ViewModels"
xmlns:local="using:ModernKeePass.Controls" xmlns:local="using:ModernKeePass.Controls"
xmlns:converters="using:ModernKeePass.Converters" xmlns:converters="using:ModernKeePass.Converters"
xmlns:interactivity="using:Microsoft.Xaml.Interactivity" xmlns:Core="using:Microsoft.Xaml.Interactions.Core"
x:Class="ModernKeePass.Pages.RecentDatabasesPage" x:Class="ModernKeePass.Pages.RecentDatabasesPage"
mc:Ignorable="d"> mc:Ignorable="d">
<Page.Resources> <Page.Resources>
@@ -16,7 +17,9 @@
<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">Recent</TextBlock> <TextBlock Style="{StaticResource HeaderTextBlockStyle}" Margin="0,-20,0,20">
<Run Text="Recent"/>
</TextBlock>
<ListView <ListView
ItemsSource="{Binding Source={StaticResource RecentItemsSource}}" ItemsSource="{Binding Source={StaticResource RecentItemsSource}}"
SelectedItem="{Binding SelectedItem, Mode=TwoWay}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
@@ -26,7 +29,13 @@
<StackPanel Margin="10,0,10,0"> <StackPanel Margin="10,0,10,0">
<TextBlock Text="{Binding Name}" Padding="5,0,0,0" /> <TextBlock Text="{Binding Name}" Padding="5,0,0,0" />
<TextBlock Text="{Binding Path}" Padding="5,0,0,0" FontSize="10" /> <TextBlock Text="{Binding Path}" Padding="5,0,0,0" FontSize="10" />
<local:OpenDatabaseUserControl Margin="0,10,0,0" Visibility="{Binding IsSelected, Converter={StaticResource BooleanToVisibilityConverter}}" ValidationChecking="OpenDatabaseUserControl_OnValidationChecking" ValidationChecked="PasswordUserControl_PasswordChecked" /> <local:OpenDatabaseUserControl x:Name="DatabaseUserControl" Margin="0,10,0,0" Visibility="{Binding IsSelected, Converter={StaticResource BooleanToVisibilityConverter}}" ValidationChecking="OpenDatabaseUserControl_OnValidationChecking" >
<interactivity:Interaction.Behaviors>
<Core:EventTriggerBehavior EventName="ValidationChecked">
<Core:NavigateToPageAction TargetPage="ModernKeePass.Pages.GroupDetailPage" />
</Core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</local:OpenDatabaseUserControl>
</StackPanel> </StackPanel>
</DataTemplate> </DataTemplate>
</ListView.ItemTemplate> </ListView.ItemTemplate>

View File

@@ -2,7 +2,6 @@
using Windows.UI.Xaml; using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation; using Windows.UI.Xaml.Navigation;
using ModernKeePass.Events;
using ModernKeePass.ViewModels; using ModernKeePass.ViewModels;
// Pour en savoir plus sur le modèle d'élément Page vierge, consultez la page http://go.microsoft.com/fwlink/?LinkId=234238 // Pour en savoir plus sur le modèle d'élément Page vierge, consultez la page http://go.microsoft.com/fwlink/?LinkId=234238
@@ -29,11 +28,6 @@ namespace ModernKeePass.Pages
_mainFrame = e.Parameter as Frame; _mainFrame = e.Parameter as Frame;
} }
private void PasswordUserControl_PasswordChecked(object sender, PasswordEventArgs e)
{
_mainFrame.Navigate(typeof(GroupDetailPage), e.RootGroup);
}
private void OpenDatabaseUserControl_OnValidationChecking(object sender, EventArgs e) private void OpenDatabaseUserControl_OnValidationChecking(object sender, EventArgs e)
{ {
var app = (App)Application.Current; var app = (App)Application.Current;

View File

@@ -4,6 +4,8 @@ namespace ModernKeePass.ViewModels
{ {
public class AboutVm public class AboutVm
{ {
public string Name { get; } = Package.Current.DisplayName;
public string Version public string Version
{ {
get get
@@ -11,7 +13,7 @@ namespace ModernKeePass.ViewModels
var package = Package.Current; var package = Package.Current;
var version = package.Id.Version; var version = package.Id.Version;
return $"{package.DisplayName} version {version.Major}.{version.Minor}"; return $"{version.Major}.{version.Minor}";
} }
} }
} }

View File

@@ -195,5 +195,10 @@ namespace ModernKeePass.ViewModels
ParentGroup.Entries.Add(this); ParentGroup.Entries.Add(this);
} }
public void Save()
{
var app = (App)Application.Current;
app.Database.Save();
}
} }
} }

View File

@@ -52,12 +52,6 @@ namespace ModernKeePass.ViewModels
} }
} }
public bool IsLeftPaneOpen
{
get { return _isLeftPaneOpen; }
set { SetProperty(ref _isLeftPaneOpen, value); }
}
public bool IsEditMode public bool IsEditMode
{ {
get { return _isEditMode; } get { return _isEditMode; }
@@ -113,5 +107,11 @@ namespace ModernKeePass.ViewModels
{ {
ParentGroup.Groups.Add(this); ParentGroup.Groups.Add(this);
} }
public void Save()
{
var app = (App)Application.Current;
app.Database.Save();
}
} }
} }

View File

@@ -1,5 +1,6 @@
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using Windows.ApplicationModel;
using Windows.Storage.AccessCache; using Windows.Storage.AccessCache;
using Windows.UI.Xaml; using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls;
@@ -13,6 +14,8 @@ namespace ModernKeePass.ViewModels
private IOrderedEnumerable<IGrouping<int, MainMenuItemVm>> _mainMenuItems; private IOrderedEnumerable<IGrouping<int, MainMenuItemVm>> _mainMenuItems;
private MainMenuItemVm _selectedItem; private MainMenuItemVm _selectedItem;
public string Name { get; } = Package.Current.DisplayName;
public IOrderedEnumerable<IGrouping<int, MainMenuItemVm>> MainMenuItems public IOrderedEnumerable<IGrouping<int, MainMenuItemVm>> MainMenuItems
{ {
get { return _mainMenuItems; } get { return _mainMenuItems; }

View File

@@ -36,6 +36,7 @@ namespace ModernKeePass.ViewModels
public RecentVm() public RecentVm()
{ {
// TODO: opening the files actually changes the MRU order
var mru = StorageApplicationPermissions.MostRecentlyUsedList; var mru = StorageApplicationPermissions.MostRecentlyUsedList;
foreach (var entry in mru.Entries) foreach (var entry in mru.Entries)
{ {