Finally a nicer looking and working TextBoxWithButton (inspired from the SearchButton)

SearchBox field style improved
This commit is contained in:
Geoffroy BONNEVILLE
2020-04-28 15:20:47 +02:00
parent 8e06bf4bb0
commit f158e5aced
24 changed files with 481 additions and 283 deletions

View File

@@ -95,6 +95,7 @@
<Compile Include="Group\Commands\DeleteEntry\DeleteEntryCommand.cs" />
<Compile Include="Group\Commands\DeleteGroup\DeleteGroupCommand.cs" />
<Compile Include="Group\Commands\UpdateGroup\UpdateGroupCommand.cs" />
<Compile Include="Group\Queries\GetAllGroups\GetAllGroupsQuery.cs" />
<Compile Include="Group\Queries\GetGroup\GetGroupQuery.cs" />
<Compile Include="Group\Queries\SearchEntries\SearchEntriesQuery.cs" />
<Compile Include="Parameters\Commands\SetCipher\SetCipherCommand.cs" />

View File

@@ -51,5 +51,6 @@ namespace ModernKeePass.Application.Common.Interfaces
void DeleteHistory(string entryId, int historyIndex);
IEnumerable<EntryEntity> Search(string groupId, string text);
IEnumerable<BaseEntity> GetAllGroups(string groupId);
}
}

View File

@@ -1,16 +1,14 @@
using System.Threading.Tasks;
using MediatR;
using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Application.Entry.Models;
using ModernKeePass.Application.Group.Models;
using ModernKeePass.Domain.Exceptions;
namespace ModernKeePass.Application.Group.Commands.AddEntry
{
public class AddEntryCommand : IRequest
{
public GroupVm ParentGroup { get; set; }
public EntryVm Entry { get; set; }
public string ParentGroupId { get; set; }
public string EntryId { get; set; }
public class AddEntryCommandHandler : IAsyncRequestHandler<AddEntryCommand>
{
@@ -25,8 +23,8 @@ namespace ModernKeePass.Application.Group.Commands.AddEntry
{
if (!_database.IsOpen) throw new DatabaseClosedException();
await _database.AddEntry(message.ParentGroup.Id, message.Entry.Id);
message.ParentGroup.Entries.Add(message.Entry);
await _database.AddEntry(message.ParentGroupId, message.EntryId);
//message.ParentGroup.Entries.Add(message.Entry);
}
}
}

View File

@@ -1,15 +1,14 @@
using System.Threading.Tasks;
using MediatR;
using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Application.Group.Models;
using ModernKeePass.Domain.Exceptions;
namespace ModernKeePass.Application.Group.Commands.AddGroup
{
public class AddGroupCommand : IRequest
{
public GroupVm ParentGroup { get; set; }
public GroupVm Group { get; set; }
public string ParentGroupId { get; set; }
public string GroupId { get; set; }
public class AddGroupCommandHandler : IAsyncRequestHandler<AddGroupCommand>
{
@@ -24,8 +23,8 @@ namespace ModernKeePass.Application.Group.Commands.AddGroup
{
if (!_database.IsOpen) throw new DatabaseClosedException();
await _database.AddGroup(message.ParentGroup.Id, message.Group.Id);
message.ParentGroup.SubGroups.Add(message.Group);
await _database.AddGroup(message.ParentGroupId, message.GroupId);
//message.ParentGroup.SubGroups.Add(message.Group);
}
}
}

View File

@@ -1,16 +1,14 @@
using System.Threading.Tasks;
using MediatR;
using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Application.Entry.Models;
using ModernKeePass.Application.Group.Models;
using ModernKeePass.Domain.Exceptions;
namespace ModernKeePass.Application.Group.Commands.RemoveEntry
{
public class RemoveEntryCommand : IRequest
{
public GroupVm ParentGroup { get; set; }
public EntryVm Entry { get; set; }
public string ParentGroupId { get; set; }
public string EntryId { get; set; }
public class RemoveEntryCommandHandler : IAsyncRequestHandler<RemoveEntryCommand>
{
@@ -25,8 +23,8 @@ namespace ModernKeePass.Application.Group.Commands.RemoveEntry
{
if (!_database.IsOpen) throw new DatabaseClosedException();
await _database.RemoveEntry(message.ParentGroup.Id, message.Entry.Id);
message.ParentGroup.Entries.Remove(message.Entry);
await _database.RemoveEntry(message.ParentGroupId, message.EntryId);
//message.ParentGroup.Entries.Remove(message.Entry);
}
}
}

View File

@@ -1,15 +1,14 @@
using System.Threading.Tasks;
using MediatR;
using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Application.Group.Models;
using ModernKeePass.Domain.Exceptions;
namespace ModernKeePass.Application.Group.Commands.RemoveGroup
{
public class RemoveGroupCommand : IRequest
{
public GroupVm ParentGroup { get; set; }
public GroupVm Group { get; set; }
public string ParentGroupId { get; set; }
public string GroupId { get; set; }
public class RemoveGroupCommandHandler : IAsyncRequestHandler<RemoveGroupCommand>
{
@@ -24,8 +23,8 @@ namespace ModernKeePass.Application.Group.Commands.RemoveGroup
{
if (!_database.IsOpen) throw new DatabaseClosedException();
await _database.RemoveGroup(message.ParentGroup.Id, message.Group.Id);
message.ParentGroup.SubGroups.Remove(message.Group);
await _database.RemoveGroup(message.ParentGroupId, message.GroupId);
//message.ParentGroup.SubGroups.Remove(message.Group);
}
}
}

View File

@@ -5,7 +5,6 @@ using ModernKeePass.Application.Common.Mappings;
using ModernKeePass.Application.Entry.Models;
using ModernKeePass.Domain.Entities;
using ModernKeePass.Domain.Enums;
using ModernKeePass.Domain.Interfaces;
namespace ModernKeePass.Application.Group.Models
{

View File

@@ -0,0 +1,33 @@
using System.Collections.Generic;
using System.Linq;
using AutoMapper;
using MediatR;
using ModernKeePass.Application.Common.Interfaces;
using ModernKeePass.Application.Group.Models;
using ModernKeePass.Domain.Exceptions;
namespace ModernKeePass.Application.Group.Queries.GetAllGroups
{
public class GetAllGroupsQuery : IRequest<IEnumerable<GroupVm>>
{
public string GroupId { get; set; }
public class GetAllGroupsQueryHandler : IRequestHandler<GetAllGroupsQuery, IEnumerable<GroupVm>>
{
private readonly IDatabaseProxy _database;
private readonly IMapper _mapper;
public GetAllGroupsQueryHandler(IDatabaseProxy database, IMapper mapper)
{
_database = database;
_mapper = mapper;
}
public IEnumerable<GroupVm> Handle(GetAllGroupsQuery message)
{
if (!_database.IsOpen) throw new DatabaseClosedException();
return _database.GetAllGroups(message.GroupId).Select(g => _mapper.Map<GroupVm>(g));
}
}
}
}

View File

@@ -348,6 +348,18 @@ namespace ModernKeePass.Infrastructure.KeePass
return searchResults.Select(e => _mapper.Map<EntryEntity>(e));
}
public IEnumerable<BaseEntity> GetAllGroups(string groupId)
{
var pwGroup = _pwDatabase.RootGroup.FindGroup(BuildIdFromString(groupId), true);
var groups = pwGroup.GetGroups(true).Select(g => new GroupEntity
{
Id = g.Uuid.ToHexString(),
Name = g.Name,
ParentName = g.ParentGroup?.Name
});
return groups;
}
private CompositeKey CreateCompositeKey(Credentials credentials)
{
var compositeKey = new CompositeKey();

View File

@@ -120,7 +120,7 @@
<Style TargetType="SearchBox" x:Key="MainColorSearchBox">
<Setter Property="Background" Value="{ThemeResource SearchBoxBackgroundThemeBrush}" />
<Setter Property="BorderBrush" Value="{ThemeResource AppBarBackgroundThemeBrush}" />
<Setter Property="BorderThickness" Value="{ThemeResource SearchBoxBorderThemeThickness}" />
<Setter Property="BorderThickness" Value="2" />
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
<Setter Property="FontSize" Value="{ThemeResource SearchBoxContentThemeFontSize}" />
<Setter Property="FontWeight" Value="{ThemeResource SearchBoxContentThemeFontWeight}"/>
@@ -153,7 +153,7 @@
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxPointerOverBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchBoxBorder" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxPointerOverBorderThemeBrush}" />
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource MainColorLight}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchButton" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource MainColorLight}" />
@@ -182,7 +182,7 @@
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxFocusedBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchBoxBorder" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxFocusedBorderThemeBrush}" />
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource MainColor}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchButton" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxButtonForegroundThemeBrush}" />
@@ -420,8 +420,8 @@
HorizontalAlignment="Left"
VerticalAlignment="Bottom">
<Border x:Name="SearchSuggestionsPopupBorder"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{ThemeResource ButtonBackgroundThemeBrush}"
BorderThickness="1"
MinWidth="{ThemeResource SearchBoxSuggestionPopupThemeMinWidth}">
<Border.Resources>
<Style x:Key="SearchSuggestionListViewItemStyle" TargetType="ListViewItem">
@@ -555,7 +555,7 @@
<Border x:Name="IMECandidateListContainer" />
<Border x:Name="IMECandidateListSeparator" Grid.Row="1" Visibility="Collapsed" BorderThickness="{ThemeResource SearchBoxIMECandidateListSeparatorThemeThickness}" BorderBrush="{ThemeResource SearchBoxIMECandidateListSeparatorThemeBrush}" />
<ListView x:Name="SearchSuggestionsList"
Background="{ThemeResource TextBoxBackgroundThemeBrush}"
Background="{ThemeResource AppBarBackgroundThemeBrush}"
Grid.Row="2"
IsTabStop="False"
IsItemClickEnabled="true"

View File

@@ -4,12 +4,157 @@
xmlns:controls="using:ModernKeePass.Controls">
<Style TargetType="controls:TextBoxWithButton" x:Key="TextBoxWithButtonStyle">
<Setter Property="Background" Value="{ThemeResource SearchBoxBackgroundThemeBrush}" />
<Setter Property="BorderBrush" Value="{ThemeResource AppBarBackgroundThemeBrush}" />
<Setter Property="BorderThickness" Value="2" />
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
<Setter Property="FontSize" Value="{ThemeResource SearchBoxContentThemeFontSize}" />
<Setter Property="FontWeight" Value="{ThemeResource SearchBoxContentThemeFontWeight}"/>
<Setter Property="Foreground" Value="{ThemeResource SearchBoxForegroundThemeBrush}" />
<Setter Property="Padding" Value="{ThemeResource SearchBoxThemePadding}"/>
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Typography.StylisticSet20" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="controls:TextBoxWithButton">
<Grid x:Name="SearchBoxGrid">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchBoxGrid" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Background}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchBoxBorder" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BorderBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ActionButton" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Foreground}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchBoxGrid" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxPointerOverBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchBoxBorder" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource MainColorLight}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ActionButton" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource MainColorLight}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchBoxGrid" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxDisabledBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchBoxBorder" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxDisabledBorderThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ActionButton" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxDisabledTextThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchTextBox" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="Transparent" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Focused">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchBoxGrid" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxFocusedBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchBoxBorder" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource MainColor}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ActionButton" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxButtonForegroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ActionButton" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource MainColor}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="FocusedDropDown">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchBoxGrid" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxFocusedBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchBoxBorder" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxFocusedBorderThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ActionButton" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxFocusedTextThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid.Resources>
<Style x:Key="ActionButtonStyle" TargetType="Button">
<Setter Property="IsTabStop" Value="False" />
<Setter Property="VerticalAlignment" Value="Stretch" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid Background="Transparent">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchGlyph" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxButtonPointerOverForegroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ActionButtonBackground" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource MainColor}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SearchGlyph" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxFocusedTextThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ActionButtonBackground" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SearchBoxFocusedBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled" />
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused" />
<VisualState x:Name="Unfocused" />
<VisualState x:Name="PointerFocused" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid x:Name="ActionButtonBackground" Background="{TemplateBinding Background}">
<TextBlock x:Name="SearchGlyph"
AutomationProperties.AccessibilityView="Raw"
FontFamily="{ThemeResource SymbolThemeFontFamily}"
Foreground="{TemplateBinding Foreground}"
HorizontalAlignment="Center"
FontStyle="Normal"
Padding="4,0,4,0"
Text="{TemplateBinding Content}"
VerticalAlignment="Center" />
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="SearchTextBoxStyle" TargetType="TextBox">
<Setter Property="MinWidth" Value="{ThemeResource TextControlThemeMinWidth}" />
<Setter Property="MinHeight" Value="{ThemeResource TextControlThemeMinHeight}" />
<Setter Property="Foreground" Value="{ThemeResource TextBoxForegroundThemeBrush}" />
<Setter Property="Background" Value="{ThemeResource TextBoxBackgroundThemeBrush}" />
<Setter Property="BorderBrush" Value="{ThemeResource TextBoxBorderThemeBrush}" />
<Setter Property="SelectionHighlightColor" Value="{ThemeResource MainColor}" />
<Setter Property="SelectionHighlightColor" Value="{StaticResource MainColor}" />
<Setter Property="BorderThickness" Value="{ThemeResource TextControlBorderThemeThickness}" />
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
@@ -19,85 +164,8 @@
<Setter Property="Padding" Value="{ThemeResource TextControlThemePadding}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="controls:TextBoxWithButton">
<ControlTemplate TargetType="TextBox">
<Grid>
<Grid.Resources>
<Style x:Name="ActionButtonStyle" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundElement"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPointerOverBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement"
Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPointerOverBorderThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="GlyphElement"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPointerOverForegroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundElement"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPressedBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement"
Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPressedBorderThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="GlyphElement"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPressedForegroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="BackgroundElement"
Storyboard.TargetProperty="Opacity"
To="0"
Duration="0" />
<DoubleAnimation Storyboard.TargetName="BorderElement"
Storyboard.TargetProperty="Opacity"
To="0"
Duration="0" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="BorderElement"
BorderBrush="{ThemeResource TextBoxButtonBorderThemeBrush}"
BorderThickness="{TemplateBinding BorderThickness}"/>
<Border x:Name="BackgroundElement"
Background="{ThemeResource TextBoxButtonBackgroundThemeBrush}"
Margin="{TemplateBinding BorderThickness}">
<TextBlock x:Name="GlyphElement"
Foreground="{ThemeResource TextBoxButtonForegroundThemeBrush}"
VerticalAlignment="Center"
HorizontalAlignment="Center"
FontStyle="Normal"
Padding="4,0,4,0"
Text="{TemplateBinding Content}"
FontFamily="{ThemeResource SymbolThemeFontFamily}"
AutomationProperties.AccessibilityView="Raw"/>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Disabled">
@@ -142,49 +210,12 @@
Storyboard.TargetProperty="Opacity"
Duration="0"
To="{ThemeResource TextControlPointerOverBorderThemeOpacity}" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ActionButton"
Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Focused">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ActionButton"
Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Focused" />
</VisualStateGroup>
<VisualStateGroup x:Name="ButtonStates">
<VisualState x:Name="ButtonVisible">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ActionButton"
Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="ButtonCollapsed" />
</VisualStateGroup>
<VisualStateGroup x:Name="ButtonStates" />
</VisualStateManager.VisualStateGroups>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
@@ -192,23 +223,20 @@
<Border x:Name="BackgroundElement"
Grid.Row="1"
Background="{TemplateBinding Background}"
Margin="{TemplateBinding BorderThickness}"
Grid.ColumnSpan="2" />
Margin="{TemplateBinding BorderThickness}" />
<Border x:Name="BorderElement"
Grid.Row="1"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Grid.ColumnSpan="2" Grid.Column="0" />
BorderThickness="{TemplateBinding BorderThickness}" />
<ContentPresenter x:Name="HeaderContentPresenter"
Grid.Row="0"
Foreground="{ThemeResource TextBoxForegroundHeaderThemeBrush}"
Margin="0,4,0,4"
Grid.ColumnSpan="2" Grid.Column="0"
Content="{TemplateBinding Header}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
FontWeight="Semilight" />
<ScrollViewer x:Name="ContentElement"
Grid.Row="1" Grid.Column="0"
Grid.Row="1"
HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}"
HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}"
@@ -227,41 +255,58 @@
Margin="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
IsTabStop="False"
Grid.ColumnSpan="2" Grid.Column="0"
Grid.ColumnSpan="2"
Content="{TemplateBinding PlaceholderText}"
IsHitTestVisible="False"/>
<Button x:Name="ActionButton"
Grid.Row="1"
Style="{StaticResource ActionButtonStyle}"
BorderThickness="{TemplateBinding BorderThickness}"
IsTabStop="False"
Grid.Column="1"
Visibility="Collapsed"
IsHitTestVisible="False" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<Border x:Name="SearchBoxBorder"
Background="Transparent"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBox x:Name="SearchTextBox"
BorderThickness="0"
Background="Transparent"
FontFamily="{TemplateBinding FontFamily}"
FontSize="{TemplateBinding FontSize}"
FontWeight="{TemplateBinding FontWeight}"
Foreground="{TemplateBinding Foreground}"
InputScope="Search"
MaxLength="2048"
MinHeight="{ThemeResource SearchBoxTextBoxThemeMinHeight}"
Padding="{TemplateBinding Padding}"
PlaceholderText="{TemplateBinding PlaceholderText}"
Style="{StaticResource SearchTextBoxStyle}"
TextWrapping="NoWrap"
VerticalAlignment="Stretch"
Margin="0"
Text="{TemplateBinding Text}" />
<Button x:Name="ActionButton"
AutomationProperties.AccessibilityView="Raw"
Background="Transparent"
FontWeight="{ThemeResource SearchBoxButtonThemeFontWeight}"
FontSize="{TemplateBinding FontSize}"
Grid.Column="1"
Style="{StaticResource ActionButtonStyle}"
Content="{TemplateBinding ButtonSymbol}"
IsEnabled="{TemplateBinding IsButtonEnabled}"
VerticalAlignment="Stretch">
Command="{TemplateBinding ButtonCommand}">
<ToolTipService.ToolTip>
<ToolTip Content="{TemplateBinding ButtonTooltip}" />
</ToolTipService.ToolTip>
<!--<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Cursor)">
<DiscreteObjectKeyFrame KeyTime="00:00:00">
<DiscreteObjectKeyFrame.Value>
<Cursor>Hand</Cursor>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>-->
</Button>
</Grid>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>

View File

@@ -210,7 +210,7 @@
<data name="GroupCreateEntry.Text" xml:space="preserve">
<value>Create new entry</value>
</data>
<data name="GroupSearch.PlaceholderText" xml:space="preserve">
<data name="EntriesSearch.PlaceholderText" xml:space="preserve">
<value>Search...</value>
</data>
<data name="GroupTitle.PlaceholderText" xml:space="preserve">
@@ -498,4 +498,10 @@
<data name="CloseDesc.Text" xml:space="preserve">
<value>This will close the currently opened database without saving the changes.</value>
</data>
<data name="GroupsSearch.PlaceholderText" xml:space="preserve">
<value>Destination group</value>
</data>
<data name="MoveButton.Content" xml:space="preserve">
<value>Move</value>
</data>
</root>

View File

@@ -210,8 +210,8 @@
<data name="GroupCreateEntry.Text" xml:space="preserve">
<value>Créer une nouvelle entrée</value>
</data>
<data name="GroupSearch.PlaceholderText" xml:space="preserve">
<value>Rechercher...</value>
<data name="GroupsSearch.PlaceholderText" xml:space="preserve">
<value>Groupe de destination</value>
</data>
<data name="GroupTitle.PlaceholderText" xml:space="preserve">
<value>Nom du nouveau groupe...</value>
@@ -501,4 +501,10 @@
<data name="CloseDesc.Text" xml:space="preserve">
<value>Cela va fermer la base de données ouverte sans sauvegarder les changements.</value>
</data>
<data name="EntriesSearch.PlaceholderText" xml:space="preserve">
<value>Rechercher...</value>
</data>
<data name="MoveButton.Content" xml:space="preserve">
<value>Déplacer</value>
</data>
</root>

View File

@@ -217,7 +217,7 @@ namespace ModernKeePass.ViewModels
public RelayCommand SaveCommand { get; }
public RelayCommand GeneratePasswordCommand { get; }
public RelayCommand MoveCommand { get; }
public RelayCommand<string> MoveCommand { get; }
public RelayCommand RestoreCommand { get; }
public RelayCommand DeleteCommand { get; }
public RelayCommand GoBackCommand { get; }
@@ -247,7 +247,7 @@ namespace ModernKeePass.ViewModels
SaveCommand = new RelayCommand(async () => await SaveChanges(), () => Database.IsDirty);
GeneratePasswordCommand = new RelayCommand(async () => await GeneratePassword());
MoveCommand = new RelayCommand(async () => await Move(_parent), () => _parent != null);
MoveCommand = new RelayCommand<string>(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());
@@ -319,10 +319,10 @@ namespace ModernKeePass.ViewModels
RaisePropertyChanged(nameof(IsRevealPasswordEnabled));
}
public async Task Move(GroupVm destination)
public async Task Move(string destination)
{
await _mediator.Send(new AddEntryCommand { ParentGroup = destination, Entry = SelectedItem });
await _mediator.Send(new RemoveEntryCommand { ParentGroup = _parent, Entry = SelectedItem });
await _mediator.Send(new AddEntryCommand { ParentGroupId = destination, EntryId = Id });
await _mediator.Send(new RemoveEntryCommand { ParentGroupId = _parent.Id, EntryId = Id });
}
public async Task SetFieldValue(string fieldName, object value)

View File

@@ -88,7 +88,7 @@ namespace ModernKeePass.ViewModels
public RelayCommand SaveCommand { get; }
public RelayCommand SortEntriesCommand { get; }
public RelayCommand SortGroupsCommand { get; }
public RelayCommand MoveCommand { get; }
public RelayCommand<string> MoveCommand { get; }
public RelayCommand CreateEntryCommand { get; }
public RelayCommand CreateGroupCommand { get; }
public RelayCommand DeleteCommand { get; set; }
@@ -117,10 +117,10 @@ namespace ModernKeePass.ViewModels
SaveCommand = new RelayCommand(async () => await SaveChanges(), () => Database.IsDirty);
SortEntriesCommand = new RelayCommand(async () => await SortEntriesAsync(), () => IsEditMode);
SortGroupsCommand = new RelayCommand(async () => await SortGroupsAsync(), () => IsEditMode);
MoveCommand = new RelayCommand(async () => await Move(_parent), () => IsNotRoot);
MoveCommand = new RelayCommand<string>(async destination => await Move(destination), destination => IsNotRoot && !string.IsNullOrEmpty(destination) && destination != Id);
CreateEntryCommand = new RelayCommand(async () => await AddNewEntry(), () => !IsInRecycleBin && Database.RecycleBinId != Id);
CreateGroupCommand = new RelayCommand(async () => await AddNewGroup(), () => !IsInRecycleBin && Database.RecycleBinId != Id);
DeleteCommand = new RelayCommand(async () => await AskForDelete());
DeleteCommand = new RelayCommand(async () => await AskForDelete(),() => IsNotRoot);
GoBackCommand = new RelayCommand(() => _navigation.GoBack());
}
@@ -167,10 +167,10 @@ namespace ModernKeePass.ViewModels
GoToEntry(entry.Id, true);
}
public async Task Move(GroupVm destination)
public async Task Move(string destinationId)
{
await _mediator.Send(new AddGroupCommand {ParentGroup = destination, Group = _group });
await _mediator.Send(new RemoveGroupCommand {ParentGroup = _parent, Group = _group });
await _mediator.Send(new AddGroupCommand {ParentGroupId = destinationId, GroupId = Id });
await _mediator.Send(new RemoveGroupCommand {ParentGroupId = _parent.Id, GroupId = Id });
}
public async Task<IEnumerable<EntryVm>> Search(string queryText)
@@ -196,7 +196,7 @@ namespace ModernKeePass.ViewModels
if (_reorderedEntry == null)
{
var entry = (EntryVm) e.NewItems[0];
await _mediator.Send(new AddEntryCommand {Entry = entry, ParentGroup = _group});
await _mediator.Send(new AddEntryCommand {EntryId = entry.Id, ParentGroupId = Id});
}
else
{

View File

@@ -3,7 +3,6 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewModels="using:ModernKeePass.ViewModels"
xmlns:converters="using:ModernKeePass.Converters"
xmlns:local="using:ModernKeePass.Controls"
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
@@ -431,7 +430,7 @@
<ProgressBar Value="{Binding PasswordComplexityIndicator, ConverterParameter=0\,128, Converter={StaticResource ProgressBarLegalValuesConverter}}" Maximum="128" Width="350" HorizontalAlignment="Left" Foreground="{Binding PasswordComplexityIndicator, ConverterParameter=128, Converter={StaticResource DoubleToForegroundBrushComplexityConverter}}" />
<CheckBox x:Uid="EntryShowPassword" HorizontalAlignment="Left" Margin="-3,0,0,0" IsChecked="{Binding IsRevealPassword, Mode=TwoWay}" IsEnabled="{Binding IsRevealPasswordEnabled}" />
<TextBlock TextWrapping="Wrap" Text="URL" FontSize="18"/>
<local:TextBoxWithButton x:Uid="UrlTextBox" Text="{Binding Url, Mode=TwoWay}" MaxLength="256" Style="{StaticResource EntryTextBoxWithButtonStyle}" ButtonSymbol="&#xE111;" IsEnabled="{Binding IsCurrentEntry}">
<local:TextBoxWithButton x:Uid="UrlTextBox" Text="{Binding Url, Mode=TwoWay}" Style="{StaticResource EntryTextBoxWithButtonStyle}" ButtonSymbol="&#xE111;" IsEnabled="{Binding IsCurrentEntry}">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="ButtonClick">
<actions:NavigateToUrlAction Url="{Binding Url}" />

View File

@@ -270,7 +270,7 @@
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</Button>
<SearchBox Grid.Column="3" x:Uid="GroupSearch" x:Name="SearchBox" Padding="12" Width="350" Visibility="Collapsed" Background="{ThemeResource TextBoxDisabledBackgroundThemeBrush}" BorderThickness="0" Margin="0,5,0,5" FontSize="15" SuggestionsRequested="SearchBox_OnSuggestionsRequested" SearchHistoryEnabled="False" ResultSuggestionChosen="SearchBox_OnResultSuggestionChosen" Style="{StaticResource MainColorSearchBox}">
<SearchBox Grid.Column="3" x:Uid="EntriesSearch" x:Name="SearchBox" Padding="12" Width="350" Visibility="Collapsed" Margin="0,5,0,5" FontSize="15" SuggestionsRequested="SearchBox_OnSuggestionsRequested" SearchHistoryEnabled="False" ResultSuggestionChosen="SearchBox_OnResultSuggestionChosen" Style="{StaticResource MainColorSearchBox}">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="LostFocus">
<core:ChangePropertyAction TargetObject="{Binding ElementName=SearchBox}" PropertyName="Visibility" Value="Collapsed" />

View File

@@ -1,8 +1,8 @@
using System;
using System.Collections.Generic;
using System.Windows.Input;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using GalaSoft.MvvmLight.Command;
using ModernKeePass.Application.Common.Interfaces;
// The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236
@@ -125,15 +125,15 @@ namespace ModernKeePass.Views.UserControls
typeof(HamburgerMenuUserControl),
new PropertyMetadata(false, (o, args) => { }));
public RelayCommand ActionButtonCommand
public ICommand ActionButtonCommand
{
get { return (RelayCommand)GetValue(ActionButtonCommandProperty); }
get { return (ICommand)GetValue(ActionButtonCommandProperty); }
set { SetValue(ActionButtonCommandProperty, value); }
}
public static readonly DependencyProperty ActionButtonCommandProperty =
DependencyProperty.Register(
nameof(ActionButtonCommand),
typeof(RelayCommand),
typeof(ICommand),
typeof(HamburgerMenuUserControl),
new PropertyMetadata(null, (o, args) => { }));

View File

@@ -16,7 +16,7 @@
<Setter Property="Height" Value="{StaticResource MenuSize}" />
</Style>
</UserControl.Resources>
<StackPanel Orientation="Horizontal">
<StackPanel x:Name="StackPanel" Orientation="Horizontal" DataContext="{Binding Source={StaticResource Locator}, Path=TopMenu}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="VisibilityStates">
<VisualState x:Name="Overflowed">
@@ -49,12 +49,29 @@
</ToolTipService.ToolTip>
</SymbolIcon>
</Button>
<Button Command="{Binding MoveCommand, ElementName=UserControl}" Visibility="{Binding MoveButtonVisibility, ElementName=UserControl}" Style="{StaticResource MenuButtonStyle}">
<Button Visibility="{Binding MoveButtonVisibility, ElementName=UserControl}" Style="{StaticResource MenuButtonStyle}">
<SymbolIcon Symbol="MoveToFolder">
<ToolTipService.ToolTip>
<ToolTip x:Uid="TopMenuMoveButton" />
</ToolTipService.ToolTip>
</SymbolIcon>
<Button.Flyout>
<Flyout>
<StackPanel>
<SearchBox
x:Uid="GroupsSearch"
Padding="12" Width="350"
Margin="0,5,0,5"
FontSize="15"
SuggestionsRequested="SearchBox_OnSuggestionsRequested"
ResultSuggestionChosen="SearchBox_OnResultSuggestionChosen"
SearchHistoryEnabled="False"
Style="{StaticResource MainColorSearchBox}">
</SearchBox>
<Button x:Uid="MoveButton" Command="{Binding MoveCommand, ElementName=UserControl}" CommandParameter="{Binding SelectedDestinationGroup}" Style="{StaticResource MainColorButton}" />
</StackPanel>
</Flyout>
</Button.Flyout>
</Button>
<Button Command="{Binding RestoreCommand, ElementName=UserControl}" Visibility="{Binding RestoreButtonVisibility, ElementName=UserControl}" Style="{StaticResource MenuButtonStyle}">
<SymbolIcon Symbol="Undo">
@@ -96,7 +113,7 @@
<Button.Flyout>
<MenuFlyout Opening="OverflowFlyout_OnOpening">
<MenuFlyoutItem x:Uid="TopMenuSaveFlyout" Command="{Binding SaveCommand, ElementName=UserControl}" />
<MenuFlyoutItem x:Uid="TopMenuMoveFlyout" x:Name="MoveFlyout" Command="{Binding MoveCommand, ElementName=UserControl}" Visibility="{Binding MoveButtonVisibility, ElementName=UserControl}" />
<MenuFlyoutItem x:Uid="TopMenuMoveFlyout" x:Name="MoveFlyout" Visibility="{Binding MoveButtonVisibility, ElementName=UserControl}" />
<MenuFlyoutItem x:Uid="TopMenuRestoreFlyout" x:Name="RestoreFlyout" Command="{Binding RestoreCommand, ElementName=UserControl}" Visibility="{Binding RestoreButtonVisibility, ElementName=UserControl}" />
<ToggleMenuFlyoutItem x:Uid="TopMenuEditFlyout" x:Name="EditFlyout" Command="{Binding EditCommand, ElementName=UserControl}" IsChecked="{Binding IsEditButtonChecked, ElementName=UserControl, Mode=TwoWay}" Click="EditButton_Click" />
<MenuFlyoutItem x:Uid="TopMenuDeleteFlyout" x:Name="DeleteFlyout" Command="{Binding DeleteCommand, ElementName=UserControl}" IsEnabled="{Binding IsDeleteButtonEnabled, ElementName=UserControl}" Click="DeleteButton_Click" />

View File

@@ -1,6 +1,11 @@
using System;
using System.Linq;
using System.Windows.Input;
using Windows.Storage.Streams;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using GalaSoft.MvvmLight.Command;
using ModernKeePass.ViewModels;
// The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236
@@ -8,6 +13,8 @@ namespace ModernKeePass.Views.UserControls
{
public sealed partial class TopMenuUserControl
{
public TopMenuVm Model => (TopMenuVm)StackPanel.DataContext;
public ICommand SaveCommand
{
get { return (ICommand)GetValue(SaveCommandProperty); }
@@ -44,15 +51,15 @@ namespace ModernKeePass.Views.UserControls
typeof(TopMenuUserControl),
new PropertyMetadata(null, (o, args) => { }));
public ICommand MoveCommand
public RelayCommand<string> MoveCommand
{
get { return (ICommand)GetValue(MoveCommandProperty); }
get { return (RelayCommand<string>)GetValue(MoveCommandProperty); }
set { SetValue(MoveCommandProperty, value); }
}
public static readonly DependencyProperty MoveCommandProperty =
DependencyProperty.Register(
nameof(MoveCommand),
typeof(ICommand),
typeof(RelayCommand<string>),
typeof(TopMenuUserControl),
new PropertyMetadata(null, (o, args) => { }));
@@ -114,7 +121,7 @@ namespace ModernKeePass.Views.UserControls
nameof(MoveButtonVisibility),
typeof(Visibility),
typeof(TopMenuUserControl),
new PropertyMetadata(Visibility.Collapsed, (o, args) => { }));
new PropertyMetadata(Visibility.Visible, (o, args) => { }));
public Visibility RestoreButtonVisibility
{
@@ -199,5 +206,19 @@ namespace ModernKeePass.Views.UserControls
SortGroupsButtonFlyout.Command = SortGroupsCommand;
}
private void SearchBox_OnSuggestionsRequested(SearchBox sender, SearchBoxSuggestionsRequestedEventArgs args)
{
var imageUri = RandomAccessStreamReference.CreateFromUri(new Uri("ms-appdata://Assets/ModernKeePass-SmallLogo.scale-80.png"));
foreach (var group in Model.Groups.Where(g => g.Title.IndexOf(args.QueryText, StringComparison.OrdinalIgnoreCase) >= 0))
{
args.Request.SearchSuggestionCollection.AppendResultSuggestion(group.Title, group.ParentGroupName, group.Id, imageUri, string.Empty);
}
}
private void SearchBox_OnResultSuggestionChosen(SearchBox sender, SearchBoxResultSuggestionChosenEventArgs args)
{
Model.SelectedDestinationGroup = args.Tag;
MoveCommand.RaiseCanExecuteChanged();
}
}
}

View File

@@ -1,10 +1,11 @@
using System;
using System.Windows.Input;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
namespace ModernKeePass.Controls
{
public class TextBoxWithButton : TextBox
public class TextBoxWithButton : Control
{
public event EventHandler<RoutedEventArgs> ButtonClick;
@@ -15,7 +16,7 @@ namespace ModernKeePass.Controls
}
public static readonly DependencyProperty ButtonSymbolProperty =
DependencyProperty.Register(
"ButtonSymbol",
nameof(ButtonSymbol),
typeof(string),
typeof(TextBoxWithButton),
new PropertyMetadata("&#xE107;", (o, args) => { }));
@@ -27,11 +28,46 @@ namespace ModernKeePass.Controls
}
public static readonly DependencyProperty ButtonTooltipProperty =
DependencyProperty.Register(
"ButtonTooltip",
nameof(ButtonTooltip),
typeof(string),
typeof(TextBoxWithButton),
new PropertyMetadata(string.Empty, (o, args) => { }));
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register(
nameof(Text),
typeof(string),
typeof(TextBoxWithButton),
new PropertyMetadata(string.Empty, (o, args) => { }));
public string PlaceholderText
{
get { return (string)GetValue(PlaceholderTextProperty); }
set { SetValue(PlaceholderTextProperty, value); }
}
public static readonly DependencyProperty PlaceholderTextProperty =
DependencyProperty.Register(
nameof(PlaceholderText),
typeof(string),
typeof(TextBoxWithButton),
new PropertyMetadata(string.Empty, (o, args) => { }));
public ICommand ButtonCommand
{
get { return (ICommand)GetValue(ButtonCommandProperty); }
set { SetValue(ButtonCommandProperty, value); }
}
public static readonly DependencyProperty ButtonCommandProperty =
DependencyProperty.Register(
nameof(ButtonCommand),
typeof(ICommand),
typeof(TextBoxWithButton),
new PropertyMetadata(null, (o, args) => { }));
public bool IsButtonEnabled
{
get { return (bool)GetValue(IsButtonEnabledProperty); }
@@ -44,6 +80,11 @@ namespace ModernKeePass.Controls
typeof(TextBoxWithButton),
new PropertyMetadata(true, (o, args) => { }));
public TextBoxWithButton()
{
DefaultStyleKey = typeof(TextBoxWithButton);
}
protected override void OnApplyTemplate()
{
base.OnApplyTemplate();

View File

@@ -0,0 +1,20 @@
using System.Collections.Generic;
using MediatR;
using ModernKeePass.Application.Database.Queries.GetDatabase;
using ModernKeePass.Application.Group.Models;
using ModernKeePass.Application.Group.Queries.GetAllGroups;
namespace ModernKeePass.ViewModels
{
public class TopMenuVm
{
public IEnumerable<GroupVm> Groups { get; set; }
public string SelectedDestinationGroup { get; set; }
public TopMenuVm(IMediator mediator)
{
var database = mediator.Send(new GetDatabaseQuery()).GetAwaiter().GetResult();
Groups = mediator.Send(new GetAllGroupsQuery { GroupId = database.RootGroupId }).GetAwaiter().GetResult();
}
}
}

View File

@@ -63,6 +63,7 @@ namespace ModernKeePass.ViewModels
SimpleIoc.Default.Register<SettingsSecurityVm>();
SimpleIoc.Default.Register<OpenDatabaseControlVm>();
SimpleIoc.Default.Register<SetCredentialsVm>();
SimpleIoc.Default.Register<TopMenuVm>();
SimpleIoc.Default.Register<MainVm>();
SimpleIoc.Default.Register<NewVm>();
SimpleIoc.Default.Register<OpenVm>();
@@ -80,6 +81,7 @@ namespace ModernKeePass.ViewModels
public SettingsSecurityVm SettingsSecurity => ServiceLocator.Current.GetInstance<SettingsSecurityVm>(Guid.NewGuid().ToString());
public OpenDatabaseControlVm OpenDatabaseControl => ServiceLocator.Current.GetInstance<OpenDatabaseControlVm>(Guid.NewGuid().ToString());
public SetCredentialsVm SetCredentials => ServiceLocator.Current.GetInstance<SetCredentialsVm>(Guid.NewGuid().ToString());
public TopMenuVm TopMenu => ServiceLocator.Current.GetInstance<TopMenuVm>(Guid.NewGuid().ToString());
public NewVm New => ServiceLocator.Current.GetInstance<NewVm>(Guid.NewGuid().ToString());
public OpenVm Open => ServiceLocator.Current.GetInstance<OpenVm>(Guid.NewGuid().ToString());
public RecentVm Recent => ServiceLocator.Current.GetInstance<RecentVm>(Guid.NewGuid().ToString());

View File

@@ -55,6 +55,7 @@
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\SaveVm.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\UserControls\OpenDatabaseControlVm.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\UserControls\SetCredentialsVm.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\UserControls\TopMenuVm.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ViewModels\ViewModelLocator.cs" />
</ItemGroup>
</Project>