Additional fields Add, Update and Delete work (too well)

SelectableListView works when programmatically setting selection
This commit is contained in:
Geoffroy BONNEVILLE
2020-05-11 10:53:14 +02:00
parent 71b6009a29
commit bb2b99ed66
20 changed files with 274 additions and 101 deletions

View File

@@ -91,6 +91,7 @@
<Compile Include="Entry\Commands\AddAttachment\AddAttachmentCommand.cs" />
<Compile Include="Entry\Commands\AddHistory\AddHistoryCommand.cs" />
<Compile Include="Entry\Commands\DeleteAttachment\DeleteAttachmentCommand.cs" />
<Compile Include="Entry\Commands\DeleteField\DeleteFieldCommand.cs" />
<Compile Include="Entry\Commands\DeleteHistory\DeleteHistoryCommand.cs" />
<Compile Include="Entry\Commands\RestoreHistory\RestoreHistoryCommand.cs" />
<Compile Include="Entry\Queries\GetEntry\GetEntryQuery.cs" />
@@ -121,8 +122,8 @@
<Compile Include="Database\Queries\OpenDatabase\OpenDatabaseQueryValidator.cs" />
<Compile Include="Database\Queries\ReOpenDatabase\ReOpenDatabaseQuery.cs" />
<Compile Include="DependencyInjection.cs" />
<Compile Include="Entry\Commands\SetFieldValue\SetFieldValueCommand.cs" />
<Compile Include="Entry\Commands\SetFieldValue\SetFieldValueCommandValidator.cs" />
<Compile Include="Entry\Commands\UpsertField\UpsertFieldCommand.cs" />
<Compile Include="Entry\Commands\UpsertField\UpsertFieldCommandValidator.cs" />
<Compile Include="Entry\Models\EntryVm.cs" />
<Compile Include="Group\Commands\AddEntry\AddEntryCommand.cs" />
<Compile Include="Group\Commands\AddGroup\AddGroupCommand.cs" />

View File

@@ -31,19 +31,22 @@ namespace ModernKeePass.Application.Common.Interfaces
void CloseDatabase();
EntryEntity GetEntry(string id);
GroupEntity GetGroup(string id);
Task AddEntry(string parentGroupId, string entryId);
Task MoveEntry(string parentGroupId, string entryId, int index);
Task AddGroup(string parentGroupId, string groupId);
void UpdateEntry(string entryId, string fieldName, object fieldValue);
void UpdateGroup(GroupEntity group);
void DeleteField(string entryId, string fieldName);
Task RemoveEntry(string parentGroupId, string entryId);
EntryEntity CreateEntry(string parentGroupId);
void SortEntries(string groupId);
GroupEntity GetGroup(string id);
Task AddGroup(string parentGroupId, string groupId);
void UpdateGroup(GroupEntity group);
Task RemoveGroup(string parentGroupId, string groupId);
void DeleteEntity(string entityId);
EntryEntity CreateEntry(string parentGroupId);
GroupEntity CreateGroup(string parentGroupId, string name, bool isRecycleBin = false);
void SortEntries(string groupId);
void SortSubGroups(string groupId);
void AddAttachment(string entryId, string attachmentName, byte[] attachmentContent);
void DeleteAttachment(string entryId, string attachmentName);

View File

@@ -0,0 +1,29 @@
using MediatR;
using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Domain.Exceptions;
namespace ModernKeePass.Application.Entry.Commands.DeleteField
{
public class DeleteFieldCommand: IRequest
{
public string EntryId { get; set; }
public string FieldName { get; set; }
public class DeleteFieldCommandHandler : IRequestHandler<DeleteFieldCommand>
{
private readonly IDatabaseProxy _database;
public DeleteFieldCommandHandler(IDatabaseProxy database)
{
_database = database;
}
public void Handle(DeleteFieldCommand message)
{
if (!_database.IsOpen) throw new DatabaseClosedException();
_database.DeleteField(message.EntryId, message.FieldName);
}
}
}
}

View File

@@ -2,24 +2,24 @@
using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Domain.Exceptions;
namespace ModernKeePass.Application.Entry.Commands.SetFieldValue
namespace ModernKeePass.Application.Entry.Commands.UpsertField
{
public class SetFieldValueCommand : IRequest
public class UpsertFieldCommand : IRequest
{
public string EntryId { get; set; }
public string FieldName { get; set; }
public object FieldValue { get; set; }
public class SetFieldValueCommandHandler : IRequestHandler<SetFieldValueCommand>
public class UpsertFieldCommandHandler : IRequestHandler<UpsertFieldCommand>
{
private readonly IDatabaseProxy _database;
public SetFieldValueCommandHandler(IDatabaseProxy database)
public UpsertFieldCommandHandler(IDatabaseProxy database)
{
_database = database;
}
public void Handle(SetFieldValueCommand message)
public void Handle(UpsertFieldCommand message)
{
if (!_database.IsOpen) throw new DatabaseClosedException();

View File

@@ -1,10 +1,10 @@
using FluentValidation;
namespace ModernKeePass.Application.Entry.Commands.SetFieldValue
namespace ModernKeePass.Application.Entry.Commands.UpsertField
{
public class SetFieldValueCommandValidator: AbstractValidator<SetFieldValueCommand>
public class UpsertFieldCommandValidator: AbstractValidator<UpsertFieldCommand>
{
public SetFieldValueCommandValidator()
public UpsertFieldCommandValidator()
{
RuleFor(v => v.EntryId)
.NotNull()

View File

@@ -78,7 +78,6 @@
<Compile Include="Common\Constants.cs" />
<Compile Include="Dtos\Attachment.cs" />
<Compile Include="Dtos\Credentials.cs" />
<Compile Include="Dtos\Field.cs" />
<Compile Include="Dtos\FileInfo.cs" />
<Compile Include="Dtos\PasswordGenerationOptions.cs" />
<Compile Include="Entities\BaseEntity.cs" />

View File

@@ -1,8 +0,0 @@
namespace ModernKeePass.Domain.Dtos
{
public class Field
{
public string Name { get; set; }
public string Value { get; set; }
}
}

View File

@@ -242,9 +242,18 @@ namespace ModernKeePass.Infrastructure.KeePass
case EntryFieldName.ForegroundColor:
pwEntry.ForegroundColor = (Color)fieldValue;
break;
default:
pwEntry.Strings.Set(fieldName, new ProtectedString(true, fieldValue.ToString()));
break;
}
}
public void DeleteField(string entryId, string fieldName)
{
var pwEntry = _pwDatabase.RootGroup.FindEntry(BuildIdFromString(entryId), true);
pwEntry.Strings.Remove(fieldName);
}
public EntryEntity AddHistory(string entryId)
{
var pwEntry = _pwDatabase.RootGroup.FindEntry(BuildIdFromString(entryId), true);
@@ -306,7 +315,7 @@ namespace ModernKeePass.Infrastructure.KeePass
var pwGroup = _pwDatabase.RootGroup.FindGroup(BuildIdFromString(groupId), true);
pwGroup.SortSubGroups(false);
}
public void AddAttachment(string entryId, string attachmentName, byte[] attachmentContent)
{
var pwEntry = _pwDatabase.RootGroup.FindEntry(BuildIdFromString(entryId), true);

View File

@@ -534,4 +534,10 @@
<data name="EntryAddAttachment.Text" xml:space="preserve">
<value>Add attachment</value>
</data>
<data name="EntryAddAdditionalField.Text" xml:space="preserve">
<value>Add field</value>
</data>
<data name="EntryDeleteAdditionalField.Content" xml:space="preserve">
<value>Delete</value>
</data>
</root>

View File

@@ -276,4 +276,7 @@
<data name="CompositeKeyFileNameSuggestion" xml:space="preserve">
<value>Clé</value>
</data>
<data name="EntryAddAdditionalField.Text" xml:space="preserve">
<value>Ajouter un champ</value>
</data>
</root>

View File

@@ -534,4 +534,7 @@
<data name="EntryAddAttachment.Text" xml:space="preserve">
<value>Ajouter une pièce jointe</value>
</data>
<data name="EntryDeleteAdditionalField.Content" xml:space="preserve">
<value>Supprimer</value>
</data>
</root>

View File

@@ -16,9 +16,10 @@ using ModernKeePass.Application.Database.Queries.GetDatabase;
using ModernKeePass.Application.Entry.Commands.AddAttachment;
using ModernKeePass.Application.Entry.Commands.AddHistory;
using ModernKeePass.Application.Entry.Commands.DeleteAttachment;
using ModernKeePass.Application.Entry.Commands.DeleteField;
using ModernKeePass.Application.Entry.Commands.DeleteHistory;
using ModernKeePass.Application.Entry.Commands.RestoreHistory;
using ModernKeePass.Application.Entry.Commands.SetFieldValue;
using ModernKeePass.Application.Entry.Commands.UpsertField;
using ModernKeePass.Application.Entry.Models;
using ModernKeePass.Application.Entry.Queries.GetEntry;
using ModernKeePass.Application.Group.Commands.AddEntry;
@@ -34,6 +35,7 @@ using ModernKeePass.Domain.Dtos;
using ModernKeePass.Domain.Exceptions;
using ModernKeePass.Extensions;
using ModernKeePass.Models;
using ModernKeePass.ViewModels.ListItems;
namespace ModernKeePass.ViewModels
{
@@ -66,7 +68,7 @@ namespace ModernKeePass.ViewModels
}
public ObservableCollection<EntryVm> History { get; private set; }
public ObservableCollection<Field> AdditionalFields { get; private set; }
public ObservableCollection<FieldVm> AdditionalFields { get; private set; }
public ObservableCollection<Attachment> Attachments { get; private set; }
/// <summary>
@@ -82,11 +84,9 @@ namespace ModernKeePass.ViewModels
Set(() => SelectedItem, ref _selectedItem, value, true);
if (value != null)
{
AdditionalFields = new ObservableCollection<Field>(SelectedItem.AdditionalFields.Select(f => new Field
{
Name = f.Key,
Value = f.Value
}));
AdditionalFields =
new ObservableCollection<FieldVm>(
SelectedItem.AdditionalFields.Select(f => new FieldVm(f.Key, f.Value)));
Attachments = new ObservableCollection<Attachment>(SelectedItem.Attachments.Select(f => new Attachment
{
Name = f.Key,
@@ -113,6 +113,16 @@ namespace ModernKeePass.ViewModels
}
}
public int AdditionalFieldSelectedIndex
{
get { return _additionalFieldSelectedIndex; }
set
{
Set(() => AdditionalFieldSelectedIndex, ref _additionalFieldSelectedIndex, value);
DeleteAdditionalField.RaiseCanExecuteChanged();
}
}
public double PasswordLength
{
get { return _passwordLength; }
@@ -258,6 +268,8 @@ namespace ModernKeePass.ViewModels
public RelayCommand DeleteCommand { get; }
public RelayCommand GoBackCommand { get; }
public RelayCommand GoToParentCommand { get; set; }
public RelayCommand AddAdditionalField { get; set; }
public RelayCommand<FieldVm> DeleteAdditionalField { get; set; }
public RelayCommand<Attachment> OpenAttachmentCommand { get; set; }
public RelayCommand AddAttachmentCommand { get; set; }
public RelayCommand<Attachment> DeleteAttachmentCommand { get; set; }
@@ -273,11 +285,12 @@ namespace ModernKeePass.ViewModels
private GroupVm _parent;
private EntryVm _selectedItem;
private int _selectedIndex;
private int _additionalFieldSelectedIndex;
private bool _isEditMode;
private bool _isRevealPassword;
private double _passwordLength = 25;
private bool _isDirty;
public EntryDetailVm(IMediator mediator, INavigationService navigation, IResourceProxy resource, IDialogService dialog, INotificationService notification, IFileProxy file)
{
_mediator = mediator;
@@ -294,13 +307,17 @@ namespace ModernKeePass.ViewModels
DeleteCommand = new RelayCommand(async () => await AskForDelete());
GoBackCommand = new RelayCommand(() => _navigation.GoBack());
GoToParentCommand = new RelayCommand(() => GoToGroup(_parent.Id));
AddAdditionalField = new RelayCommand(AddField);
DeleteAdditionalField = new RelayCommand<FieldVm>(async field => await DeleteField(field), field => field != null);
OpenAttachmentCommand = new RelayCommand<Attachment>(async attachment => await OpenAttachment(attachment));
AddAttachmentCommand = new RelayCommand(async () => await AddAttachment(), () => IsCurrentEntry);
DeleteAttachmentCommand = new RelayCommand<Attachment>(async attachment => await DeleteAttachment(attachment));
MessengerInstance.Register<DatabaseSavedMessage>(this, _ => SaveCommand.RaiseCanExecuteChanged());
MessengerInstance.Register<EntryFieldValueChangedMessage>(this, async message => await SetFieldValue(message.FieldName, message.FieldValue));
MessengerInstance.Register<EntryFieldNameChangedMessage>(this, async message => await UpdateFieldName(message.OldName, message.NewName, message.Value));
}
public async Task Initialize(string entryId)
{
SelectedIndex = 0;
@@ -314,6 +331,70 @@ namespace ModernKeePass.ViewModels
History.CollectionChanged += (sender, args) => SaveCommand.RaiseCanExecuteChanged();
}
public async Task GeneratePassword()
{
Password = await _mediator.Send(new GeneratePasswordCommand
{
BracketsPatternSelected = BracketsPatternSelected,
CustomChars = CustomChars,
DigitsPatternSelected = DigitsPatternSelected,
LowerCasePatternSelected = LowerCasePatternSelected,
MinusPatternSelected = MinusPatternSelected,
PasswordLength = (int)PasswordLength,
SpacePatternSelected = SpacePatternSelected,
SpecialPatternSelected = SpecialPatternSelected,
UnderscorePatternSelected = UnderscorePatternSelected,
UpperCasePatternSelected = UpperCasePatternSelected
});
RaisePropertyChanged(nameof(IsRevealPasswordEnabled));
}
public async Task AddHistory()
{
if (_isDirty) await _mediator.Send(new AddHistoryCommand { Entry = History[0] });
}
public void GoToGroup(string groupId)
{
_navigation.NavigateTo(Constants.Navigation.GroupPage, new NavigationItem { Id = groupId });
}
private async Task Move(string destination)
{
await _mediator.Send(new AddEntryCommand { ParentGroupId = destination, EntryId = Id });
await _mediator.Send(new RemoveEntryCommand { ParentGroupId = _parent.Id, EntryId = Id });
GoToGroup(destination);
}
private async Task SetFieldValue(string fieldName, object value)
{
await _mediator.Send(new UpsertFieldCommand { EntryId = Id, FieldName = fieldName, FieldValue = value });
SaveCommand.RaiseCanExecuteChanged();
_isDirty = true;
}
private async Task UpdateFieldName(string oldName, string newName, string value)
{
if (!string.IsNullOrEmpty(oldName)) await _mediator.Send(new DeleteFieldCommand { EntryId = Id, FieldName = oldName });
await SetFieldValue(newName, value);
}
private void AddField()
{
AdditionalFields.Add(new FieldVm(string.Empty, string.Empty));
AdditionalFieldSelectedIndex = AdditionalFields.Count - 1;
}
private async Task DeleteField(FieldVm field)
{
AdditionalFields.Remove(field);
if (!string.IsNullOrEmpty(field.Name))
{
await _mediator.Send(new DeleteFieldCommand {EntryId = Id, FieldName = field.Name});
SaveCommand.RaiseCanExecuteChanged();
_isDirty = true;
}
}
private async Task AskForDelete()
{
if (IsCurrentEntry)
@@ -349,48 +430,6 @@ namespace ModernKeePass.ViewModels
}
}
public async Task GeneratePassword()
{
Password = await _mediator.Send(new GeneratePasswordCommand
{
BracketsPatternSelected = BracketsPatternSelected,
CustomChars = CustomChars,
DigitsPatternSelected = DigitsPatternSelected,
LowerCasePatternSelected = LowerCasePatternSelected,
MinusPatternSelected = MinusPatternSelected,
PasswordLength = (int)PasswordLength,
SpacePatternSelected = SpacePatternSelected,
SpecialPatternSelected = SpecialPatternSelected,
UnderscorePatternSelected = UnderscorePatternSelected,
UpperCasePatternSelected = UpperCasePatternSelected
});
RaisePropertyChanged(nameof(IsRevealPasswordEnabled));
}
public async Task Move(string destination)
{
await _mediator.Send(new AddEntryCommand { ParentGroupId = destination, EntryId = Id });
await _mediator.Send(new RemoveEntryCommand { ParentGroupId = _parent.Id, EntryId = Id });
GoToGroup(destination);
}
public async Task SetFieldValue(string fieldName, object value)
{
await _mediator.Send(new SetFieldValueCommand { EntryId = Id, FieldName = fieldName, FieldValue = value });
SaveCommand.RaiseCanExecuteChanged();
_isDirty = true;
}
public async Task AddHistory()
{
if (_isDirty) await _mediator.Send(new AddHistoryCommand { Entry = History[0] });
}
public void GoToGroup(string groupId)
{
_navigation.NavigateTo(Constants.Navigation.GroupPage, new NavigationItem { Id = groupId });
}
private async Task RestoreHistory()
{
await _mediator.Send(new RestoreHistoryCommand { Entry = History[0], HistoryIndex = History.Count - SelectedIndex - 1 });
@@ -442,12 +481,16 @@ namespace ModernKeePass.ViewModels
var contents = await _file.ReadBinaryFile(fileInfo.Id);
await _mediator.Send(new AddAttachmentCommand { Entry = SelectedItem, AttachmentName = fileInfo.Name, AttachmentContent = contents });
Attachments.Add(new Attachment { Name = fileInfo.Name, Content = contents });
SaveCommand.RaiseCanExecuteChanged();
_isDirty = true;
}
private async Task DeleteAttachment(Attachment attachment)
{
await _mediator.Send(new DeleteAttachmentCommand { Entry = SelectedItem, AttachmentName = attachment.Name });
Attachments.Remove(attachment);
SaveCommand.RaiseCanExecuteChanged();
_isDirty = true;
}
}

View File

@@ -482,29 +482,40 @@
</HubSection>
<HubSection x:Uid="EntryHubAdditional">
<DataTemplate>
<local:SelectableTemplateListView
ItemsSource="{Binding AdditionalFields}"
ItemContainerStyle="{StaticResource ListViewLeftIndicatorItemExpanded}">
<local:SelectableTemplateListView.SelectedItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBox Text="{Binding Name, Mode=TwoWay}" Width="350"
IsEnabled="{Binding Path=DataContext.IsCurrentEntry, ElementName=Page}" />
<TextBox HorizontalAlignment="Left" AcceptsReturn="True" Height="100" TextWrapping="Wrap" Width="350"
Text="{Binding Value, Mode=TwoWay}"
IsEnabled="{Binding Path=DataContext.IsCurrentEntry, ElementName=Page}" />
</StackPanel>
</DataTemplate>
</local:SelectableTemplateListView.SelectedItemTemplate>
<local:SelectableTemplateListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Name}" Style="{StaticResource EntryTextBlockStyle}" FontWeight="SemiBold" />
<TextBlock HorizontalAlignment="Left" MaxLines="3" FontSize="12" Margin="2,0,2,5" Text="{Binding Value}" Style="{StaticResource EntryTextBlockStyle}"/>
</StackPanel>
</DataTemplate>
</local:SelectableTemplateListView.ItemTemplate>
</local:SelectableTemplateListView>
<StackPanel Orientation="Vertical">
<HyperlinkButton Command="{Binding Path=DataContext.AddAdditionalField, ElementName=Page}">
<StackPanel Orientation="Horizontal">
<SymbolIcon Symbol="Add" />
<TextBlock x:Uid="EntryAddAdditionalField" VerticalAlignment="Center" Margin="10,0,0,0" />
</StackPanel>
</HyperlinkButton>
<Border BorderBrush="DarkGray" BorderThickness="0,0,0,1" />
<local:SelectableTemplateListView
ItemsSource="{Binding AdditionalFields}"
SelectedIndex="{Binding AdditionalFieldSelectedIndex, Mode=TwoWay}"
ItemContainerStyle="{StaticResource ListViewLeftIndicatorItemExpanded}">
<local:SelectableTemplateListView.SelectedItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBox Text="{Binding Name, Mode=TwoWay}" Width="350"
IsEnabled="{Binding Path=DataContext.IsCurrentEntry, ElementName=Page}" />
<TextBox HorizontalAlignment="Left" AcceptsReturn="True" Height="100" TextWrapping="Wrap" Width="350"
Text="{Binding Value, Mode=TwoWay}"
IsEnabled="{Binding Path=DataContext.IsCurrentEntry, ElementName=Page}" />
<Button x:Uid="EntryDeleteAdditionalField" HorizontalAlignment="Right" Command="{Binding Path=DataContext.DeleteAdditionalField, ElementName=Page}" CommandParameter="{Binding}" />
</StackPanel>
</DataTemplate>
</local:SelectableTemplateListView.SelectedItemTemplate>
<local:SelectableTemplateListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Name}" Style="{StaticResource EntryTextBlockStyle}" FontWeight="SemiBold" />
<TextBlock HorizontalAlignment="Left" MaxLines="3" FontSize="12" Margin="2,0,2,5" Text="{Binding Value}" Style="{StaticResource EntryTextBlockStyle}"/>
</StackPanel>
</DataTemplate>
</local:SelectableTemplateListView.ItemTemplate>
</local:SelectableTemplateListView>
</StackPanel>
</DataTemplate>
</HubSection>
<HubSection x:Uid="EntryHubAttachments" Foreground="{StaticResource HubSectionBrush}">

View File

@@ -20,6 +20,7 @@
</StackPanel>
</HyperlinkButton>
<controls:SelectableTemplateListView Grid.Row="1"
SelectedIndex="{Binding SelectedIndex}"
ItemsSource="{Binding RecentItems}"
ItemContainerStyle="{StaticResource ListViewLeftIndicatorItemExpanded}">
<controls:SelectableTemplateListView.SelectedItemTemplate>

View File

@@ -19,9 +19,17 @@ namespace ModernKeePass.Controls
public SelectableTemplateListView()
{
ContainerContentChanging += SelectableTemplateListView_ContainerContentChanging;
SelectionChanged += SelectableTemplateListView_SelectionChanged;
}
private void SelectableTemplateListView_ContainerContentChanging(ListViewBase sender, ContainerContentChangingEventArgs args)
{
args.ItemContainer.ContentTemplate = args.ItemContainer.IsSelected
? SelectedItemTemplate
: ItemTemplate;
}
private void SelectableTemplateListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var listView = sender as ListView;

View File

@@ -0,0 +1,9 @@
namespace Messages
{
public class EntryFieldNameChangedMessage
{
public string OldName { get; set; }
public string NewName { get; set; }
public string Value { get; set; }
}
}

View File

@@ -0,0 +1,8 @@
namespace Messages
{
public class EntryFieldValueChangedMessage
{
public string FieldName { get; set; }
public string FieldValue { get; set; }
}
}

View File

@@ -0,0 +1,37 @@
using GalaSoft.MvvmLight;
using Messages;
namespace ModernKeePass.ViewModels.ListItems
{
public class FieldVm: ViewModelBase
{
private string _name;
private string _value;
public string Name
{
get { return _name; }
set
{
MessengerInstance.Send(new EntryFieldNameChangedMessage { OldName = Name, NewName = value, Value = Value });
Set(nameof(Name), ref _name, value);
}
}
public string Value
{
get { return _value; }
set
{
MessengerInstance.Send(new EntryFieldValueChangedMessage { FieldName = Name, FieldValue = value });
Set(nameof(Value), ref _value, value);
}
}
public FieldVm(string fieldName, string fieldValue)
{
_name = fieldName;
_value = fieldValue;
}
}
}

View File

@@ -13,6 +13,7 @@ namespace ModernKeePass.ViewModels
{
private readonly IRecentProxy _recent;
private ObservableCollection<RecentItemVm> _recentItems;
private int _selectedIndex;
public ObservableCollection<RecentItemVm> RecentItems
{
@@ -21,7 +22,13 @@ namespace ModernKeePass.ViewModels
}
public ICommand ClearAllCommand { get; }
public int SelectedIndex
{
get { return _selectedIndex; }
set { Set(() => SelectedIndex, ref _selectedIndex, value); }
}
public RecentVm(IRecentProxy recent)
{
_recent = recent;
@@ -34,6 +41,7 @@ namespace ModernKeePass.ViewModels
{
var recentItems = _recent.GetAll().Select(r => new RecentItemVm(r));
RecentItems = new ObservableCollection<RecentItemVm>(recentItems);
if (RecentItems.Any()) SelectedIndex = 0;
}
private void ClearAll()

View File

@@ -36,10 +36,13 @@
<Compile Include="$(MSBuildThisFileDirectory)Messages\DatabaseOpenedMessage.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Messages\DatabaseOpeningMessage.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Messages\DatabaseSavedMessage.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Messages\EntryFieldNameChangedMessage.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Messages\EntryFieldValueChangedMessage.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Messages\FileNotFoundMessage.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Messages\NavigateToPageMessage.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Messages\SaveErrorMessage.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\AboutVm.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\Items\FieldVm.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\ViewModelLocatorCommon.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\Items\ListMenuItemVm.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\Items\MainMenuItemVm.cs" />