Initial support for masking

This commit is contained in:
TheXamlGuy
2024-06-08 18:00:36 +01:00
parent 05a6cd4540
commit 64847f2096
17 changed files with 377 additions and 71 deletions
+89 -1
View File
@@ -6,6 +6,94 @@
x:DataType="vm:ItemDropdownEntryViewModel"
Header="{Binding Key}">
<SettingsExpander.Footer>
<TextBox MinWidth="264" />
<Grid>
<ComboBox
DisplayMemberBinding="{ReflectionBinding Value}"
ItemsSource="{Binding}"
SelectedItem="{Binding SelectedItem}"
SelectedValue="{Binding Value}"
SelectedValueBinding="{ReflectionBinding Value}">
<ComboBox.Styles>
<Style Selector="ComboBox.Write">
<Setter Property="MinWidth" Value="264" />
<Setter Property="IsVisible" Value="True" />
</Style>
<Style Selector="ComboBox.Read">
<Setter Property="MinWidth" Value="0" />
<Setter Property="IsVisible" Value="False" />
</Style>
</ComboBox.Styles>
<Interaction.Behaviors>
<DataTriggerBehavior Binding="{Binding State}" Value="{x:Static vm:ItemState.Read}">
<AddClassAction ClassName="Read" RemoveIfExists="True" />
<RemoveClassAction ClassName="Write" />
</DataTriggerBehavior>
<DataTriggerBehavior Binding="{Binding State}" Value="{x:Static vm:ItemState.New}">
<AddClassAction ClassName="Write" RemoveIfExists="True" />
<RemoveClassAction ClassName="Read" />
</DataTriggerBehavior>
<DataTriggerBehavior Binding="{Binding State}" Value="{x:Static vm:ItemState.Write}">
<AddClassAction ClassName="Write" RemoveIfExists="True" />
<RemoveClassAction ClassName="Read" />
</DataTriggerBehavior>
</Interaction.Behaviors>
</ComboBox>
<TextBox Text="{Binding Value}">
<TextBox.Styles>
<Style Selector="TextBox.Write">
<Setter Property="IsVisible" Value="False" />
</Style>
<Style Selector="TextBox.Read">
<Setter Property="MinWidth" Value="0" />
<Setter Property="IsReadOnly" Value="True" />
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="IsVisible" Value="True" />
<Setter Property="Foreground">
<Setter.Value>
<SolidColorBrush Opacity="0.7" Color="{DynamicResource TextFillColorPrimary}" />
</Setter.Value>
</Setter>
<Style Selector="^:pointerover">
<Setter Property="Foreground">
<Setter.Value>
<SolidColorBrush Opacity="0.7" Color="{DynamicResource TextFillColorPrimary}" />
</Setter.Value>
</Setter>
<Style Selector="^ /template/ Border#PART_BorderElement">
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="Background" Value="Transparent" />
</Style>
</Style>
<Style Selector="^:focus">
<Setter Property="Foreground">
<Setter.Value>
<SolidColorBrush Opacity="0.7" Color="{DynamicResource TextFillColorPrimary}" />
</Setter.Value>
</Setter>
<Style Selector="^ /template/ Border#PART_BorderElement">
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderBrush" Value="Transparent" />
</Style>
</Style>
</Style>
</TextBox.Styles>
<Interaction.Behaviors>
<DataTriggerBehavior Binding="{Binding State}" Value="{x:Static vm:ItemState.Read}">
<AddClassAction ClassName="Read" RemoveIfExists="True" />
<RemoveClassAction ClassName="Write" />
</DataTriggerBehavior>
<DataTriggerBehavior Binding="{Binding State}" Value="{x:Static vm:ItemState.New}">
<AddClassAction ClassName="Write" RemoveIfExists="True" />
<RemoveClassAction ClassName="Read" />
</DataTriggerBehavior>
<DataTriggerBehavior Binding="{Binding State}" Value="{x:Static vm:ItemState.Write}">
<AddClassAction ClassName="Write" RemoveIfExists="True" />
<RemoveClassAction ClassName="Read" />
</DataTriggerBehavior>
</Interaction.Behaviors>
</TextBox>
</Grid>
</SettingsExpander.Footer>
</SettingsExpander>
+42
View File
@@ -14,11 +14,53 @@
Text="{Binding Value}"
TextAlignment="Center"
Watermark="Enter name">
<TextBox.Styles>
<Style Selector="TextBox.Write">
<Setter Property="MinWidth" Value="264" />
</Style>
<Style Selector="TextBox.Read">
<Setter Property="MinWidth" Value="0" />
<Setter Property="IsReadOnly" Value="True" />
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Foreground">
<Setter.Value>
<SolidColorBrush Opacity="0.7" Color="{DynamicResource TextFillColorPrimary}" />
</Setter.Value>
</Setter>
<Style Selector="^:pointerover">
<Setter Property="Foreground">
<Setter.Value>
<SolidColorBrush Opacity="0.7" Color="{DynamicResource TextFillColorPrimary}" />
</Setter.Value>
</Setter>
<Style Selector="^ /template/ Border#PART_BorderElement">
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="Background" Value="Transparent" />
</Style>
</Style>
<Style Selector="^:focus">
<Setter Property="Foreground">
<Setter.Value>
<SolidColorBrush Opacity="0.7" Color="{DynamicResource TextFillColorPrimary}" />
</Setter.Value>
</Setter>
<Style Selector="^ /template/ Border#PART_BorderElement">
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderBrush" Value="Transparent" />
</Style>
</Style>
</Style>
</TextBox.Styles>
<Interaction.Behaviors>
<DataTriggerBehavior Binding="{Binding State}" Value="{x:Static vm:ItemState.Read}">
<AddClassAction ClassName="Read" RemoveIfExists="True" />
<RemoveClassAction ClassName="Write" />
</DataTriggerBehavior>
<DataTriggerBehavior Binding="{Binding State}" Value="{x:Static vm:ItemState.New}">
<AddClassAction ClassName="Write" RemoveIfExists="True" />
<RemoveClassAction ClassName="Read" />
</DataTriggerBehavior>
<DataTriggerBehavior Binding="{Binding State}" Value="{x:Static vm:ItemState.Write}">
<AddClassAction ClassName="Write" RemoveIfExists="True" />
<RemoveClassAction ClassName="Read" />
@@ -6,6 +6,59 @@
x:DataType="vm:ItemMaskedTextEntryViewModel"
Header="{Binding Key}">
<SettingsExpander.Footer>
<MaskedTextBox Mask="{Binding Pattern}" Text="{Binding Value}" />
<MaskedTextBox Mask="{Binding Pattern}" Text="{Binding Value}">
<TextBox.Styles>
<Style Selector="TextBox.Write">
<Setter Property="MinWidth" Value="264" />
</Style>
<Style Selector="TextBox.Read">
<Setter Property="MinWidth" Value="0" />
<Setter Property="IsReadOnly" Value="True" />
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Foreground">
<Setter.Value>
<SolidColorBrush Opacity="0.7" Color="{DynamicResource TextFillColorPrimary}" />
</Setter.Value>
</Setter>
<Style Selector="^:pointerover">
<Setter Property="Foreground">
<Setter.Value>
<SolidColorBrush Opacity="0.7" Color="{DynamicResource TextFillColorPrimary}" />
</Setter.Value>
</Setter>
<Style Selector="^ /template/ Border#PART_BorderElement">
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="Background" Value="Transparent" />
</Style>
</Style>
<Style Selector="^:focus">
<Setter Property="Foreground">
<Setter.Value>
<SolidColorBrush Opacity="0.7" Color="{DynamicResource TextFillColorPrimary}" />
</Setter.Value>
</Setter>
<Style Selector="^ /template/ Border#PART_BorderElement">
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderBrush" Value="Transparent" />
</Style>
</Style>
</Style>
</TextBox.Styles>
<Interaction.Behaviors>
<DataTriggerBehavior Binding="{Binding State}" Value="{x:Static vm:ItemState.Read}">
<AddClassAction ClassName="Read" RemoveIfExists="True" />
<RemoveClassAction ClassName="Write" />
</DataTriggerBehavior>
<DataTriggerBehavior Binding="{Binding State}" Value="{x:Static vm:ItemState.New}">
<AddClassAction ClassName="Write" RemoveIfExists="True" />
<RemoveClassAction ClassName="Read" />
</DataTriggerBehavior>
<DataTriggerBehavior Binding="{Binding State}" Value="{x:Static vm:ItemState.Write}">
<AddClassAction ClassName="Write" RemoveIfExists="True" />
<RemoveClassAction ClassName="Read" />
</DataTriggerBehavior>
</Interaction.Behaviors>
</MaskedTextBox>
</SettingsExpander.Footer>
</SettingsExpander>
+42 -4
View File
@@ -7,15 +7,53 @@
Header="{Binding Key}">
<SettingsExpander.Footer>
<TextBox Text="{Binding Value}">
<TextBox.Styles>
<Style Selector="TextBox.Write">
<Setter Property="MinWidth" Value="264" />
</Style>
<Style Selector="TextBox.Read">
<Setter Property="MinWidth" Value="0" />
<Setter Property="IsReadOnly" Value="True" />
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Foreground">
<Setter.Value>
<SolidColorBrush Opacity="0.7" Color="{DynamicResource TextFillColorPrimary}" />
</Setter.Value>
</Setter>
<Style Selector="^:pointerover">
<Setter Property="Foreground">
<Setter.Value>
<SolidColorBrush Opacity="0.7" Color="{DynamicResource TextFillColorPrimary}" />
</Setter.Value>
</Setter>
<Style Selector="^ /template/ Border#PART_BorderElement">
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="Background" Value="Transparent" />
</Style>
</Style>
<Style Selector="^:focus">
<Setter Property="Foreground">
<Setter.Value>
<SolidColorBrush Opacity="0.7" Color="{DynamicResource TextFillColorPrimary}" />
</Setter.Value>
</Setter>
<Style Selector="^ /template/ Border#PART_BorderElement">
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderBrush" Value="Transparent" />
</Style>
</Style>
</Style>
</TextBox.Styles>
<Interaction.Behaviors>
<DataTriggerBehavior Binding="{Binding State}" Value="{x:Static vm:ItemState.Read}">
<AddClassAction ClassName="Read" RemoveIfExists="True" />
<RemoveClassAction ClassName="Write" />
</DataTriggerBehavior>
<DataTriggerBehavior Binding="{Binding State}" Value="{x:Static vm:ItemState.New}">
<AddClassAction ClassName="Write" RemoveIfExists="True" />
<RemoveClassAction ClassName="Read" />
</DataTriggerBehavior>
<DataTriggerBehavior Binding="{Binding State}" Value="{x:Static vm:ItemState.New}">
<AddClassAction ClassName="Write" RemoveIfExists="True" />
<RemoveClassAction ClassName="Read" />
</DataTriggerBehavior>
<DataTriggerBehavior Binding="{Binding State}" Value="{x:Static vm:ItemState.Write}">
<AddClassAction ClassName="Write" RemoveIfExists="True" />
<RemoveClassAction ClassName="Read" />
-38
View File
@@ -4,44 +4,6 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:Bitvault"
x:DataType="vm:ItemViewModel">
<UserControl.Styles>
<Style Selector="TextBox.Write">
<Setter Property="MinWidth" Value="264" />
</Style>
<Style Selector="TextBox.Read">
<Setter Property="MinWidth" Value="0" />
<Setter Property="IsReadOnly" Value="True" />
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Foreground">
<Setter.Value>
<SolidColorBrush Opacity="0.7" Color="{DynamicResource TextFillColorPrimary}" />
</Setter.Value>
</Setter>
<Style Selector="^:pointerover">
<Setter Property="Foreground">
<Setter.Value>
<SolidColorBrush Opacity="0.7" Color="{DynamicResource TextFillColorPrimary}" />
</Setter.Value>
</Setter>
<Style Selector="^ /template/ Border#PART_BorderElement">
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="Background" Value="Transparent" />
</Style>
</Style>
<Style Selector="^:focus">
<Setter Property="Foreground">
<Setter.Value>
<SolidColorBrush Opacity="0.7" Color="{DynamicResource TextFillColorPrimary}" />
</Setter.Value>
</Setter>
<Style Selector="^ /template/ Border#PART_BorderElement">
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderBrush" Value="Transparent" />
</Style>
</Style>
</Style>
</UserControl.Styles>
<Interaction.Behaviors>
<AttachedBehaviour>
<NavigateAction
+1 -1
View File
@@ -8,7 +8,7 @@ public partial class BackActionViewModel(IServiceProvider provider,
IMediator mediator,
IPublisher publisher,
ISubscription subscriber,
IDisposer disposer) : Observable<string>(provider, factory, mediator, publisher, subscriber, disposer)
IDisposer disposer) : Observable(provider, factory, mediator, publisher, subscriber, disposer)
{
[ObservableProperty]
private int index = 0;
+1 -1
View File
@@ -6,5 +6,5 @@ public record DropdownEntryConfiguration :
ItemEntryConfiguration
{
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string[]? Values { get; set; }
public IList<string> Values { get; set; } = new List<string>();
}
+33 -10
View File
@@ -2,13 +2,36 @@
namespace Bitvault;
public partial class ItemDropdownEntryViewModel(IServiceProvider provider,
IServiceFactory factory,
IMediator mediator,
IPublisher publisher,
ISubscription subscriber,
IDisposer disposer,
ItemState state,
ItemEntryConfiguration configuration,
string? key = default,
object? value = default) : ItemEntryViewModel(provider, factory, mediator, publisher, subscriber, disposer, state, configuration, key, value);
public partial class ItemDropdownEntryViewModel :
ItemEntryCollectionViewModel<ItemDropdownValueViewModel>
{
public ItemDropdownEntryViewModel(IServiceProvider provider,
IServiceFactory factory,
IMediator mediator,
IPublisher publisher,
ISubscription subscriber,
IDisposer disposer,
IEnumerable<ItemDropdownValueViewModel> items,
ItemState state,
ItemEntryConfiguration configuration,
string key,
object value,
ItemDropdownValueViewModel selectedItem) : base(provider, factory, mediator, publisher, subscriber, disposer, items, state, configuration, key, value)
{
SelectedItem = selectedItem;
}
public ItemDropdownEntryViewModel(IServiceProvider provider,
IServiceFactory factory,
IMediator mediator,
IPublisher publisher,
ISubscription subscriber,
IDisposer disposer,
IEnumerable<ItemDropdownValueViewModel> items,
ItemState state,
ItemEntryConfiguration configuration,
string key,
object value) : base(provider, factory, mediator, publisher, subscriber, disposer, items, state, configuration, key, value)
{
}
}
+12 -1
View File
@@ -10,7 +10,18 @@ public class ItemDropdownEntryViewModelHandler(IServiceFactory serviceFactory) :
{
if (args.Value is DropdownEntryConfiguration configuration)
{
if (serviceFactory.Create<ItemDropdownEntryViewModel>([.. args.Parameters, configuration, configuration.Label, configuration.Value ?? ""])
List<ItemDropdownValueViewModel> values = [];
foreach (string item in configuration.Values)
{
values.Add(serviceFactory.Create<ItemDropdownValueViewModel>(item));
}
string? label = configuration.Label;
object? value = configuration.Value;
ItemDropdownValueViewModel? selected = values.FirstOrDefault(x => x.Value is not null && x.Value.Equals($"{value}"));
if (serviceFactory.Create<ItemDropdownEntryViewModel>([values, .. args.Parameters, configuration, label, value ?? "", selected])
is ItemDropdownEntryViewModel viewModel)
{
return Task.FromResult<IItemEntryViewModel?>(viewModel);
+11
View File
@@ -0,0 +1,11 @@
using Toolkit.Foundation;
namespace Bitvault;
public partial class ItemDropdownValueViewModel(IServiceProvider provider,
IServiceFactory factory,
IMediator mediator,
IPublisher publisher,
ISubscription subscriber,
IDisposer disposer,
string? value = null) : Observable<string>(provider, factory, mediator, publisher, subscriber, disposer, value);
+77
View File
@@ -0,0 +1,77 @@
using CommunityToolkit.Mvvm.ComponentModel;
using Toolkit.Foundation;
namespace Bitvault;
public partial class ItemEntryCollectionViewModel<TItem> :
ObservableCollection<TItem, string, object>,
IItemEntryViewModel,
INotificationHandler<UpdateEventArgs<Item>>,
INotificationHandler<ConfirmEventArgs<Item>>,
INotificationHandler<CancelEventArgs<Item>>
where TItem : notnull,
IDisposable
{
[ObservableProperty]
private ItemState state;
private readonly ItemEntryConfiguration configuration;
public ItemEntryCollectionViewModel(IServiceProvider provider,
IServiceFactory factory,
IMediator mediator,
IPublisher publisher,
ISubscription subscriber,
IDisposer disposer,
ItemState state,
ItemEntryConfiguration configuration,
string key,
object value) : base(provider, factory, mediator, publisher, subscriber, disposer, key, value)
{
this.configuration = configuration;
State = state;
}
public ItemEntryCollectionViewModel(IServiceProvider provider,
IServiceFactory factory,
IMediator mediator,
IPublisher publisher,
ISubscription subscriber,
IDisposer disposer,
IEnumerable<TItem> items,
ItemState state,
ItemEntryConfiguration configuration,
string key,
object value) : base(provider, factory, mediator, publisher, subscriber, disposer, items, key, value)
{
this.configuration = configuration;
State = state;
}
protected override void OnValueChanged()
{
if (configuration is not null)
{
configuration.Value = Value;
}
}
public Task Handle(UpdateEventArgs<Item> args) =>
Task.FromResult(State = ItemState.Write);
public Task Handle(CancelEventArgs<Item> args)
{
Revert();
State = ItemState.Read;
return Task.CompletedTask;
}
public Task Handle(ConfirmEventArgs<Item> args)
{
Commit();
State = ItemState.Read;
return Task.CompletedTask;
}
}
+3 -3
View File
@@ -11,8 +11,8 @@ public partial class ItemEntryViewModel(IServiceProvider provider,
IDisposer disposer,
ItemState state,
ItemEntryConfiguration configuration,
string? key = default,
object? value = default) :
string key,
object value) :
Observable<string, object>(provider, factory, mediator, publisher, subscriber, disposer, key, value),
IItemEntryViewModel,
INotificationHandler<UpdateEventArgs<Item>>,
@@ -43,4 +43,4 @@ public partial class ItemEntryViewModel(IServiceProvider provider,
State = ItemState.Read;
return Task.CompletedTask;
}
}
}
+3 -2
View File
@@ -25,7 +25,8 @@ public partial class ItemHeaderViewModel :
ISubscription subscriber,
IDisposer disposer,
ItemState state,
string? value = null) : base(provider, factory, mediator, publisher, subscriber, disposer, value)
string key,
string value) : base(provider, factory, mediator, publisher, subscriber, disposer, key, value)
{
State = state;
Value = value;
@@ -68,6 +69,6 @@ public partial class ItemHeaderViewModel :
return Task.CompletedTask;
}
public Task<string?> Handle(ConfirmEventArgs<ItemHeader> args,
public Task<string> Handle(ConfirmEventArgs<ItemHeader> args,
CancellationToken cancellationToken) => Task.FromResult(Value);
}
+4 -4
View File
@@ -11,10 +11,10 @@ public partial class ItemMaskedTextEntryViewModel(IServiceProvider provider,
IDisposer disposer,
ItemState state,
ItemEntryConfiguration configuration,
string? pattern,
string? key = default,
object? value = default) : ItemEntryViewModel(provider, factory, mediator, publisher, subscriber, disposer, state, configuration, key, value)
string pattern,
string key,
object value) : ItemEntryViewModel(provider, factory, mediator, publisher, subscriber, disposer, state, configuration, key, value)
{
[ObservableProperty]
private string? pattern = pattern;
private string pattern = pattern;
}
+2 -2
View File
@@ -10,5 +10,5 @@ public partial class ItemPasswordEntryViewModel(IServiceProvider provider,
IDisposer disposer,
ItemState state,
ItemEntryConfiguration configuration,
string? key = default,
object? value = default) : ItemEntryViewModel(provider, factory, mediator, publisher, subscriber, disposer, state, configuration, key, value);
string key,
object value) : ItemEntryViewModel(provider, factory, mediator, publisher, subscriber, disposer, state, configuration, key, value);
+2 -2
View File
@@ -10,5 +10,5 @@ public partial class ItemTextEntryViewModel(IServiceProvider provider,
IDisposer disposer,
ItemState state,
ItemEntryConfiguration configuration,
string? key = default,
object? value = default) : ItemEntryViewModel(provider, factory, mediator, publisher, subscriber, disposer, state, configuration, key, value);
string key,
object value) : ItemEntryViewModel(provider, factory, mediator, publisher, subscriber, disposer, state, configuration, key, value);
+1 -1
View File
@@ -49,7 +49,7 @@ public partial class ItemViewModel :
Archived = archived;
Name = name;
Add<ItemHeaderViewModel>(name, state);
Add<ItemHeaderViewModel>("", name, state);
Add<ItemContentViewModel>();
}