diff --git a/ModernKeePass.Application/Database/Commands/CreateDatabase/CreateDatabaseCommand.cs b/ModernKeePass.Application/Database/Commands/CreateDatabase/CreateDatabaseCommand.cs index d239405..b74e42d 100644 --- a/ModernKeePass.Application/Database/Commands/CreateDatabase/CreateDatabaseCommand.cs +++ b/ModernKeePass.Application/Database/Commands/CreateDatabase/CreateDatabaseCommand.cs @@ -51,9 +51,17 @@ namespace ModernKeePass.Application.Database.Commands.CreateDatabase if (message.CreateSampleData) { - _database.CreateGroup(_database.RootGroupId, "Banking"); - _database.CreateGroup(_database.RootGroupId, "Email"); - _database.CreateGroup(_database.RootGroupId, "Internet"); + var bankingGroup = _database.CreateGroup(_database.RootGroupId, "Banking"); + bankingGroup.Icon = Icon.Shop; + _database.UpdateGroup(bankingGroup); + + var emailGroup = _database.CreateGroup(_database.RootGroupId, "Email"); + emailGroup.Icon = Icon.Mail; + _database.UpdateGroup(emailGroup); + + var internetGroup = _database.CreateGroup(_database.RootGroupId, "Internet"); + internetGroup.Icon = Icon.World; + _database.UpdateGroup(internetGroup); var sample1 = _database.CreateEntry(_database.RootGroupId); _database.UpdateEntry(sample1.Id, EntryFieldName.Title, "Sample Entry" ); diff --git a/ModernKeePass.Application/Group/Queries/GetAllGroups/GetAllGroupsQuery.cs b/ModernKeePass.Application/Group/Queries/GetAllGroups/GetAllGroupsQuery.cs index 35ca640..c4b4ea8 100644 --- a/ModernKeePass.Application/Group/Queries/GetAllGroups/GetAllGroupsQuery.cs +++ b/ModernKeePass.Application/Group/Queries/GetAllGroups/GetAllGroupsQuery.cs @@ -26,7 +26,9 @@ namespace ModernKeePass.Application.Group.Queries.GetAllGroups public IEnumerable Handle(GetAllGroupsQuery message) { if (!_database.IsOpen) throw new DatabaseClosedException(); - return _database.GetAllGroups(message.GroupId).Select(g => _mapper.Map(g)); + var groups = new List {_mapper.Map(_database.GetGroup(message.GroupId))}; + groups.AddRange(_database.GetAllGroups(message.GroupId).Select(g => _mapper.Map(g))); + return groups; } } } diff --git a/ModernKeePass.Infrastructure/UWP/UwpSettingsClient.cs b/ModernKeePass.Infrastructure/UWP/UwpSettingsClient.cs index 48520f2..b016dac 100644 --- a/ModernKeePass.Infrastructure/UWP/UwpSettingsClient.cs +++ b/ModernKeePass.Infrastructure/UWP/UwpSettingsClient.cs @@ -13,7 +13,8 @@ namespace ModernKeePass.Infrastructure.UWP { try { - return (T)Convert.ChangeType(_values[property], typeof(T)); + var value = (T)Convert.ChangeType(_values[property], typeof(T)); + return value == null ? defaultValue : value; } catch (InvalidCastException) { diff --git a/ModernKeePass/ResourceDictionaries/Styles.xaml b/ModernKeePass/ResourceDictionaries/Styles.xaml index 785953c..9ec5fd1 100644 --- a/ModernKeePass/ResourceDictionaries/Styles.xaml +++ b/ModernKeePass/ResourceDictionaries/Styles.xaml @@ -51,7 +51,7 @@ - + diff --git a/ModernKeePass/ViewModels/EntryDetailVm.cs b/ModernKeePass/ViewModels/EntryDetailVm.cs index f773fdf..6664dca 100644 --- a/ModernKeePass/ViewModels/EntryDetailVm.cs +++ b/ModernKeePass/ViewModels/EntryDetailVm.cs @@ -107,7 +107,12 @@ namespace ModernKeePass.ViewModels public string UserName { get { return SelectedItem.Username; } - set { SelectedItem.Username = value; } + set + { + SelectedItem.Username = value; + SetFieldValue(nameof(UserName), value).Wait(); + RaisePropertyChanged(nameof(UserName)); + } } public string Password @@ -129,6 +134,7 @@ namespace ModernKeePass.ViewModels { SelectedItem.Url = value; SetFieldValue(nameof(Url), value).Wait(); + RaisePropertyChanged(nameof(Url)); } } @@ -253,7 +259,7 @@ namespace ModernKeePass.ViewModels SaveCommand = new RelayCommand(async () => await SaveChanges(), () => Database.IsDirty); GeneratePasswordCommand = new RelayCommand(async () => await GeneratePassword()); - MoveCommand = new RelayCommand(async destination => await Move(destination), destination => _parent != null && string.IsNullOrEmpty(destination) && destination != _parent.Id); + MoveCommand = new RelayCommand(async destination => await Move(destination), destination => _parent != null && !string.IsNullOrEmpty(destination) && destination != _parent.Id); RestoreCommand = new RelayCommand(async () => await RestoreHistory()); DeleteCommand = new RelayCommand(async () => await AskForDelete()); GoBackCommand = new RelayCommand(() => _navigation.GoBack()); diff --git a/ModernKeePass/Views/MainPageFrames/NewDatabasePage.xaml.cs b/ModernKeePass/Views/MainPageFrames/NewDatabasePage.xaml.cs index 0dd56c1..ca190f0 100644 --- a/ModernKeePass/Views/MainPageFrames/NewDatabasePage.xaml.cs +++ b/ModernKeePass/Views/MainPageFrames/NewDatabasePage.xaml.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using Windows.Storage.AccessCache; using Windows.Storage.Pickers; using Windows.UI.Xaml; -using ModernKeePass.Domain.Dtos; using ModernKeePass.ViewModels; // The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238 @@ -29,19 +28,14 @@ namespace ModernKeePass.Views SuggestedStartLocation = PickerLocationId.DocumentsLibrary, SuggestedFileName = "New Database" }; - savePicker.FileTypeChoices.Add("KeePass 2.x database", new List { ".kdbx" }); + savePicker.FileTypeChoices.Add("KeePass 2.x database", new List {".kdbx"}); var file = await savePicker.PickSaveFileAsync().AsTask(); if (file == null) return; - var token = StorageApplicationPermissions.FutureAccessList.Add(file, file.Name); - var fileInfo = new FileInfo - { - Id = token, - Path = file.Path, - Name = file.DisplayName - }; - Model.OpenFile(fileInfo); + Model.Token = StorageApplicationPermissions.FutureAccessList.Add(file, file.Name); + Model.Name = file.Name; + Model.Path = file.Path; } } } diff --git a/ModernKeePass/Views/MainPageFrames/OpenDatabasePage.xaml.cs b/ModernKeePass/Views/MainPageFrames/OpenDatabasePage.xaml.cs index 8e0ac14..292fea9 100644 --- a/ModernKeePass/Views/MainPageFrames/OpenDatabasePage.xaml.cs +++ b/ModernKeePass/Views/MainPageFrames/OpenDatabasePage.xaml.cs @@ -28,7 +28,9 @@ namespace ModernKeePass.Views var file = e.Parameter as FileInfo; if (file != null) { - Model.OpenFile(file); + Model.Path = file.Path; + Model.Name = file.Name; + Model.Token = file.Id; } } @@ -46,14 +48,9 @@ namespace ModernKeePass.Views if (file == null) return; // TODO: use service - var token = StorageApplicationPermissions.MostRecentlyUsedList.Add(file, file.Path); - var fileInfo = new FileInfo - { - Path = file.Path, - Name = file.DisplayName, - Id = token - }; - Model.OpenFile(fileInfo); + Model.Token = StorageApplicationPermissions.MostRecentlyUsedList.Add(file, file.Path); + Model.Path = file.Path; + Model.Name = file.Name; } } } diff --git a/ModernKeePass/Views/UserControls/SetCredentialsUserControl.xaml b/ModernKeePass/Views/UserControls/SetCredentialsUserControl.xaml index 6baa12e..f62a72b 100644 --- a/ModernKeePass/Views/UserControls/SetCredentialsUserControl.xaml +++ b/ModernKeePass/Views/UserControls/SetCredentialsUserControl.xaml @@ -117,19 +117,6 @@ - - - - - - - - - - - - - @@ -145,9 +132,6 @@ - - - diff --git a/ModernKeePass/Views/UserControls/SetCredentialsUserControl.xaml.cs b/ModernKeePass/Views/UserControls/SetCredentialsUserControl.xaml.cs index f8367b3..c28fe47 100644 --- a/ModernKeePass/Views/UserControls/SetCredentialsUserControl.xaml.cs +++ b/ModernKeePass/Views/UserControls/SetCredentialsUserControl.xaml.cs @@ -44,9 +44,8 @@ namespace ModernKeePass.Views.UserControls var file = await picker.PickSingleFileAsync(); if (file == null) return; - var token = StorageApplicationPermissions.FutureAccessList.Add(file, file.Name); - Model.KeyFilePath = token; - Model.KeyFileText = file.DisplayName; + Model.KeyFilePath = StorageApplicationPermissions.FutureAccessList.Add(file, file.Name); + Model.KeyFileText = file.Name; } private async void CreateKeyFileButton_Click(object sender, RoutedEventArgs e) @@ -61,9 +60,8 @@ namespace ModernKeePass.Views.UserControls var file = await savePicker.PickSaveFileAsync(); if (file == null) return; - var token = StorageApplicationPermissions.FutureAccessList.Add(file, file.Name); - Model.KeyFilePath = token; - Model.KeyFileText = file.DisplayName; + Model.KeyFilePath = StorageApplicationPermissions.FutureAccessList.Add(file, file.Name); + Model.KeyFileText = file.Name; await Model.GenerateKeyFile(); } } diff --git a/ModernKeePass/Views/UserControls/TopMenuUserControl.xaml.cs b/ModernKeePass/Views/UserControls/TopMenuUserControl.xaml.cs index 30a2c55..3046d43 100644 --- a/ModernKeePass/Views/UserControls/TopMenuUserControl.xaml.cs +++ b/ModernKeePass/Views/UserControls/TopMenuUserControl.xaml.cs @@ -202,7 +202,7 @@ namespace ModernKeePass.Views.UserControls { args.Request.SearchSuggestionCollection.AppendResultSuggestion( group.Title, - group.ParentGroupName, + group.ParentGroupName ?? string.Empty, group.Id, imageUri, string.Empty); diff --git a/WinAppCommon/Converters/EmptyStringToVisibilityConverter.cs b/WinAppCommon/Converters/EmptyStringToVisibilityConverter.cs index dc73ae4..8f59085 100644 --- a/WinAppCommon/Converters/EmptyStringToVisibilityConverter.cs +++ b/WinAppCommon/Converters/EmptyStringToVisibilityConverter.cs @@ -4,7 +4,7 @@ using Windows.UI.Xaml.Data; namespace ModernKeePass.Converters { - class EmptyStringToVisibilityConverter: IValueConverter + public class EmptyStringToVisibilityConverter: IValueConverter { public object Convert(object value, Type targetType, object parameter, string language) { diff --git a/WinAppCommon/ViewModels/Items/SettingsNewVm.cs b/WinAppCommon/ViewModels/Items/SettingsNewVm.cs index 225268b..a3b5f73 100644 --- a/WinAppCommon/ViewModels/Items/SettingsNewVm.cs +++ b/WinAppCommon/ViewModels/Items/SettingsNewVm.cs @@ -16,7 +16,7 @@ namespace ModernKeePass.ViewModels.ListItems public bool IsCreateSample { - get { return _settings.GetSetting(Constants.Settings.Sample); } + get { return _settings.GetSetting(Constants.Settings.Sample, true); } set { _settings.PutSetting(Constants.Settings.Sample, value); } } @@ -38,7 +38,7 @@ namespace ModernKeePass.ViewModels.ListItems { get { - var version = _settings.GetSetting(Constants.Settings.DefaultFileFormat); + var version = _settings.GetSetting(Constants.Settings.DefaultFileFormat, "4"); return FileFormats.FirstOrDefault(f => f.Version == version); } set { _settings.PutSetting(Constants.Settings.DefaultFileFormat, value.Version); } diff --git a/WinAppCommon/ViewModels/NewVm.cs b/WinAppCommon/ViewModels/NewVm.cs index d97fd00..88be541 100644 --- a/WinAppCommon/ViewModels/NewVm.cs +++ b/WinAppCommon/ViewModels/NewVm.cs @@ -45,7 +45,7 @@ namespace ModernKeePass.ViewModels Password = message.Password, Name = "ModernKeePass", Version = _settings.GetSetting(Constants.Settings.DefaultFileFormat, "4"), - CreateSampleData = _settings.GetSetting(Constants.Settings.Sample) + CreateSampleData = _settings.GetSetting(Constants.Settings.Sample, true) }); var database = await _mediator.Send(new GetDatabaseQuery()); diff --git a/WinAppCommon/ViewModels/OpenVm.cs b/WinAppCommon/ViewModels/OpenVm.cs index 57674cb..216ef1d 100644 --- a/WinAppCommon/ViewModels/OpenVm.cs +++ b/WinAppCommon/ViewModels/OpenVm.cs @@ -1,5 +1,4 @@ using GalaSoft.MvvmLight; -using ModernKeePass.Domain.Dtos; namespace ModernKeePass.ViewModels { @@ -8,32 +7,28 @@ namespace ModernKeePass.ViewModels private string _name; private string _path; private string _token; - public bool IsFileSelected => !string.IsNullOrEmpty(Path); + public bool IsFileSelected => !string.IsNullOrEmpty(Token); public string Token { get { return _token; } - set { Set(() => Token, ref _token, value); } + set + { + Set(() => Token, ref _token, value); + RaisePropertyChanged(nameof(IsFileSelected)); + } } public string Name { get { return _name; } - private set { Set(() => Name, ref _name, value); } + set { Set(() => Name, ref _name, value); } } public string Path { get { return _path; } - private set { Set(() => Path, ref _path, value); } - } - - public void OpenFile(FileInfo file) - { - Token = file.Id; - Name = file.Name; - Path = file.Path; - RaisePropertyChanged(nameof(IsFileSelected)); + set { Set(() => Path, ref _path, value); } } } } diff --git a/WinAppCommon/ViewModels/UserControls/BreadcrumbVm.cs b/WinAppCommon/ViewModels/UserControls/BreadcrumbVm.cs deleted file mode 100644 index dc53cf2..0000000 --- a/WinAppCommon/ViewModels/UserControls/BreadcrumbVm.cs +++ /dev/null @@ -1,19 +0,0 @@ -using GalaSoft.MvvmLight.Command; -using GalaSoft.MvvmLight.Views; -using ModernKeePass.Common; -using ModernKeePass.Models; - -namespace ModernKeePass.ViewModels -{ - public class BreadcrumbVm - { - public RelayCommand NavigateCommand { get; } - - public BreadcrumbVm(INavigationService navigation) - { - NavigateCommand = new RelayCommand(groupId => - navigation.NavigateTo(Constants.Navigation.GroupPage, new NavigationItem {Id = groupId}), - groupId => !string.IsNullOrEmpty(groupId)); - } - } -} \ No newline at end of file diff --git a/WinAppCommon/ViewModels/UserControls/CredentialsViewModel.cs b/WinAppCommon/ViewModels/UserControls/CredentialsViewModel.cs deleted file mode 100644 index c0cd1aa..0000000 --- a/WinAppCommon/ViewModels/UserControls/CredentialsViewModel.cs +++ /dev/null @@ -1,175 +0,0 @@ -using System; -using System.Text; -using System.Threading.Tasks; -using MediatR; -using Microsoft.Extensions.DependencyInjection; -using ModernKeePass.Application.Common.Interfaces; -using ModernKeePass.Application.Database.Commands.CreateDatabase; -using ModernKeePass.Application.Database.Commands.UpdateCredentials; -using ModernKeePass.Application.Database.Queries.GetDatabase; -using ModernKeePass.Application.Database.Queries.OpenDatabase; -using ModernKeePass.Application.Security.Commands.GenerateKeyFile; -using ModernKeePass.Application.Security.Queries.EstimatePasswordComplexity; -using ModernKeePass.Domain.AOP; -using ModernKeePass.Domain.Dtos; - -namespace ModernKeePass.ViewModels -{ - public class CompositeKeyVm : NotifyPropertyChangedBase - { - public enum StatusTypes - { - Normal = 0, - Error = 1, - Warning = 3, - Success = 5 - } - - public bool HasPassword - { - get { return _hasPassword; } - set - { - SetProperty(ref _hasPassword, value); - OnPropertyChanged(nameof(IsValid)); - } - } - - public bool HasKeyFile - { - get { return _hasKeyFile; } - set - { - SetProperty(ref _hasKeyFile, value); - OnPropertyChanged(nameof(IsValid)); - } - } - - public bool IsValid => !_isOpening && (HasPassword || HasKeyFile && KeyFilePath != null); - - public string Status - { - get { return _status; } - set { SetProperty(ref _status, value); } - } - - public int StatusType - { - get { return (int)_statusType; } - set { SetProperty(ref _statusType, (StatusTypes)value); } - } - - public string Password - { - get { return _password; } - set - { - _password = value; - OnPropertyChanged(nameof(PasswordComplexityIndicator)); - StatusType = (int)StatusTypes.Normal; - Status = string.Empty; - } - } - - public string KeyFilePath - { - get { return _keyFilePath; } - set - { - _keyFilePath = value; - OnPropertyChanged(nameof(IsValid)); - } - } - - public string KeyFileText - { - get { return _keyFileText; } - set { SetProperty(ref _keyFileText, value); } - } - - public string RootGroupId { get; set; } - - public double PasswordComplexityIndicator => _mediator.Send(new EstimatePasswordComplexityQuery { Password = Password }).GetAwaiter().GetResult(); - - private bool _hasPassword; - private bool _hasKeyFile; - private bool _isOpening; - private string _password = string.Empty; - private string _status; - private StatusTypes _statusType; - private string _keyFilePath; - private string _keyFileText; - private readonly IMediator _mediator; - private readonly ISettingsProxy _settings; - private readonly IResourceProxy _resource; - - public CompositeKeyVm() : this( - App.Services.GetRequiredService(), - App.Services.GetRequiredService(), - App.Services.GetRequiredService()) - { } - - public CompositeKeyVm(IMediator mediator, ISettingsProxy settings, IResourceProxy resource) - { - _mediator = mediator; - _settings = settings; - _resource = resource; - _keyFileText = _resource.GetResourceValue("CompositeKeyDefaultKeyFile"); - } - - public async Task OpenDatabase(string databaseFilePath, bool createNew) - { - try - { - _isOpening = true; - OnPropertyChanged(nameof(IsValid)); - if (createNew) - { - await _mediator.Send(new CreateDatabaseCommand - { - FilePath = databaseFilePath, - KeyFilePath = HasKeyFile ? KeyFilePath : null, - Password = HasPassword ? Password : null, - Name = "New Database", - CreateSampleData = _settings.GetSetting("Sample") - }); - } - else - { - await _mediator.Send(new OpenDatabaseQuery - { - FilePath = databaseFilePath, - KeyFilePath = HasKeyFile ? KeyFilePath : null, - Password = HasPassword ? Password : null, - }); - } - RootGroupId = (await _mediator.Send(new GetDatabaseQuery())).RootGroupId; - return true; - } - catch (ArgumentException) - { - var errorMessage = new StringBuilder($"{_resource.GetResourceValue("CompositeKeyErrorOpen")}\n"); - if (HasPassword) errorMessage.AppendLine(_resource.GetResourceValue("CompositeKeyErrorUserPassword")); - if (HasKeyFile) errorMessage.AppendLine(_resource.GetResourceValue("CompositeKeyErrorUserKeyFile")); - UpdateStatus(errorMessage.ToString(), StatusTypes.Error); - } - catch (Exception e) - { - var error = $"{_resource.GetResourceValue("CompositeKeyErrorOpen")}{e.Message}"; - UpdateStatus(error, StatusTypes.Error); - } - finally - { - _isOpening = false; - OnPropertyChanged(nameof(IsValid)); - } - return false; - } - - private void UpdateStatus(string text, StatusTypes type) - { - Status = text; - StatusType = (int)type; - } - } -} diff --git a/WinAppCommon/ViewModels/UserControls/SetCredentialsViewModel.cs b/WinAppCommon/ViewModels/UserControls/SetCredentialsViewModel.cs deleted file mode 100644 index 8902f46..0000000 --- a/WinAppCommon/ViewModels/UserControls/SetCredentialsViewModel.cs +++ /dev/null @@ -1,137 +0,0 @@ -using System.Threading.Tasks; -using GalaSoft.MvvmLight; -using GalaSoft.MvvmLight.Command; -using GalaSoft.MvvmLight.Messaging; -using MediatR; -using Messages; -using Microsoft.Extensions.DependencyInjection; -using ModernKeePass.Application.Common.Interfaces; -using ModernKeePass.Application.Security.Commands.GenerateKeyFile; - -namespace ModernKeePass.ViewModels -{ - public class SetCredentialsViewModel : ObservableObject - { - private readonly IMediator _mediator; - private readonly ICredentialsProxy _credentials; - private readonly IMessenger _messenger; - - public bool HasPassword - { - get { return _hasPassword; } - set - { - Set(() => HasPassword, ref _hasPassword, value); - RaisePropertyChanged(nameof(IsValid)); - GenerateCredentialsCommand.RaiseCanExecuteChanged(); - } - } - - public bool HasKeyFile - { - get { return _hasKeyFile; } - set - { - Set(() => HasKeyFile, ref _hasKeyFile, value); - RaisePropertyChanged(nameof(IsValid)); - GenerateCredentialsCommand.RaiseCanExecuteChanged(); - } - } - - public string Status - { - get { return _status; } - set { Set(() => Status, ref _status, value); } - } - - public string Password - { - get { return _password; } - set - { - _password = value; - RaisePropertyChanged(nameof(IsValid)); - RaisePropertyChanged(nameof(PasswordComplexityIndicator)); - GenerateCredentialsCommand.RaiseCanExecuteChanged(); - } - } - public string ConfirmPassword - { - get { return _confirmPassword; } - set - { - _confirmPassword = value; - RaisePropertyChanged(nameof(IsValid)); - GenerateCredentialsCommand.RaiseCanExecuteChanged(); - } - } - - public string KeyFilePath - { - get { return _keyFilePath; } - set - { - _keyFilePath = value; - RaisePropertyChanged(nameof(IsValid)); - GenerateCredentialsCommand.RaiseCanExecuteChanged(); - } - } - - public string KeyFileText - { - get { return _keyFileText; } - set { Set(() => KeyFileText, ref _keyFileText, value); } - } - - public string OpenButtonLabel - { - get { return _openButtonLabel; } - set { Set(() => OpenButtonLabel, ref _openButtonLabel, value); } - } - - public double PasswordComplexityIndicator => _credentials.EstimatePasswordComplexity(Password); - - public bool IsValid => HasPassword && Password == ConfirmPassword || HasKeyFile && !string.IsNullOrEmpty(KeyFilePath); - - public RelayCommand GenerateCredentialsCommand{ get; } - - private bool _hasPassword; - private bool _hasKeyFile; - private string _password = string.Empty; - private string _confirmPassword; - private string _status; - private string _keyFilePath; - private string _keyFileText; - private string _openButtonLabel; - - public SetCredentialsViewModel(): this( - App.Services.GetRequiredService(), - App.Services.GetRequiredService(), - App.Services.GetRequiredService(), - App.Services.GetRequiredService()) { } - - public SetCredentialsViewModel(IMediator mediator, ICredentialsProxy credentials, IMessenger messenger, IResourceProxy resource) - { - _mediator = mediator; - _credentials = credentials; - _messenger = messenger; - GenerateCredentialsCommand = new RelayCommand(GenerateCredentials, () => IsValid); - - _keyFileText = resource.GetResourceValue("CompositeKeyDefaultKeyFile"); - } - - public async Task GenerateKeyFile() - { - await _mediator.Send(new GenerateKeyFileCommand {KeyFilePath = KeyFilePath}); - } - - private void GenerateCredentials() - { - _messenger.Send(new CredentialsSetMessage - { - Password = HasPassword ? Password : null, - KeyFilePath = HasKeyFile ? KeyFilePath : null - }); - } - } -} \ No newline at end of file diff --git a/WinAppCommon/ViewModels/UserControls/SetCredentialsVm.cs b/WinAppCommon/ViewModels/UserControls/SetCredentialsVm.cs index 1184607..b469fa5 100644 --- a/WinAppCommon/ViewModels/UserControls/SetCredentialsVm.cs +++ b/WinAppCommon/ViewModels/UserControls/SetCredentialsVm.cs @@ -83,7 +83,7 @@ namespace ModernKeePass.ViewModels public bool IsPasswordValid => HasPassword && Password == ConfirmPassword || !HasPassword; public bool IsKeyFileValid => HasKeyFile && !string.IsNullOrEmpty(KeyFilePath) || !HasKeyFile; - public bool IsValid => (IsPasswordValid || IsKeyFileValid) && (HasPassword || HasKeyFile); + public bool IsValid => HasPassword && Password == ConfirmPassword || HasKeyFile && !string.IsNullOrEmpty(KeyFilePath) && (HasPassword || HasKeyFile); public RelayCommand GenerateCredentialsCommand{ get; }