Main page now uses Frame to change views when selecting items

Backgrounds unified
Menu items can be disabled thanks to custom ListView control
This commit is contained in:
2017-09-27 18:01:21 +02:00
committed by BONNEVILLE Geoffroy
parent 3a045dbb16
commit caaf34918e
19 changed files with 319 additions and 138 deletions

View File

@@ -60,7 +60,11 @@ namespace ModernKeePass.Common
public void Save()
{
_pwDatabase.Save(new NullStatusLogger());
//_pwDatabase.Close();
}
public void Close()
{
_pwDatabase.Close();
}
}
}

View File

@@ -0,0 +1,20 @@
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using ModernKeePass.Interfaces;
namespace ModernKeePass.Controls
{
public class ListViewWithDisable: ListView
{
protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
{
base.PrepareContainerForItemOverride(element, item);
var container = element as ListViewItem;
var binaryItem = item as IIsEnabled;
if (container == null || binaryItem == null) return;
container.IsEnabled = binaryItem.IsEnabled;
container.IsHitTestVisible = binaryItem.IsEnabled;
}
}
}

View File

@@ -0,0 +1,7 @@
namespace ModernKeePass.Interfaces
{
public interface IIsEnabled
{
bool IsEnabled { get; }
}
}

View File

@@ -1,62 +1,46 @@
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:ModernKeePass"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewModels="using:ModernKeePass.ViewModels"
xmlns:viewModels="using:ModernKeePass.ViewModels"
xmlns:controls="using:ModernKeePass.Controls"
x:Class="ModernKeePass.MainPage"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" >
<Page.DataContext>
<viewModels:HomeVm/>
<viewModels:MainVm />
</Page.DataContext>
<Page.Resources>
<CollectionViewSource
x:Name="MenuItemsSource"
Source="{Binding MainMenuItems}" />
</Page.Resources>
<Grid HorizontalAlignment="Left" VerticalAlignment="Top" Margin="25,25,0,0" >
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="50" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ListView Grid.Column="0" SelectionChanged="ListView_SelectionChanged">
<controls:ListViewWithDisable Grid.Column="0"
x:Name="MenuListView"
SelectionChanged="ListView_SelectionChanged"
ItemsSource="{Binding Source={StaticResource MenuItemsSource}}">
<ListView.Header>
<TextBlock Text="ModernKeePass" FontWeight="Bold" FontSize="36" />
<TextBlock Text="ModernKeePass" FontWeight="Bold" FontSize="36" Margin="20" />
</ListView.Header>
<ListView.ItemTemplate >
<DataTemplate>
<TextBlock Text="{Binding}" />
<ListView.ItemTemplate>
<DataTemplate >
<TextBlock Text="{Binding Title}" />
</DataTemplate>
</ListView.ItemTemplate>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Padding" Value="10,5,0,0" />
<Setter Property="Padding" Value="20,5,0,0" />
</Style>
</ListView.ItemContainerStyle>
<ListView.Items>
<ListViewItem Name="SaveItem">Save</ListViewItem>
<ListViewItem Name="NewItem">New</ListViewItem>
<ListViewItem Name="SelectItem">File</ListViewItem>
<ListViewItem Name="RecentItem">Recent files - Coming soon</ListViewItem>
<ListViewItem Name="UrlItem">Url files - Coming soon</ListViewItem>
</ListView.Items>
</ListView>
<Grid Name="SelectGrid" Grid.Column="2" HorizontalAlignment="Left" Height="auto" VerticalAlignment="Top" Width="auto" Margin="0,30,0,0" Visibility="Collapsed" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="150" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<HyperlinkButton Grid.Row="0" Grid.ColumnSpan="2" Content="Select password database" Click="Button_Click" />
<TextBlock Grid.Column="0" Grid.Row="1" x:Name="PasswordTextBlock" HorizontalAlignment="Left" Visibility="{Binding Visibility}" TextWrapping="Wrap" Text="Password" VerticalAlignment="Center" Height="auto" Width="auto" FontSize="16" Margin="10,7,0,6" />
<PasswordBox Grid.Column="1" Grid.Row="1" x:Name="PasswordBox" VerticalAlignment="Top" HorizontalAlignment=" Right" Visibility="{Binding Visibility}" Width="130" Password="{Binding Password, Mode=TwoWay}" IsPasswordRevealButtonEnabled="True" Margin="0,0,10,0"/>
<TextBlock Grid.Column="1" Grid.Row="2" Text="{Binding ErrorMessage}" Foreground="#FF9E1B1B" />
<Button Grid.Column="1" Grid.Row="3" x:Name="OpenButton" Content="OK" HorizontalAlignment="Right" VerticalAlignment="Top" Visibility="{Binding Visibility}" Click="openBbutton_Click" Margin="0,0,7,0" Width="auto"/>
</Grid>
<HyperlinkButton Grid.Column="2" Name="SaveButton" Content="Save file" Click="saveBbutton_Click" VerticalAlignment="Top" Margin="0,30,0,0" Visibility="Collapsed" IsEnabled="{Binding IsOpen}" />
</controls:ListViewWithDisable>
<Frame Grid.Column="2" Name="MenuFrame" Width="auto" Margin="0,60,0,0" />
</Grid>
</Page>

View File

@@ -1,7 +1,6 @@
using System;
using Windows.UI.Xaml;
using System.Collections.ObjectModel;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using ModernKeePass.Models;
using ModernKeePass.Pages;
using ModernKeePass.ViewModels;
@@ -17,70 +16,26 @@ namespace ModernKeePass
public MainPage()
{
InitializeComponent();
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
var picker = new Windows.Storage.Pickers.FileOpenPicker();
picker.ViewMode = Windows.Storage.Pickers.PickerViewMode.List;
picker.SuggestedStartLocation =
Windows.Storage.Pickers.PickerLocationId.DocumentsLibrary;
picker.FileTypeFilter.Add(".kdbx");
var file = await picker.PickSingleFileAsync();
if (file != null)
var mainMenuItems = new ObservableCollection<MainMenuItem>
{
// Application now has read/write access to the picked file
//DataContext = new DatabaseVm(file);
((App)Application.Current).Database = new Common.DatabaseHelper(file);
var homeVm = DataContext as HomeVm;
homeVm.Visibility = Visibility.Visible;
homeVm.NotifyPropertyChanged("Visibility");
}
new MainMenuItem {Title = "File", PageType = typeof(OpenDatabasePage)},
new MainMenuItem {Title = "New" /*, PageType = typeof(NewDatabasePage)*/},
new MainMenuItem {Title = "Save" , PageType = typeof(SaveDatabasePage)},
new MainMenuItem {Title = "Recent files - Coming soon" /*, PageType = typeof(RecentDatabasesPage)*/},
new MainMenuItem {Title = "Url files - Coming soon" /*, PageType = typeof(OpenUrlPage)*/}
};
DataContext = new MainVm {MainMenuItems = mainMenuItems};
MenuListView.SelectedIndex = -1;
}
private void openBbutton_Click(object sender, RoutedEventArgs e)
{
/*var database = DataContext as DatabaseVm;
database.Open();
if (database.IsOpen)
Frame.Navigate(typeof(GroupDetailPage), database.RootGroup);*/
var homeVm = DataContext as HomeVm;
var app = ((App)Application.Current);
homeVm.ErrorMessage = app.Database.Open(homeVm.Password);
if (!string.IsNullOrEmpty(homeVm.ErrorMessage)) homeVm.NotifyPropertyChanged("ErrorMessage");
else Frame.Navigate(typeof(GroupDetailPage), app.Database.RootGroup);
}
private void saveBbutton_Click(object sender, RoutedEventArgs e)
{
var database = DataContext as HomeVm;
((App)Application.Current).Database.Save();
}
private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (e.AddedItems.Contains(SelectItem) || e.AddedItems.Contains(NewItem))
{
SelectGrid.Visibility = Visibility.Visible;
SaveButton.Visibility = Visibility.Collapsed;
}
else if (e.AddedItems.Contains(SaveItem))
{
SaveButton.Visibility = Visibility.Visible;
SelectGrid.Visibility = Visibility.Collapsed;
}
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
var app = (App)Application.Current;
if (app.Database == null) return;
var homeVm = DataContext as HomeVm;
homeVm.IsOpen = app.Database.IsOpen;
homeVm.NotifyPropertyChanged("IsOpen");
if (Frame == null) return;
var listView = sender as ListView;
if (listView == null) return;
if (listView.SelectedIndex == -1) return;
var selectedItem = listView.SelectedItem as MainMenuItem;
if (selectedItem != null) MenuFrame.Navigate(selectedItem.PageType, Frame);
}
}
}

View File

@@ -0,0 +1,17 @@
using System;
using ModernKeePass.Interfaces;
namespace ModernKeePass.Models
{
public class MainMenuItem: IIsEnabled
{
public string Title { get; set; }
public Type PageType { get; set; }
public bool IsEnabled => PageType != null;
public override string ToString()
{
return Title;
}
}
}

View File

@@ -115,19 +115,29 @@
<Compile Include="Common\ObservableDictionary.cs" />
<Compile Include="Common\RelayCommand.cs" />
<Compile Include="Common\SuspensionManager.cs" />
<Compile Include="Controls\ListViewWithDisable.cs" />
<Compile Include="Interfaces\IIsEnabled.cs" />
<Compile Include="MainPage.xaml.cs">
<DependentUpon>MainPage.xaml</DependentUpon>
</Compile>
<Compile Include="Models\MainMenuItem.cs" />
<Compile Include="Pages\EntryDetailPage.xaml.cs">
<DependentUpon>EntryDetailPage.xaml</DependentUpon>
</Compile>
<Compile Include="Pages\GroupDetailPage.xaml.cs">
<DependentUpon>GroupDetailPage.xaml</DependentUpon>
</Compile>
<Compile Include="Pages\OpenDatabasePage.xaml.cs">
<DependentUpon>OpenDatabasePage.xaml</DependentUpon>
</Compile>
<Compile Include="Pages\SaveDatabasePage.xaml.cs">
<DependentUpon>SaveDatabasePage.xaml</DependentUpon>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ViewModels\HomeVm.cs" />
<Compile Include="ViewModels\DatabaseVm.cs" />
<Compile Include="ViewModels\EntryVm.cs" />
<Compile Include="ViewModels\GroupVm.cs" />
<Compile Include="ViewModels\MainVm.cs" />
</ItemGroup>
<ItemGroup>
<AppxManifest Include="Package.appxmanifest">
@@ -157,13 +167,21 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Pages\OpenDatabasePage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Pages\SaveDatabasePage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Reference Include="BouncyCastle.Crypto, Version=1.8.1.0, Culture=neutral, PublicKeyToken=0e99375e54769942, processorArchitecture=MSIL">
<HintPath>..\packages\Portable.BouncyCastle.1.8.1.3\lib\netstandard1.0\BouncyCastle.Crypto.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="ModernKeePassLib, Version=2.28.1.30896, Culture=neutral, processorArchitecture=MSIL">
<Reference Include="ModernKeePassLib, Version=2.28.1.27501, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ModernKeePassLib.2.28.3000\lib\netstandard1.2\ModernKeePassLib.dll</HintPath>
<Private>True</Private>
</Reference>

View File

@@ -0,0 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">CSharp70</s:String></wpf:ResourceDictionary>

View File

@@ -37,6 +37,7 @@
x:Name="groupsGridView"
AutomationProperties.AutomationId="ItemGridView"
AutomationProperties.Name="Groups"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
TabIndex="1"
Grid.RowSpan="2"
Padding="120,126,120,50"

View File

@@ -59,13 +59,11 @@ namespace ModernKeePass.Pages
protected override void OnNavigatedTo(NavigationEventArgs e)
{
navigationHelper.OnNavigatedTo(e);
if (e.Parameter is GroupVm)
{
DataContext = e.Parameter as GroupVm;
groupsGridView.SelectedIndex = -1;
entriesListView.SelectedIndex = -1;
}
if (!(e.Parameter is GroupVm)) return;
DataContext = (GroupVm) e.Parameter;
groupsGridView.SelectedIndex = -1;
entriesListView.SelectedIndex = -1;
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
@@ -78,14 +76,14 @@ namespace ModernKeePass.Pages
private void groupsGridView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var gridView = sender as GridView;
Frame.Navigate(typeof(GroupDetailPage), gridView.SelectedItem as GroupVm);
Frame.Navigate(typeof(GroupDetailPage), gridView?.SelectedItem as GroupVm);
}
private void entriesListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var listView = sender as ListView;
Frame.Navigate(typeof(EntryDetailPage), listView.SelectedItem as EntryVm);
Frame.Navigate(typeof(EntryDetailPage), listView?.SelectedItem as EntryVm);
}
}
}

View File

@@ -0,0 +1,37 @@
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
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"
x:Class="ModernKeePass.Pages.OpenDatabasePage"
mc:Ignorable="d">
<Page.DataContext>
<viewModels:DatabaseVm/>
</Page.DataContext>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.ChildrenTransitions>
<TransitionCollection>
<EntranceThemeTransition/>
</TransitionCollection>
</Grid.ChildrenTransitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<HyperlinkButton Grid.Row="0" Grid.ColumnSpan="2" Content="Browse files..." Click="ButtonBase_OnClick" />
<TextBlock Grid.Column="1" Grid.Row="0" HorizontalAlignment="Left" Visibility="{Binding SelectedVisibility}" TextWrapping="Wrap" Text="{Binding Name}" VerticalAlignment="Center" Height="auto" Width="auto" FontSize="16" Margin="10,7,0,6" />
<TextBlock Grid.Column="0" Grid.Row="2" HorizontalAlignment="Left" Visibility="{Binding SelectedVisibility}" TextWrapping="Wrap" Text="Password" VerticalAlignment="Center" Height="auto" Width="auto" FontSize="16" Margin="10,7,0,6" />
<PasswordBox Grid.Column="1" Grid.Row="2" x:Name="PasswordBox" VerticalAlignment="Top" HorizontalAlignment=" Right" Visibility="{Binding SelectedVisibility}" Width="500" IsPasswordRevealButtonEnabled="True" Margin="0,0,10,0"/>
<TextBlock Grid.Column="1" Grid.Row="3" x:Name="StatusTextBlock" Visibility="{Binding SelectedVisibility}" Height="auto" Width="auto" Foreground="#FF9E1B1B" FontSize="16" />
<Button Grid.Column="1" Grid.Row="4" Content="OK" Visibility="{Binding SelectedVisibility}" HorizontalAlignment="Right" VerticalAlignment="Top" Click="OpenButton_OnClick" Margin="0,0,7,0" Width="auto"/>
</Grid>
</Page>

View File

@@ -0,0 +1,61 @@
using System;
using Windows.Storage.Pickers;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using ModernKeePass.Common;
using ModernKeePass.ViewModels;
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
namespace ModernKeePass.Pages
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class OpenDatabasePage : Page
{
private Frame _mainFrame;
public OpenDatabasePage()
{
InitializeComponent();
DataContext = new DatabaseVm();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
_mainFrame = e.Parameter as Frame;
}
private async void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
var picker =
new FileOpenPicker
{
ViewMode = PickerViewMode.List,
SuggestedStartLocation = PickerLocationId.DocumentsLibrary
};
picker.FileTypeFilter.Add(".kdbx");
var file = await picker.PickSingleFileAsync();
if (file == null) return;
// Application now has read/write access to the picked file
((App)Application.Current).Database = new DatabaseHelper(file);
var databaseVm = DataContext as DatabaseVm;
if (databaseVm == null) return;
databaseVm.SelectedVisibility = Visibility.Visible;
databaseVm.Name = file.Name;
databaseVm.NotifyPropertyChanged("SelectedVisibility");
databaseVm.NotifyPropertyChanged("Name");
}
private void OpenButton_OnClick(object sender, RoutedEventArgs e)
{
var app = (App)Application.Current;
StatusTextBlock.Text = app.Database.Open(PasswordBox.Password);
if (string.IsNullOrEmpty(StatusTextBlock.Text)) _mainFrame.Navigate(typeof(GroupDetailPage), app.Database.RootGroup);
}
}
}

View File

@@ -0,0 +1,28 @@
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
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"
x:Class="ModernKeePass.Pages.SaveDatabasePage"
mc:Ignorable="d">
<Page.DataContext>
<viewModels:DatabaseVm/>
</Page.DataContext>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.ChildrenTransitions>
<TransitionCollection>
<EntranceThemeTransition/>
</TransitionCollection>
</Grid.ChildrenTransitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<HyperlinkButton Grid.Row="0" x:Name="SaveButton" Content="Save and close" Click="SaveButton_OnClick" VerticalAlignment="Top" IsEnabled="{Binding IsOpen}" />
<HyperlinkButton Grid.Row="1" x:Name="SaveAsButton" Content="Save as..." VerticalAlignment="Top" IsEnabled="{Binding IsOpen}" />
</Grid>
</Page>

View File

@@ -0,0 +1,39 @@
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using ModernKeePass.ViewModels;
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
namespace ModernKeePass.Pages
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class SaveDatabasePage : Page
{
public SaveDatabasePage()
{
this.InitializeComponent();
DataContext = new DatabaseVm();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
var app = (App)Application.Current;
if (app.Database == null) return;
var databaseVm = DataContext as DatabaseVm;
if (databaseVm == null) return;
databaseVm.IsOpen = app.Database.IsOpen;
databaseVm.NotifyPropertyChanged("IsOpen");
}
private void SaveButton_OnClick(object sender, RoutedEventArgs e)
{
var app = (App) Application.Current;
app.Database.Save();
app.Database.Close();
}
}
}

View File

@@ -6,9 +6,9 @@ using System.Runtime.InteropServices;
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("ModernKeePass")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyDescription("A port of KeePass 2.x to Modern UI as a Windows Store application")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyCompany("wismna")]
[assembly: AssemblyProduct("ModernKeePass")]
[assembly: AssemblyCopyright("Copyright © 2017")]
[assembly: AssemblyTrademark("")]

View File

@@ -0,0 +1,25 @@
using System;
using System.ComponentModel;
using Windows.UI.Xaml;
namespace ModernKeePass.ViewModels
{
public class DatabaseVm : INotifyPropertyChanged
{
private string _name;
public Visibility SelectedVisibility { get; set; } = Visibility.Collapsed;
public bool IsOpen { get; set; }
public string Name {
get { return string.IsNullOrEmpty(_name) ? string.Empty : $"Database {_name} selected"; }
set { _name = value; }
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}

View File

@@ -59,8 +59,7 @@ namespace ModernKeePass.ViewModels
Entries.Add(new EntryVm(pwEntry));
NotifyPropertyChanged("Entries");
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propertyName)

View File

@@ -1,24 +0,0 @@
using System.ComponentModel;
using Windows.UI.Xaml;
namespace ModernKeePass.ViewModels
{
public class HomeVm : INotifyPropertyChanged
{
public string Password { get; set; }
public Visibility Visibility { get; set; }
public string ErrorMessage { get; set; }
public bool IsOpen { get; set; }
public HomeVm()
{
Visibility = Visibility.Collapsed;
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}

View File

@@ -0,0 +1,10 @@
using System.Collections.ObjectModel;
using ModernKeePass.Models;
namespace ModernKeePass.ViewModels
{
public class MainVm
{
public ObservableCollection<MainMenuItem> MainMenuItems { get; set; }
}
}