├── .gitattributes ├── .github └── workflows │ └── vale.yml ├── .gitignore ├── CS ├── MVVMExpenses.sln └── MVVMExpenses │ ├── App.config │ ├── Common │ ├── AppIcon.ico │ ├── CommonResources.Designer.cs │ ├── CommonResources.resx │ ├── DataModel │ │ ├── DbExceptions.cs │ │ ├── EntityFramework │ │ │ ├── DbConnectionFactory.cs │ │ │ ├── DbExceptionsConverter.cs │ │ │ ├── DbReadOnlyRepository.cs │ │ │ ├── DbRepository.cs │ │ │ ├── DbUnitOfWork.cs │ │ │ ├── DbUnitOfWorkFactory.cs │ │ │ └── InstantFeedbackSource.cs │ │ ├── EntityState.cs │ │ ├── IReadOnlyRepository.cs │ │ ├── IRepository.cs │ │ ├── IUnitOfWork.cs │ │ └── UnitOfWorkBase.cs │ ├── Utils │ │ ├── DbExtensions.cs │ │ └── ExpressionHelper.cs │ └── ViewModel │ │ ├── CollectionViewModel.cs │ │ ├── DocumentsViewModel.cs │ │ ├── EntitiesViewModel.cs │ │ ├── ISingleObjectViewModel.cs │ │ ├── InstantFeedbackCollectionViewModel.cs │ │ ├── LayoutSettings.Designer.cs │ │ ├── LayoutSettings.settings │ │ ├── LookUpEntitiesViewModel.cs │ │ ├── Messages.cs │ │ ├── PeekCollectionViewModel.cs │ │ ├── ReadOnlyCollectionViewModel.cs │ │ ├── SingleObjectViewModel.cs │ │ └── ViewModelLogicalLayoutHelper.cs │ ├── Data │ └── Expenses.sqlite3 │ ├── DataBase │ ├── DataDirectoryHelper.cs │ └── DbContext.cs │ ├── MVVMExpenses.csproj │ ├── Models │ ├── Account.cs │ ├── Category.cs │ ├── CredentialsSource.cs │ ├── MyDbContextDataModel │ │ ├── IMyDbContextUnitOfWork.cs │ │ ├── MyDbContextUnitOfWork.cs │ │ └── UnitOfWorkSource.cs │ ├── Transaction.cs │ └── User.cs │ ├── Program.cs │ ├── Properties │ ├── AssemblyInfo.cs │ ├── DataSources │ │ ├── MVVMExpenses.DataModels.Account.datasource │ │ ├── MVVMExpenses.DataModels.Category.datasource │ │ ├── MVVMExpenses.DataModels.Transaction.datasource │ │ └── MVVMExpenses.Models.SampleUserList.datasource │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings │ ├── ViewModels │ ├── Account │ │ ├── AccountCollectionViewModel.cs │ │ └── AccountViewModel.cs │ ├── Category │ │ ├── CategoryCollectionViewModel.cs │ │ └── CategoryViewModel.cs │ ├── LoginViewModel.cs │ ├── MyDbContextViewModel.cs │ ├── MyDbContextViewModel.partial.cs │ └── Transaction │ │ ├── TransactionCollectionViewModel.cs │ │ └── TransactionViewModel.cs │ ├── Views │ ├── Account │ │ ├── AccountsEditFormView.Designer.cs │ │ ├── AccountsEditFormView.cs │ │ ├── AccountsEditFormView.resx │ │ ├── AccountsView.Designer.cs │ │ ├── AccountsView.cs │ │ └── AccountsView.resx │ ├── Category │ │ ├── CategoriesEditFormView.Designer.cs │ │ ├── CategoriesEditFormView.cs │ │ ├── CategoriesEditFormView.resx │ │ ├── CategoriesView.Designer.cs │ │ ├── CategoriesView.cs │ │ └── CategoriesView.resx │ ├── LoginView.Designer.cs │ ├── LoginView.cs │ ├── LoginView.resx │ ├── MainView.Designer.cs │ ├── MainView.cs │ ├── MainView.resx │ └── Transaction │ │ ├── TransactionsEditFormView.Designer.cs │ │ ├── TransactionsEditFormView.cs │ │ ├── TransactionsEditFormView.resx │ │ ├── TransactionsView.Designer.cs │ │ ├── TransactionsView.cs │ │ └── TransactionsView.resx │ ├── packages.config │ └── sqlite │ ├── System.Data.SQLite.EF6.dll │ └── System.Data.SQLite.dll ├── LICENSE ├── Readme.md ├── VB ├── MVVMExpenses.sln └── MVVMExpenses │ ├── AppIcon.ico │ ├── Common │ ├── AppIcon.ico │ ├── CommonResources.Designer.vb │ ├── CommonResources.resx │ ├── DataModel │ │ ├── DbExceptions.vb │ │ ├── EntityFramework │ │ │ ├── DbExceptionsConverter.vb │ │ │ ├── DbReadOnlyRepository.vb │ │ │ ├── DbRepository.vb │ │ │ ├── DbUnitOfWork.vb │ │ │ ├── DbUnitOfWorkFactory.vb │ │ │ └── InstantFeedbackSource.vb │ │ ├── EntityState.vb │ │ ├── IReadOnlyRepository.vb │ │ ├── IRepository.vb │ │ ├── IUnitOfWork.vb │ │ └── UnitOfWorkBase.vb │ ├── Utils │ │ ├── DbExtensions.vb │ │ └── ExpressionHelper.vb │ └── ViewModel │ │ ├── CollectionViewModel.vb │ │ ├── DocumentsViewModel.vb │ │ ├── EntitiesViewModel.vb │ │ ├── ISingleObjectViewModel.vb │ │ ├── InstantFeedbackCollectionViewModel.vb │ │ ├── LayoutSettings.Designer.vb │ │ ├── LayoutSettings.settings │ │ ├── LookUpEntitiesViewModel.vb │ │ ├── Messages.vb │ │ ├── PeekCollectionViewModel.vb │ │ ├── ReadOnlyCollectionViewModel.vb │ │ ├── SingleObjectViewModel.vb │ │ └── ViewModelLogicalLayoutHelper.vb │ ├── Data │ └── Expenses.sqlite3 │ ├── DataBase │ ├── DataDirectoryHelper.vb │ ├── DbContext.vb │ └── MyDbSQLiteConfiguration.vb │ ├── MVVMExpenses.vbproj │ ├── Models │ ├── Account.vb │ ├── Category.vb │ ├── CredentialsSource.vb │ ├── MyDbContextDataModel │ │ ├── IMyDbContextUnitOfWork.vb │ │ ├── MyDbContextUnitOfWork.vb │ │ └── UnitOfWorkSource.vb │ ├── Transaction.vb │ └── User.vb │ ├── My Project │ ├── AssemblyInfo.vb │ ├── DataSources │ │ ├── MVVMExpenses.DataModels.Account.datasource │ │ ├── MVVMExpenses.DataModels.Category.datasource │ │ └── MVVMExpenses.DataModels.Transaction.datasource │ ├── Resources.Designer.vb │ ├── Resources.resx │ ├── Settings.Designer.vb │ └── Settings.settings │ ├── Program.vb │ ├── ViewModels │ ├── Account │ │ ├── AccountCollectionViewModel.vb │ │ └── AccountViewModel.vb │ ├── Category │ │ ├── CategoryCollectionViewModel.vb │ │ └── CategoryViewModel.vb │ ├── LoginViewModel.vb │ ├── MyDbContextViewModel.partial.vb │ ├── MyDbContextViewModel.vb │ └── Transaction │ │ ├── TransactionCollectionViewModel.vb │ │ └── TransactionViewModel.vb │ ├── Views │ ├── Account │ │ ├── AccountsEditFormView.Designer.vb │ │ ├── AccountsEditFormView.resx │ │ ├── AccountsEditFormView.vb │ │ ├── AccountsView.Designer.vb │ │ ├── AccountsView.resx │ │ └── AccountsView.vb │ ├── Category │ │ ├── CategoriesEditFormView.Designer.vb │ │ ├── CategoriesEditFormView.resx │ │ ├── CategoriesEditFormView.vb │ │ ├── CategoriesView.Designer.vb │ │ ├── CategoriesView.resx │ │ └── CategoriesView.vb │ ├── LoginView.Designer.vb │ ├── LoginView.resx │ ├── LoginView.vb │ ├── MainView.Designer.vb │ ├── MainView.resx │ ├── MainView.vb │ └── Transaction │ │ ├── TransactionsEditFormView.Designer.vb │ │ ├── TransactionsEditFormView.resx │ │ ├── TransactionsEditFormView.vb │ │ ├── TransactionsView.Designer.vb │ │ ├── TransactionsView.resx │ │ └── TransactionsView.vb │ ├── app.config │ ├── packages.config │ └── sqlite │ ├── System.Data.SQLite.EF6.dll │ └── System.Data.SQLite.dll └── config.json /.gitattributes: -------------------------------------------------------------------------------- 1 | VB/* linguist-vendored 2 | scripts linguist-vendored 3 | *.css linguist-detectable=false 4 | *.aff linguist-detectable=false -------------------------------------------------------------------------------- /.github/workflows/vale.yml: -------------------------------------------------------------------------------- 1 | name: vale-validation 2 | on: 3 | pull_request: 4 | paths: 5 | - README.md 6 | - readme.md 7 | - Readme.md 8 | 9 | jobs: 10 | vale: 11 | name: runner / vale 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: clone repo 15 | uses: actions/checkout@v4 16 | - name: clone vale-styles repo 17 | uses: actions/checkout@v4 18 | with: 19 | repository: DevExpress/vale-styles 20 | path: vale-styles 21 | ssh-key: ${{ secrets.VALE_STYLES_ACCESS_KEY }} 22 | - name: copy vale rules to the root repo 23 | run: shopt -s dotglob && cp -r ./vale-styles/vale/* . 24 | - name: vale linter check 25 | uses: DevExpress/vale-action@reviewdog 26 | with: 27 | files: '["README.md", "readme.md", "Readme.md"]' 28 | fail_on_error: true 29 | filter_mode: nofilter 30 | reporter: github-check 31 | -------------------------------------------------------------------------------- /CS/MVVMExpenses.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio 14 3 | VisualStudioVersion = 14.0.23107.0 4 | MinimumVisualStudioVersion = 10.0.40219.1 5 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MVVMExpenses", "MVVMExpenses\MVVMExpenses.csproj", "{E7AE86FF-3BDC-43E1-A33A-63A6970D3670}" 6 | EndProject 7 | Global 8 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 9 | Debug|Any CPU = Debug|Any CPU 10 | Debug|x86 = Debug|x86 11 | Release|Any CPU = Release|Any CPU 12 | Release|x86 = Release|x86 13 | EndGlobalSection 14 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 15 | {E7AE86FF-3BDC-43E1-A33A-63A6970D3670}.Debug|Any CPU.ActiveCfg = Debug|x86 16 | {E7AE86FF-3BDC-43E1-A33A-63A6970D3670}.Debug|Any CPU.Build.0 = Debug|x86 17 | {E7AE86FF-3BDC-43E1-A33A-63A6970D3670}.Debug|x86.ActiveCfg = Debug|x86 18 | {E7AE86FF-3BDC-43E1-A33A-63A6970D3670}.Debug|x86.Build.0 = Debug|x86 19 | {E7AE86FF-3BDC-43E1-A33A-63A6970D3670}.Release|Any CPU.ActiveCfg = Release|Any CPU 20 | {E7AE86FF-3BDC-43E1-A33A-63A6970D3670}.Release|Any CPU.Build.0 = Release|Any CPU 21 | {E7AE86FF-3BDC-43E1-A33A-63A6970D3670}.Release|x86.ActiveCfg = Release|x86 22 | {E7AE86FF-3BDC-43E1-A33A-63A6970D3670}.Release|x86.Build.0 = Release|x86 23 | EndGlobalSection 24 | GlobalSection(SolutionProperties) = preSolution 25 | HideSolutionNode = FALSE 26 | EndGlobalSection 27 | EndGlobal 28 | -------------------------------------------------------------------------------- /CS/MVVMExpenses/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 | 10 | 11 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /CS/MVVMExpenses/Common/AppIcon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevExpress-Examples/winforms-mvvm-expenses-app/70a139e6d5909c97e63090201977325d1be58b9a/CS/MVVMExpenses/Common/AppIcon.ico -------------------------------------------------------------------------------- /CS/MVVMExpenses/Common/DataModel/DbExceptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | 4 | namespace MVVMExpenses.Common.DataModel { 5 | /// 6 | /// The database-independent exception used in Data Layer and View Model Layer to handle database errors. 7 | /// 8 | public class DbException : Exception { 9 | 10 | /// 11 | /// Initializes a new instance of the DbRepository class. 12 | /// 13 | /// An error message text. 14 | /// An error message caption text. 15 | /// An underlying exception. 16 | public DbException(string errorMessage, string errorCaption, Exception innerException) 17 | : base(innerException.Message, innerException) { 18 | ErrorMessage = errorMessage; 19 | ErrorCaption = errorCaption; 20 | } 21 | 22 | /// The error message text. 23 | public string ErrorMessage { get; private set; } 24 | 25 | /// The error message caption text. 26 | public string ErrorCaption { get; private set; } 27 | } 28 | } -------------------------------------------------------------------------------- /CS/MVVMExpenses/Common/DataModel/EntityFramework/DbConnectionFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Data.Common; 4 | using System.Data.SQLite; 5 | using System.Data.SQLite.EF6; 6 | using System.IO; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | //using DevExpress.DocumentServices.ServiceModel.DataContracts.Xpf.Designer; 11 | using DevExpress.Internal; 12 | 13 | namespace MVVMExpenses.Common.DataModel.EntityFramework { 14 | public class SQLiteConnectionFactory : System.Data.Entity.Infrastructure.IDbConnectionFactory { 15 | static string filePath; 16 | public DbConnection CreateConnection(string nameOrConnectionString) { 17 | if(filePath == null) { 18 | filePath = DataDirectoryHelper.GetFile("expenses.sqlite3", DataDirectoryHelper.DataFolderName); 19 | File.SetAttributes(filePath, File.GetAttributes(filePath) & ~FileAttributes.ReadOnly); 20 | } 21 | return new SQLiteConnection(new SQLiteConnectionStringBuilder { DataSource = filePath }.ConnectionString); 22 | } 23 | } 24 | public class MyDbSQLiteConfiguration : System.Data.Entity.DbConfiguration { 25 | public MyDbSQLiteConfiguration() { 26 | SetDefaultConnectionFactory(new SQLiteConnectionFactory()); 27 | SetProviderFactory("System.Data.SQLite", SQLiteFactory.Instance); 28 | SetProviderFactory("System.Data.SQLite.EF6", System.Data.SQLite.EF6.SQLiteProviderFactory.Instance); 29 | Type t = Type.GetType("System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6", true, true); 30 | System.Reflection.FieldInfo fi = t.GetField("Instance", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static); 31 | SetProviderServices("System.Data.SQLite", (System.Data.Entity.Core.Common.DbProviderServices)fi.GetValue(null)); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /CS/MVVMExpenses/Common/DataModel/EntityFramework/DbExceptionsConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Data.Entity.Infrastructure; 3 | using System.Data.Entity.Validation; 4 | using System.Linq; 5 | using System.Text; 6 | 7 | namespace MVVMExpenses.Common.DataModel.EntityFramework { 8 | /// 9 | /// Provides methods to convert Entity Framework exceptions to database-independent exceptions used in Data Layer and View Model Layer. 10 | /// 11 | public static class DbExceptionsConverter { 12 | 13 | /// 14 | /// Converts System.Data.Entity.Infrastructure.DbUpdateException exception to database-independent DbException exception used in Data Layer and View Model Layer. 15 | /// 16 | /// Exception to convert. 17 | public static DbException Convert(DbUpdateException exception) { 18 | Exception originalException = exception; 19 | while(originalException.InnerException != null) { 20 | originalException = originalException.InnerException; 21 | } 22 | return new DbException(originalException.Message, CommonResources.Exception_UpdateErrorCaption, exception); 23 | } 24 | 25 | /// 26 | /// Converts System.Data.Entity.Validation.DbEntityValidationException exception to database-independent DbException exception used in Data Layer and View Model Layer. 27 | /// 28 | /// Exception to convert. 29 | public static DbException Convert(DbEntityValidationException exception) { 30 | StringBuilder stringBuilder = new StringBuilder(); 31 | foreach(DbEntityValidationResult validationResult in exception.EntityValidationErrors) { 32 | foreach(DbValidationError error in validationResult.ValidationErrors) { 33 | if(stringBuilder.Length > 0) 34 | stringBuilder.AppendLine(); 35 | stringBuilder.Append(error.PropertyName + ": " + error.ErrorMessage); 36 | } 37 | } 38 | return new DbException(stringBuilder.ToString(), CommonResources.Exception_ValidationErrorCaption, exception); 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /CS/MVVMExpenses/Common/DataModel/EntityFramework/DbReadOnlyRepository.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Linq.Expressions; 4 | using System.Data.Entity; 5 | using System.Collections.Generic; 6 | using System.Collections.ObjectModel; 7 | 8 | namespace MVVMExpenses.Common.DataModel.EntityFramework { 9 | /// 10 | /// A DbReadOnlyRepository is a IReadOnlyRepository interface implementation representing the collection of all entities in the unit of work, or that can be queried from the database, of a given type. 11 | /// DbReadOnlyRepository objects are created from a DbUnitOfWork using the GetReadOnlyRepository method. 12 | /// DbReadOnlyRepository provides only read-only operations against entities of a given type. 13 | /// 14 | /// Repository entity type. 15 | /// DbContext type. 16 | public class DbReadOnlyRepository : DbRepositoryQuery, IReadOnlyRepository 17 | where TEntity : class 18 | where TDbContext : DbContext { 19 | 20 | readonly Func> dbSetAccessor; 21 | readonly DbUnitOfWork unitOfWork; 22 | 23 | /// 24 | /// Initializes a new instance of DbReadOnlyRepository class. 25 | /// 26 | /// Owner unit of work that provides context for repository entities. 27 | /// Function that returns DbSet entities from Entity Framework DbContext. 28 | public DbReadOnlyRepository(DbUnitOfWork unitOfWork, Func> dbSetAccessor) 29 | : base(() => dbSetAccessor(unitOfWork.Context)) { 30 | this.dbSetAccessor = dbSetAccessor; 31 | this.unitOfWork = unitOfWork; 32 | } 33 | 34 | protected DbSet DbSet { 35 | get { return dbSetAccessor(unitOfWork.Context); } 36 | } 37 | 38 | protected TDbContext Context { 39 | get { return unitOfWork.Context; } 40 | } 41 | 42 | #region IReadOnlyRepository 43 | IUnitOfWork IReadOnlyRepository.UnitOfWork { 44 | get { return unitOfWork; } 45 | } 46 | #endregion 47 | } 48 | 49 | /// 50 | /// DbRepositoryQuery is an IRepositoryQuery interface implementation that is an extension of IQueryable designed to specify the related objects to include in query results. 51 | /// 52 | /// An entity type. 53 | public class DbRepositoryQuery : RepositoryQueryBase, IRepositoryQuery where TEntity : class { 54 | 55 | /// 56 | /// Initializes a new instance of the DesignTimeRepositoryQuery class. 57 | /// 58 | /// A function that returns an IQueryable instance which is used by DbRepositoryQuery to perform queries. 59 | public DbRepositoryQuery(Func> getQueryable) 60 | : base(getQueryable) { } 61 | 62 | IRepositoryQuery IRepositoryQuery.Include(Expression> path) { 63 | return new DbRepositoryQuery(() => Queryable.Include(path)); 64 | } 65 | 66 | IRepositoryQuery IRepositoryQuery.Where(Expression> predicate) { 67 | return new DbRepositoryQuery(() => Queryable.Where(predicate)); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /CS/MVVMExpenses/Common/DataModel/EntityFramework/DbUnitOfWork.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Data.Entity; 4 | using System.Data.Entity.Validation; 5 | using System.Data.Entity.Infrastructure; 6 | using System.Linq; 7 | using System.Linq.Expressions; 8 | 9 | namespace MVVMExpenses.Common.DataModel.EntityFramework { 10 | /// 11 | /// A DbUnitOfWork instance represents the implementation of the Unit Of Work pattern 12 | /// such that it can be used to query from a database and group together changes that will then be written back to the store as a unit. 13 | /// 14 | /// DbContext type. 15 | public abstract class DbUnitOfWork : UnitOfWorkBase, IUnitOfWork where TContext : DbContext { 16 | 17 | readonly Lazy context; 18 | 19 | public DbUnitOfWork(Func contextFactory) { 20 | context = new Lazy(contextFactory); 21 | } 22 | 23 | /// 24 | /// Instance of underlying DbContext. 25 | /// 26 | public TContext Context { get { return context.Value; } } 27 | 28 | void IUnitOfWork.SaveChanges() { 29 | try { 30 | Context.SaveChanges(); 31 | } 32 | catch(DbEntityValidationException ex) { 33 | throw DbExceptionsConverter.Convert(ex); 34 | } 35 | catch(DbUpdateException ex) { 36 | throw DbExceptionsConverter.Convert(ex); 37 | } 38 | } 39 | 40 | bool IUnitOfWork.HasChanges() { 41 | return Context.ChangeTracker.HasChanges(); 42 | } 43 | 44 | protected IRepository 45 | GetRepository(Func> dbSetAccessor, Expression> getPrimaryKeyExpression) 46 | where TEntity : class { 47 | return GetRepositoryCore, TEntity>(() => new DbRepository(this, dbSetAccessor, getPrimaryKeyExpression)); 48 | } 49 | 50 | protected IReadOnlyRepository 51 | GetReadOnlyRepository(Func> dbSetAccessor) 52 | where TEntity : class { 53 | return GetRepositoryCore, TEntity>(() => new DbReadOnlyRepository(this, dbSetAccessor)); 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /CS/MVVMExpenses/Common/DataModel/EntityFramework/DbUnitOfWorkFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Data; 4 | using System.Data.Entity; 5 | using System.Linq.Expressions; 6 | using System.Collections.Generic; 7 | using MVVMExpenses.Common.Utils; 8 | using MVVMExpenses.Common.DataModel; 9 | using DevExpress.Mvvm; 10 | using System.Collections; 11 | using System.ComponentModel; 12 | using DevExpress.Data.Linq; 13 | using DevExpress.Data.Linq.Helpers; 14 | using DevExpress.Data.Async.Helpers; 15 | 16 | namespace MVVMExpenses.Common.DataModel.EntityFramework { 17 | class DbUnitOfWorkFactory : IUnitOfWorkFactory where TUnitOfWork : IUnitOfWork { 18 | Func createUnitOfWork; 19 | 20 | public DbUnitOfWorkFactory(Func createUnitOfWork) { 21 | this.createUnitOfWork = createUnitOfWork; 22 | } 23 | 24 | TUnitOfWork IUnitOfWorkFactory.CreateUnitOfWork() { 25 | return createUnitOfWork(); 26 | } 27 | 28 | IInstantFeedbackSource IUnitOfWorkFactory.CreateInstantFeedbackSource( 29 | Func> getRepositoryFunc, 30 | Func, IQueryable> projection) { 31 | var threadSafeProperties = new TypeInfoProxied(TypeDescriptor.GetProperties(typeof(TProjection)), null).UIDescriptors; 32 | if(projection == null) { 33 | projection = x => x as IQueryable; 34 | } 35 | var source = new EntityInstantFeedbackSource((GetQueryableEventArgs e) => e.QueryableSource = projection(getRepositoryFunc(createUnitOfWork()))) { 36 | KeyExpression = getRepositoryFunc(createUnitOfWork()).GetPrimaryKeyPropertyName(), 37 | }; 38 | return new InstantFeedbackSource(source, threadSafeProperties); 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /CS/MVVMExpenses/Common/DataModel/EntityFramework/InstantFeedbackSource.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Data; 4 | using System.Data.Entity; 5 | using System.Linq.Expressions; 6 | using System.Collections.Generic; 7 | using MVVMExpenses.Common.Utils; 8 | using MVVMExpenses.Common.DataModel; 9 | using DevExpress.Mvvm; 10 | using System.Collections; 11 | using System.ComponentModel; 12 | using DevExpress.Data.Linq; 13 | using DevExpress.Data.Linq.Helpers; 14 | using DevExpress.Data.Async.Helpers; 15 | 16 | namespace MVVMExpenses.Common.DataModel.EntityFramework { 17 | 18 | class InstantFeedbackSource : IInstantFeedbackSource 19 | where TEntity : class { 20 | readonly EntityInstantFeedbackSource source; 21 | readonly PropertyDescriptorCollection threadSafeProperties; 22 | 23 | public InstantFeedbackSource(EntityInstantFeedbackSource source, PropertyDescriptorCollection threadSafeProperties) { 24 | this.source = source; 25 | this.threadSafeProperties = threadSafeProperties; 26 | } 27 | 28 | bool IListSource.ContainsListCollection { get { return ((IListSource)source).ContainsListCollection; } } 29 | 30 | IList IListSource.GetList() { 31 | return ((IListSource)source).GetList(); 32 | } 33 | 34 | TProperty IInstantFeedbackSource.GetPropertyValue(object threadSafeProxy, Expression> propertyExpression) { 35 | var propertyName = ExpressionHelper.GetPropertyName(propertyExpression); 36 | var threadSafeProperty = threadSafeProperties[propertyName]; 37 | return (TProperty)threadSafeProperty.GetValue(threadSafeProxy); 38 | } 39 | 40 | bool IInstantFeedbackSource.IsLoadedProxy(object threadSafeProxy) { 41 | return threadSafeProxy is ReadonlyThreadSafeProxyForObjectFromAnotherThread; 42 | } 43 | 44 | void IInstantFeedbackSource.Refresh() { 45 | source.Refresh(); 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /CS/MVVMExpenses/Common/DataModel/EntityState.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | 4 | namespace MVVMExpenses.Common.DataModel { 5 | /// 6 | /// Represents the state of the entity relative to the unit of work. 7 | /// 8 | public enum EntityState { 9 | 10 | /// 11 | /// The object exists but is not being tracked. 12 | /// An entity is in this state immediately after it has been created and before it is added to the unit of work. 13 | /// An entity is also in this state after it has been removed from the unit of work by calling the IUnitOfWork.Detach method. 14 | /// 15 | Detached = 1, 16 | 17 | /// 18 | /// The object has not been modified since it was attached to the unit of work or since the last time that the IUnitOfWork.SaveChanges method was called. 19 | /// 20 | Unchanged = 2, 21 | 22 | /// 23 | /// The object is new, has been added to the unit of work, and the IUnitOfWork.SaveChanges method has not been called. 24 | /// After the changes are saved, the object state changes to Unchanged. 25 | /// 26 | Added = 4, 27 | 28 | /// 29 | /// The object has been deleted from the unit of work. After the changes are saved, the object state changes to Detached. 30 | /// 31 | Deleted = 8, 32 | 33 | /// 34 | /// One of the scalar properties on the object has been modified and the IUnitOfWork.SaveChanges method has not been called. 35 | /// After the changes are saved, the object state changes to Unchanged. 36 | /// 37 | Modified = 16, 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /CS/MVVMExpenses/Common/DataModel/IUnitOfWork.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Linq; 4 | using System.Linq.Expressions; 5 | 6 | namespace MVVMExpenses.Common.DataModel { 7 | /// 8 | /// The IUnitOfWork interface represents the Unit Of Work pattern 9 | /// such that it can be used to query from a database and group together changes that will then be written back to the store as a unit. 10 | /// 11 | public interface IUnitOfWork { 12 | /// 13 | /// Saves all changes made in this unit of work to the underlying store. 14 | /// 15 | void SaveChanges(); 16 | 17 | /// 18 | /// Checks if the unit of work is tracking any new, deleted, or changed entities or relationships that will be sent to the store if SaveChanges() is called. 19 | /// 20 | bool HasChanges(); 21 | } 22 | 23 | /// 24 | /// Provides the method to create a unit of work of a given type. 25 | /// 26 | /// A unit of work type. 27 | public interface IUnitOfWorkFactory where TUnitOfWork : IUnitOfWork { 28 | 29 | /// 30 | /// Creates a new unit of work. 31 | /// 32 | TUnitOfWork CreateUnitOfWork(); 33 | IInstantFeedbackSource CreateInstantFeedbackSource(Func> getRepositoryFunc, Func, IQueryable> projection) 34 | where TEntity : class, new() 35 | where TProjection : class; 36 | } 37 | 38 | public interface IInstantFeedbackSource : IListSource 39 | where TEntity : class { 40 | void Refresh(); 41 | TProperty GetPropertyValue(object threadSafeProxy, Expression> propertyExpression); 42 | bool IsLoadedProxy(object threadSafeProxy); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /CS/MVVMExpenses/Common/DataModel/UnitOfWorkBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Collections.Generic; 4 | using System.Linq.Expressions; 5 | 6 | namespace MVVMExpenses.Common.DataModel { 7 | /// 8 | /// The base class for unit of works that provides the storage for repositories. 9 | /// 10 | public class UnitOfWorkBase { 11 | 12 | readonly Dictionary repositories = new Dictionary(); 13 | 14 | protected TRepository GetRepositoryCore(Func createRepositoryFunc) 15 | where TRepository : IReadOnlyRepository 16 | where TEntity : class { 17 | object result = null; 18 | if(!repositories.TryGetValue(typeof(TEntity), out result)) { 19 | result = createRepositoryFunc(); 20 | repositories[typeof(TEntity)] = result; 21 | } 22 | return (TRepository)result; 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /CS/MVVMExpenses/Common/Utils/DbExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Linq; 4 | 5 | namespace MVVMExpenses.Common.Utils { 6 | /// 7 | /// Provides the extension method for implementations of the IQueryable interface. 8 | /// 9 | public static class DbExtensions { 10 | 11 | /// 12 | /// Forces entities to be loaded locally from the IQueryable instance. 13 | /// 14 | /// An instance of the IQueryable interface from which to load entities. 15 | public static void Load(this IQueryable source) { 16 | IEnumerator enumerator = source.GetEnumerator(); 17 | while(enumerator.MoveNext()) { 18 | } 19 | } 20 | 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /CS/MVVMExpenses/Common/ViewModel/ISingleObjectViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.Linq; 4 | using System.Linq.Expressions; 5 | using DevExpress.Mvvm; 6 | using DevExpress.Mvvm.POCO; 7 | using DevExpress.Mvvm.DataAnnotations; 8 | using MVVMExpenses.Common.Utils; 9 | using MVVMExpenses.Common.DataModel; 10 | 11 | namespace MVVMExpenses.Common.ViewModel { 12 | /// 13 | /// The base interface for view models representing a single entity. 14 | /// 15 | /// An entity type. 16 | /// An entity primary key type. 17 | public interface ISingleObjectViewModel { 18 | 19 | /// 20 | /// The entity represented by a view model. 21 | /// 22 | TEntity Entity { get; } 23 | 24 | /// 25 | /// The entity primary key value. 26 | /// 27 | TPrimaryKey PrimaryKey { get; } 28 | } 29 | } -------------------------------------------------------------------------------- /CS/MVVMExpenses/Common/ViewModel/LayoutSettings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.18052 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace MVVMExpenses.Common.ViewModel { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] 16 | internal sealed partial class LayoutSettings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static LayoutSettings defaultInstance = ((LayoutSettings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new LayoutSettings()))); 19 | 20 | public static LayoutSettings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | 26 | [global::System.Configuration.UserScopedSettingAttribute()] 27 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 28 | [global::System.Configuration.DefaultSettingValueAttribute("")] 29 | public string LogicalLayout { 30 | get { 31 | return ((string)(this["LogicalLayout"])); 32 | } 33 | set { 34 | this["LogicalLayout"] = value; 35 | } 36 | } 37 | 38 | [global::System.Configuration.UserScopedSettingAttribute()] 39 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 40 | [global::System.Configuration.DefaultSettingValueAttribute("")] 41 | public string ViewsLayout { 42 | get { 43 | return ((string)(this["ViewsLayout"])); 44 | } 45 | set { 46 | this["ViewsLayout"] = value; 47 | } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /CS/MVVMExpenses/Common/ViewModel/LayoutSettings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /CS/MVVMExpenses/Common/ViewModel/LookUpEntitiesViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.ComponentModel; 4 | using DevExpress.Mvvm; 5 | using DevExpress.Mvvm.POCO; 6 | using System.Collections.ObjectModel; 7 | using MVVMExpenses.Common.Utils; 8 | using MVVMExpenses.Common.DataModel; 9 | 10 | namespace MVVMExpenses.Common.ViewModel { 11 | /// 12 | /// Represents a POCO view models used by SingleObjectViewModel to exposing collections of related entities. 13 | /// This is a partial class that provides an extension point to add custom properties, commands and override methods without modifying the auto-generated code. 14 | /// 15 | /// A repository entity type. 16 | /// A projection entity type. 17 | /// A primary key value type. 18 | /// A unit of work type. 19 | public class LookUpEntitiesViewModel : EntitiesViewModel, IDocumentContent 20 | where TEntity : class 21 | where TProjection : class 22 | where TUnitOfWork : IUnitOfWork { 23 | 24 | /// 25 | /// Creates a new instance of LookUpEntitiesViewModel as a POCO view model. 26 | /// 27 | /// A factory used to create a unit of work instance. 28 | /// A function that returns a repository representing entities of the given type. 29 | /// An optional parameter that provides a LINQ function used to customize a query for entities. The parameter, for example, can be used for sorting data and/or for projecting data to a custom type that does not match the repository entity type. 30 | public static LookUpEntitiesViewModel Create( 31 | IUnitOfWorkFactory unitOfWorkFactory, 32 | Func> getRepositoryFunc, 33 | Func, IQueryable> projection = null) { 34 | return ViewModelSource.Create(() => new LookUpEntitiesViewModel(unitOfWorkFactory, getRepositoryFunc, projection)); 35 | } 36 | 37 | /// 38 | /// Initializes a new instance of the LookUpEntitiesViewModel class. 39 | /// This constructor is declared protected to avoid an undesired instantiation of the LookUpEntitiesViewModel type without the POCO proxy factory. 40 | /// 41 | /// A factory used to create a unit of work instance. 42 | /// A function that returns a repository representing entities of the given type. 43 | /// A LINQ function used to customize a query for entities. The parameter, for example, can be used for sorting data and/or for projecting data to a custom type that does not match the repository entity type. 44 | protected LookUpEntitiesViewModel( 45 | IUnitOfWorkFactory unitOfWorkFactory, 46 | Func> getRepositoryFunc, 47 | Func, IQueryable> projection 48 | ) : base(unitOfWorkFactory, getRepositoryFunc, projection) { 49 | } 50 | 51 | protected override IEntitiesChangeTracker CreateEntitiesChangeTracker() { 52 | return new EntitiesChangeTracker(this); 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /CS/MVVMExpenses/Common/ViewModel/Messages.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.ComponentModel; 4 | 5 | namespace MVVMExpenses.Common.ViewModel { 6 | /// 7 | /// Represents the type of an entity state change notification that is shown when the IUnitOfWork.SaveChanges method has been called. 8 | /// 9 | public enum EntityMessageType { 10 | 11 | /// 12 | /// A new entity has been added to the unit of work. 13 | /// 14 | Added, 15 | 16 | /// 17 | /// An entity has been removed from the unit of work. 18 | /// 19 | Deleted, 20 | 21 | /// 22 | /// One of the entity properties has been modified. 23 | /// 24 | Changed 25 | } 26 | 27 | /// 28 | /// Provides the information about an entity state change notification that is shown when an entity has been added, removed or modified, and the IUnitOfWork.SaveChanges method has been called. 29 | /// 30 | /// An entity type. 31 | /// A primary key value type. 32 | public class EntityMessage { 33 | 34 | /// 35 | /// Initializes a new instance of the EntityMessage class. 36 | /// 37 | /// A primary key of an entity that has been added, removed or modified. 38 | /// An entity state change notification type. 39 | public EntityMessage(TPrimaryKey primaryKey, EntityMessageType messageType) { 40 | this.PrimaryKey = primaryKey; 41 | this.MessageType = messageType; 42 | } 43 | 44 | /// 45 | /// The primary key of entity that has been added, deleted or modified. 46 | /// 47 | public TPrimaryKey PrimaryKey { get; private set; } 48 | 49 | /// 50 | /// The entity state change notification type. 51 | /// 52 | public EntityMessageType MessageType { get; private set; } 53 | } 54 | 55 | /// 56 | /// A message notifying that all view models should save changes. Usually sent by DocumentsViewModel when the SaveAll command is executed. 57 | /// 58 | public class SaveAllMessage { 59 | } 60 | 61 | /// 62 | /// A message notifying that all view models should close itself. Usually sent by DocumentsViewModel when the CloseAll command is executed. 63 | /// 64 | public class CloseAllMessage { 65 | 66 | readonly CancelEventArgs cancelEventArgs; 67 | 68 | /// 69 | /// Initializes a new instance of the CloseAllMessage class. 70 | /// 71 | /// An argument of the System.ComponentModel.CancelEventArgs type which can be used to cancel closing. 72 | public CloseAllMessage(CancelEventArgs cancelEventArgs) { 73 | this.cancelEventArgs = cancelEventArgs; 74 | } 75 | 76 | /// 77 | /// Used to cancel closing and check whether the closing has already been cancelled. 78 | /// 79 | public bool Cancel { 80 | get { return cancelEventArgs.Cancel; } 81 | set { cancelEventArgs.Cancel = value; } 82 | } 83 | } 84 | 85 | public class DestroyOrphanedDocumentsMessage { } 86 | 87 | /// 88 | /// Used by the PeekCollectionViewModel to notify that DocumentsViewModel should navigate to the specified module. 89 | /// 90 | /// The navigation token type. 91 | public class NavigateMessage { 92 | 93 | /// 94 | /// Initializes a new instance of the NavigateMessage class. 95 | /// 96 | /// An object that is used to identify the module to which the DocumentsViewModel should navigate. 97 | public NavigateMessage(TNavigationToken token) { 98 | Token = token; 99 | } 100 | 101 | /// 102 | /// An object that is used to identify the module to which the DocumentsViewModel should navigate. 103 | /// 104 | public TNavigationToken Token { get; private set; } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /CS/MVVMExpenses/Common/ViewModel/PeekCollectionViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Linq.Expressions; 7 | using DevExpress.Mvvm; 8 | using DevExpress.Mvvm.POCO; 9 | using DevExpress.Mvvm.DataAnnotations; 10 | using MVVMExpenses.Common.Utils; 11 | using MVVMExpenses.Common.DataModel; 12 | 13 | namespace MVVMExpenses.Common.ViewModel { 14 | /// 15 | /// A POCO view model exposing a read-only collection of entities of a given type. It is designed for quick navigation between collection views. 16 | /// This is a partial class that provides an extension point to add custom properties, commands and override methods without modifying the auto-generated code. 17 | /// 18 | /// A navigation token type. 19 | /// An entity type. 20 | /// A primary key value type. 21 | /// A unit of work type. 22 | public partial class PeekCollectionViewModel : CollectionViewModelBase 23 | where TEntity : class 24 | where TUnitOfWork : IUnitOfWork { 25 | 26 | /// 27 | /// Creates a new instance of PeekCollectionViewModel as a POCO view model. 28 | /// 29 | /// Identifies the module that is the navigation target. 30 | /// A factory that is used to create a unit of work instance. 31 | /// A function that returns a repository representing entities of a given type. 32 | /// An optional parameter that provides a LINQ function used to customize a query for entities. The parameter, for example, can be used for sorting data. 33 | public static PeekCollectionViewModel Create( 34 | TNavigationToken navigationToken, 35 | IUnitOfWorkFactory unitOfWorkFactory, 36 | Func> getRepositoryFunc, 37 | Func, IQueryable> projection = null) { 38 | return ViewModelSource.Create(() => new PeekCollectionViewModel(navigationToken, unitOfWorkFactory, getRepositoryFunc, projection)); 39 | } 40 | 41 | TNavigationToken navigationToken; 42 | TEntity pickedEntity; 43 | 44 | /// 45 | /// Initializes a new instance of the PeekCollectionViewModel class. 46 | /// This constructor is declared protected to avoid an undesired instantiation of the PeekCollectionViewModel type without the POCO proxy factory. 47 | /// 48 | /// Identifies the module that is the navigation target. 49 | /// A factory that is used to create a unit of work instance. 50 | /// A function that returns a repository representing entities of a given type. 51 | /// An optional parameter that provides a LINQ function used to customize a query for entities. The parameter, for example, can be used for sorting data. 52 | protected PeekCollectionViewModel( 53 | TNavigationToken navigationToken, 54 | IUnitOfWorkFactory unitOfWorkFactory, 55 | Func> getRepositoryFunc, 56 | Func, IQueryable> projection = null 57 | ) : base(unitOfWorkFactory, getRepositoryFunc, projection, null, null, true) { 58 | this.navigationToken = navigationToken; 59 | } 60 | 61 | /// 62 | /// Navigates to the corresponding collection view and selects the given entity. 63 | /// Since PeekCollectionViewModel is a POCO view model, an instance of this class will also expose the NavigateCommand property that can be used as a binding source in views. 64 | /// 65 | /// An entity to select within the collection view. 66 | [Display(AutoGenerateField = false)] 67 | public void Navigate(TEntity projectionEntity) { 68 | pickedEntity = projectionEntity; 69 | SendSelectEntityMessage(); 70 | Messenger.Default.Send(new NavigateMessage(navigationToken), navigationToken); 71 | } 72 | 73 | /// 74 | /// Determines if a navigation to corresponding collection view can be performed. 75 | /// Since PeekCollectionViewModel is a POCO view model, this method will be used as a CanExecute callback for NavigateCommand. 76 | /// 77 | /// An entity to select in the collection view. 78 | public bool CanNavigate(TEntity projectionEntity) { 79 | return projectionEntity != null; 80 | } 81 | 82 | protected override void OnInitializeInRuntime() { 83 | base.OnInitializeInRuntime(); 84 | Messenger.Default.Register(this, x => SendSelectEntityMessage()); 85 | } 86 | 87 | void SendSelectEntityMessage() { 88 | if(IsLoaded && pickedEntity != null) 89 | Messenger.Default.Send(new SelectEntityMessage(CreateRepository().GetProjectionPrimaryKey(pickedEntity))); 90 | } 91 | } 92 | } -------------------------------------------------------------------------------- /CS/MVVMExpenses/Common/ViewModel/ViewModelLogicalLayoutHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using DevExpress.Mvvm; 7 | 8 | namespace MVVMExpenses.Common.ViewModel { 9 | public class ViewModelLogicalLayoutHelper { 10 | public static string PersistentLogicalLayout { 11 | get { return LayoutSettings.Default.LogicalLayout; } 12 | set { LayoutSettings.Default.LogicalLayout = value; } 13 | } 14 | static Dictionary persistentViewsLayout; 15 | public static Dictionary PersistentViewsLayout { 16 | get { 17 | if(persistentViewsLayout == null) { 18 | persistentViewsLayout = LogicalLayoutSerializationHelper.Deserialize(LayoutSettings.Default.ViewsLayout); 19 | } 20 | return persistentViewsLayout; 21 | } 22 | } 23 | public static void SaveLayout() { 24 | LayoutSettings.Default.ViewsLayout = LogicalLayoutSerializationHelper.Serialize(PersistentViewsLayout); 25 | LayoutSettings.Default.Save(); 26 | } 27 | public static void ResetLayout() { 28 | PersistentViewsLayout.Clear(); 29 | PersistentLogicalLayout = null; 30 | SaveLayout(); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /CS/MVVMExpenses/Data/Expenses.sqlite3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevExpress-Examples/winforms-mvvm-expenses-app/70a139e6d5909c97e63090201977325d1be58b9a/CS/MVVMExpenses/Data/Expenses.sqlite3 -------------------------------------------------------------------------------- /CS/MVVMExpenses/DataBase/DbContext.cs: -------------------------------------------------------------------------------- 1 | using System.Data.Entity; 2 | using MVVMExpenses.DataModels; 3 | 4 | namespace MVVMExpenses.DataBase { 5 | [DbConfigurationType(typeof(MVVMExpenses.Common.DataModel.EntityFramework.MyDbSQLiteConfiguration))] 6 | public class MyDbContext : System.Data.Entity.DbContext { 7 | static MyDbContext() { 8 | Database.SetInitializer(null); 9 | } 10 | public DbSet Accounts { get; set; } 11 | public DbSet Categories { get; set; } 12 | public DbSet Transactions { get; set; } 13 | } 14 | } -------------------------------------------------------------------------------- /CS/MVVMExpenses/Models/Account.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.ComponentModel.DataAnnotations; 7 | 8 | namespace MVVMExpenses.DataModels { 9 | public class Account { 10 | [Key, Display(AutoGenerateField = false)] 11 | public long ID { get; set; } 12 | [Required, StringLength(30, MinimumLength = 4)] 13 | [Display(Name = "ACCOUNT")] 14 | public string Name { get; set; } 15 | [DataType(DataType.Currency)] 16 | [Display(Name = "AMOUNT")] 17 | public decimal Amount { get; set; } 18 | public override string ToString() { 19 | return Name + " (" + Amount.ToString("C") + ")"; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /CS/MVVMExpenses/Models/Category.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.ComponentModel.DataAnnotations; 7 | 8 | namespace MVVMExpenses.DataModels { 9 | public class Category { 10 | [Key, Display(AutoGenerateField = false)] 11 | public long ID { get; set; } 12 | [Required, StringLength(30, MinimumLength = 5)] 13 | [Display(Name = "CATEGORY")] 14 | public string Name { get; set; } 15 | [EnumDataType(typeof(TransactionType))] 16 | [Display(Name = "TRANSACTION TYPE")] 17 | public TransactionType Type { get; set; } 18 | public override string ToString() { 19 | return Name + " (" + Type.ToString() + ")"; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /CS/MVVMExpenses/Models/CredentialsSource.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using DevExpress.Mvvm.POCO; 3 | using MVVMExpenses.Models; 4 | 5 | namespace MVVMExpenses.ViewModels 6 | { 7 | // 8 | // TODO - your implementation 9 | static class CredentialsSource { 10 | static System.Collections.Hashtable credentials; 11 | static CredentialsSource() { 12 | credentials = new System.Collections.Hashtable(); 13 | credentials.Add("Guest", GetHash(null)); 14 | credentials.Add("John", GetHash("qwerty")); 15 | credentials.Add("Administrator", GetHash("admin")); 16 | credentials.Add("Mary", GetHash("12345")); 17 | } 18 | internal static bool Check(string login, string pwd) { 19 | return object.Equals(credentials[login], GetHash(pwd)); 20 | } 21 | static object GetHash(string password) { 22 | return password; 23 | } 24 | internal static System.Collections.Generic.IEnumerable GetUserNames() { 25 | foreach(string item in credentials.Keys) 26 | yield return item; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /CS/MVVMExpenses/Models/MyDbContextDataModel/IMyDbContextUnitOfWork.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Data; 4 | using System.Data.Entity; 5 | using System.Linq.Expressions; 6 | using System.Collections.Generic; 7 | using MVVMExpenses.Common.Utils; 8 | using MVVMExpenses.Common.DataModel; 9 | using MVVMExpenses.Common.DataModel.EntityFramework; 10 | using MVVMExpenses.DataBase; 11 | using MVVMExpenses.DataModels; 12 | 13 | namespace MVVMExpenses.Models.MyDbContextDataModel { 14 | /// 15 | /// IMyDbContextUnitOfWork extends the IUnitOfWork interface with repositories representing specific entities. 16 | /// 17 | public interface IMyDbContextUnitOfWork : IUnitOfWork { 18 | 19 | /// 20 | /// The Account entities repository. 21 | /// 22 | IRepository Accounts { get; } 23 | 24 | /// 25 | /// The Category entities repository. 26 | /// 27 | IRepository Categories { get; } 28 | 29 | /// 30 | /// The Transaction entities repository. 31 | /// 32 | IRepository Transactions { get; } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /CS/MVVMExpenses/Models/MyDbContextDataModel/MyDbContextUnitOfWork.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Data; 4 | using System.Data.Entity; 5 | using System.Linq.Expressions; 6 | using System.Collections.Generic; 7 | using MVVMExpenses.Common.Utils; 8 | using MVVMExpenses.Common.DataModel; 9 | using MVVMExpenses.Common.DataModel.EntityFramework; 10 | using MVVMExpenses.DataBase; 11 | using MVVMExpenses.DataModels; 12 | using DevExpress.XtraBars; 13 | 14 | namespace MVVMExpenses.Models.MyDbContextDataModel { 15 | /// 16 | /// A MyDbContextUnitOfWork instance that represents the run-time implementation of the IMyDbContextUnitOfWork interface. 17 | /// 18 | public class MyDbContextUnitOfWork : DbUnitOfWork, IMyDbContextUnitOfWork { 19 | 20 | public MyDbContextUnitOfWork(Func contextFactory) 21 | : base(contextFactory) { 22 | } 23 | 24 | IRepository IMyDbContextUnitOfWork.Accounts { 25 | get { return GetRepository(x => x.Set(), x => x.ID); } 26 | } 27 | 28 | IRepository IMyDbContextUnitOfWork.Categories { 29 | get { return GetRepository(x => x.Set(), x => x.ID); } 30 | } 31 | 32 | IRepository IMyDbContextUnitOfWork.Transactions { 33 | get { return GetRepository(x => x.Set(), x => x.ID); } 34 | } 35 | 36 | BarHeaderItem bhi = new BarHeaderItem() { Width = 100 }; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /CS/MVVMExpenses/Models/MyDbContextDataModel/UnitOfWorkSource.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Data; 4 | using System.Data.Entity; 5 | using System.Linq.Expressions; 6 | using System.Collections.Generic; 7 | using MVVMExpenses.Common.Utils; 8 | using MVVMExpenses.Common.DataModel; 9 | using MVVMExpenses.Common.DataModel.EntityFramework; 10 | using MVVMExpenses.DataBase; 11 | using MVVMExpenses.DataModels; 12 | using DevExpress.Mvvm; 13 | using System.Collections; 14 | using System.ComponentModel; 15 | using DevExpress.Data.Linq; 16 | using DevExpress.Data.Linq.Helpers; 17 | using DevExpress.Data.Async.Helpers; 18 | 19 | namespace MVVMExpenses.Models.MyDbContextDataModel { 20 | /// 21 | /// Provides methods to obtain the relevant IUnitOfWorkFactory. 22 | /// 23 | public static class UnitOfWorkSource { 24 | 25 | /// 26 | /// Returns the IUnitOfWorkFactory implementation. 27 | /// 28 | public static IUnitOfWorkFactory GetUnitOfWorkFactory() { 29 | return new DbUnitOfWorkFactory(() => new MyDbContextUnitOfWork(() => new MyDbContext())); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /CS/MVVMExpenses/Models/Transaction.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.ComponentModel.DataAnnotations; 7 | 8 | namespace MVVMExpenses.DataModels { 9 | public enum TransactionType { 10 | Expense, 11 | Income 12 | } 13 | public class Transaction { 14 | [Key, Display(AutoGenerateField = false)] 15 | public long ID { get; set; } 16 | [Display(AutoGenerateField = false)] 17 | public long AccountID { get; set; } 18 | [Display(Name = "ACCOUNT")] 19 | public virtual Account Account { get; set; } 20 | [Display(AutoGenerateField = false)] 21 | public long CategoryID { get; set; } 22 | [Display(Name = "CATEGORY")] 23 | public virtual Category Category { get; set; } 24 | [DataType(DataType.Date)] 25 | [Display(Name = "DATE")] 26 | public DateTime Date { get; set; } 27 | [DataType(DataType.Currency)] 28 | [Display(Name = "AMOUNT")] 29 | public decimal Amount { get; set; } 30 | [DataType(DataType.MultilineText)] 31 | [Display(Name = "COMMENT")] 32 | public string Comment { get; set; } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /CS/MVVMExpenses/Models/User.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace MVVMExpenses.Models { 9 | public class User { 10 | public string Login { get; set; } 11 | public string Password { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /CS/MVVMExpenses/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using System.Windows.Forms; 6 | using DevExpress.Skins; 7 | 8 | namespace MVVMExpenses { 9 | static class Program { 10 | /// 11 | /// The main entry point for the application. 12 | /// 13 | [STAThread] 14 | static void Main() { 15 | SkinManager.EnableFormSkins(); 16 | Application.EnableVisualStyles(); 17 | Application.SetCompatibleTextRenderingDefault(false); 18 | Application.Run(new MainView()); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /CS/MVVMExpenses/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("MVVMExpenses")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("MVVMExpenses")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("f4f8f877-60af-42a1-a36e-a6d8ddc2d7cc")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /CS/MVVMExpenses/Properties/DataSources/MVVMExpenses.DataModels.Account.datasource: -------------------------------------------------------------------------------- 1 |  2 | 8 | 9 | MVVMExpenses.DataModels.Account, MVVMExpenses, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null 10 | -------------------------------------------------------------------------------- /CS/MVVMExpenses/Properties/DataSources/MVVMExpenses.DataModels.Category.datasource: -------------------------------------------------------------------------------- 1 |  2 | 8 | 9 | MVVMExpenses.DataModels.Category, MVVMExpenses, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null 10 | -------------------------------------------------------------------------------- /CS/MVVMExpenses/Properties/DataSources/MVVMExpenses.DataModels.Transaction.datasource: -------------------------------------------------------------------------------- 1 |  2 | 8 | 9 | MVVMExpenses.DataModels.Transaction, MVVMExpenses, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null 10 | -------------------------------------------------------------------------------- /CS/MVVMExpenses/Properties/DataSources/MVVMExpenses.Models.SampleUserList.datasource: -------------------------------------------------------------------------------- 1 |  2 | 8 | 9 | -------------------------------------------------------------------------------- /CS/MVVMExpenses/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.18052 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace MVVMExpenses.Properties { 12 | 13 | 14 | /// 15 | /// A strongly-typed resource class, for looking up localized strings, etc. 16 | /// 17 | // This class was auto-generated by the StronglyTypedResourceBuilder 18 | // class via a tool like ResGen or Visual Studio. 19 | // To add or remove a member, edit your .ResX file then rerun ResGen 20 | // with the /str option, or rebuild your VS project. 21 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 22 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 23 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 24 | internal class Resources { 25 | 26 | private static global::System.Resources.ResourceManager resourceMan; 27 | 28 | private static global::System.Globalization.CultureInfo resourceCulture; 29 | 30 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 31 | internal Resources() { 32 | } 33 | 34 | /// 35 | /// Returns the cached ResourceManager instance used by this class. 36 | /// 37 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 38 | internal static global::System.Resources.ResourceManager ResourceManager { 39 | get { 40 | if((resourceMan == null)) { 41 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MVVMExpenses.Properties.Resources", typeof(Resources).Assembly); 42 | resourceMan = temp; 43 | } 44 | return resourceMan; 45 | } 46 | } 47 | 48 | /// 49 | /// Overrides the current thread's CurrentUICulture property for all 50 | /// resource lookups using this strongly typed resource class. 51 | /// 52 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 53 | internal static global::System.Globalization.CultureInfo Culture { 54 | get { 55 | return resourceCulture; 56 | } 57 | set { 58 | resourceCulture = value; 59 | } 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /CS/MVVMExpenses/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /CS/MVVMExpenses/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.18052 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace MVVMExpenses.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /CS/MVVMExpenses/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /CS/MVVMExpenses/ViewModels/Account/AccountCollectionViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using DevExpress.Mvvm.POCO; 4 | using MVVMExpenses.Common.Utils; 5 | using MVVMExpenses.Models.MyDbContextDataModel; 6 | using MVVMExpenses.Common.DataModel; 7 | using MVVMExpenses.DataModels; 8 | using MVVMExpenses.DataBase; 9 | using MVVMExpenses.Common.ViewModel; 10 | using System.Collections.Generic; 11 | 12 | namespace MVVMExpenses.Models.ViewModels { 13 | /// 14 | /// Represents the Accounts collection view model. 15 | /// 16 | public partial class AccountCollectionViewModel : CollectionViewModel { 17 | 18 | /// 19 | /// Creates a new instance of AccountCollectionViewModel as a POCO view model. 20 | /// 21 | /// A factory used to create a unit of work instance. 22 | public static AccountCollectionViewModel Create(IUnitOfWorkFactory unitOfWorkFactory = null) { 23 | return ViewModelSource.Create(() => new AccountCollectionViewModel(unitOfWorkFactory)); 24 | } 25 | 26 | /// 27 | /// Initializes a new instance of the AccountCollectionViewModel class. 28 | /// This constructor is declared protected to avoid undesired instantiation of the AccountCollectionViewModel type without the POCO proxy factory. 29 | /// 30 | /// A factory used to create a unit of work instance. 31 | protected AccountCollectionViewModel(IUnitOfWorkFactory unitOfWorkFactory = null) 32 | : base(unitOfWorkFactory ?? UnitOfWorkSource.GetUnitOfWorkFactory(), x => x.Accounts) { 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /CS/MVVMExpenses/ViewModels/Account/AccountViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Linq.Expressions; 4 | using System.Collections.Generic; 5 | using System.Collections.ObjectModel; 6 | using DevExpress.Mvvm; 7 | using DevExpress.Mvvm.POCO; 8 | using MVVMExpenses.Common.Utils; 9 | using MVVMExpenses.Models.MyDbContextDataModel; 10 | using MVVMExpenses.Common.DataModel; 11 | using MVVMExpenses.DataModels; 12 | using MVVMExpenses.DataBase; 13 | using MVVMExpenses.Common.ViewModel; 14 | 15 | namespace MVVMExpenses.Models.ViewModels { 16 | /// 17 | /// Represents the single Account object view model. 18 | /// 19 | public partial class AccountViewModel : SingleObjectViewModel { 20 | 21 | /// 22 | /// Creates a new instance of AccountViewModel as a POCO view model. 23 | /// 24 | /// A factory used to create a unit of work instance. 25 | public static AccountViewModel Create(IUnitOfWorkFactory unitOfWorkFactory = null) { 26 | return ViewModelSource.Create(() => new AccountViewModel(unitOfWorkFactory)); 27 | } 28 | 29 | /// 30 | /// Initializes a new instance of the AccountViewModel class. 31 | /// This constructor is declared protected to avoid undesired instantiation of the AccountViewModel type without the POCO proxy factory. 32 | /// 33 | /// A factory used to create a unit of work instance. 34 | protected AccountViewModel(IUnitOfWorkFactory unitOfWorkFactory = null) 35 | : base(unitOfWorkFactory ?? UnitOfWorkSource.GetUnitOfWorkFactory(), x => x.Accounts, x => x.Name) { 36 | } 37 | 38 | public CollectionViewModel AccountTransactionDetails { 39 | get { return GetDetailsCollectionViewModel((AccountViewModel x) => x.AccountTransactionDetails, x => x.Transactions, x => x.AccountID, (x, key) => x.AccountID = key); } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /CS/MVVMExpenses/ViewModels/Category/CategoryCollectionViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using DevExpress.Mvvm.POCO; 4 | using MVVMExpenses.Common.Utils; 5 | using MVVMExpenses.Models.MyDbContextDataModel; 6 | using MVVMExpenses.Common.DataModel; 7 | using MVVMExpenses.DataModels; 8 | using MVVMExpenses.DataBase; 9 | using MVVMExpenses.Common.ViewModel; 10 | 11 | namespace MVVMExpenses.Models.ViewModels { 12 | /// 13 | /// Represents the Categories collection view model. 14 | /// 15 | public partial class CategoryCollectionViewModel : CollectionViewModel { 16 | 17 | /// 18 | /// Creates a new instance of CategoryCollectionViewModel as a POCO view model. 19 | /// 20 | /// A factory used to create a unit of work instance. 21 | public static CategoryCollectionViewModel Create(IUnitOfWorkFactory unitOfWorkFactory = null) { 22 | return ViewModelSource.Create(() => new CategoryCollectionViewModel(unitOfWorkFactory)); 23 | } 24 | 25 | /// 26 | /// Initializes a new instance of the CategoryCollectionViewModel class. 27 | /// This constructor is declared protected to avoid undesired instantiation of the CategoryCollectionViewModel type without the POCO proxy factory. 28 | /// 29 | /// A factory used to create a unit of work instance. 30 | protected CategoryCollectionViewModel(IUnitOfWorkFactory unitOfWorkFactory = null) 31 | : base(unitOfWorkFactory ?? UnitOfWorkSource.GetUnitOfWorkFactory(), x => x.Categories) { 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /CS/MVVMExpenses/ViewModels/Category/CategoryViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Linq.Expressions; 4 | using System.Collections.Generic; 5 | using System.Collections.ObjectModel; 6 | using DevExpress.Mvvm; 7 | using DevExpress.Mvvm.POCO; 8 | using MVVMExpenses.Common.Utils; 9 | using MVVMExpenses.Models.MyDbContextDataModel; 10 | using MVVMExpenses.Common.DataModel; 11 | using MVVMExpenses.DataModels; 12 | using MVVMExpenses.DataBase; 13 | using MVVMExpenses.Common.ViewModel; 14 | 15 | namespace MVVMExpenses.Models.ViewModels { 16 | /// 17 | /// Represents the single Category object view model. 18 | /// 19 | public partial class CategoryViewModel : SingleObjectViewModel { 20 | 21 | /// 22 | /// Creates a new instance of CategoryViewModel as a POCO view model. 23 | /// 24 | /// A factory used to create a unit of work instance. 25 | public static CategoryViewModel Create(IUnitOfWorkFactory unitOfWorkFactory = null) { 26 | return ViewModelSource.Create(() => new CategoryViewModel(unitOfWorkFactory)); 27 | } 28 | 29 | /// 30 | /// Initializes a new instance of the CategoryViewModel class. 31 | /// This constructor is declared protected to avoid undesired instantiation of the CategoryViewModel type without the POCO proxy factory. 32 | /// 33 | /// A factory used to create a unit of work instance. 34 | protected CategoryViewModel(IUnitOfWorkFactory unitOfWorkFactory = null) 35 | : base(unitOfWorkFactory ?? UnitOfWorkSource.GetUnitOfWorkFactory(), x => x.Categories, x => x.Name) { 36 | } 37 | 38 | public CollectionViewModel CategoryTransactionDetails { 39 | get { return GetDetailsCollectionViewModel((CategoryViewModel x) => x.CategoryTransactionDetails, x => x.Transactions, x => x.CategoryID, (x, key) => x.CategoryID = key); } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /CS/MVVMExpenses/ViewModels/LoginViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using DevExpress.Mvvm.POCO; 3 | using MVVMExpenses.Models; 4 | 5 | namespace MVVMExpenses.ViewModels { 6 | public class LoginViewModel { 7 | public IEnumerable LookUpUsers { 8 | get { return CredentialsSource.GetUserNames(); } 9 | } 10 | public virtual User CurrentUser { get; set; } 11 | public bool IsCurrentUserCredentialsValid { get; private set; } 12 | // 13 | [DevExpress.Mvvm.DataAnnotations.Command(false)] 14 | public void Init() { 15 | this.CurrentUser = new User(); 16 | } 17 | public void Update() { 18 | IsCurrentUserCredentialsValid = CredentialsSource.Check(CurrentUser.Login, CurrentUser.Password); 19 | } 20 | public static LoginViewModel Create() { 21 | return ViewModelSource.Create(); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /CS/MVVMExpenses/ViewModels/MyDbContextViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.ComponentModel; 5 | using DevExpress.Mvvm; 6 | using DevExpress.Mvvm.POCO; 7 | using MVVMExpenses.Common.DataModel; 8 | using MVVMExpenses.Common.ViewModel; 9 | using MVVMExpenses.Models.MyDbContextDataModel; 10 | using MVVMExpenses.DataBase; 11 | using MVVMExpenses.DataModels; 12 | using MVVMExpenses.ViewModels; 13 | 14 | namespace MVVMExpenses.Models.ViewModels { 15 | /// 16 | /// Represents the root POCO view model for the MyDbContext data model. 17 | /// 18 | public partial class MyDbContextViewModel : DocumentsViewModel { 19 | const string TablesGroup = "Tables"; 20 | 21 | const string ViewsGroup = "Views"; 22 | 23 | /// 24 | /// Creates a new instance of MyDbContextViewModel as a POCO view model. 25 | /// 26 | public static MyDbContextViewModel Create() { 27 | return ViewModelSource.Create(() => new MyDbContextViewModel()); 28 | } 29 | 30 | /// 31 | /// Initializes a new instance of the MyDbContextViewModel class. 32 | /// This constructor is declared protected to avoid undesired instantiation of the MyDbContextViewModel type without the POCO proxy factory. 33 | /// 34 | //protected MyDbContextViewModel() 35 | // : base(UnitOfWorkSource.GetUnitOfWorkFactory()) { 36 | //} 37 | 38 | protected override MyDbContextModuleDescription[] CreateModules() { 39 | return new MyDbContextModuleDescription[] { 40 | new MyDbContextModuleDescription("Accounts", "AccountCollectionView", TablesGroup, GetPeekCollectionViewModelFactory(x => x.Accounts)), 41 | new MyDbContextModuleDescription("Categories", "CategoryCollectionView", TablesGroup, GetPeekCollectionViewModelFactory(x => x.Categories)), 42 | new MyDbContextModuleDescription("Transactions", "TransactionCollectionView", TablesGroup, GetPeekCollectionViewModelFactory(x => x.Transactions)), 43 | }; 44 | } 45 | 46 | 47 | 48 | } 49 | 50 | public partial class MyDbContextModuleDescription : ModuleDescription { 51 | public MyDbContextModuleDescription(string title, string documentType, string group, Func peekCollectionViewModelFactory = null) 52 | : base(title, documentType, group, peekCollectionViewModelFactory) { 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /CS/MVVMExpenses/ViewModels/MyDbContextViewModel.partial.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Windows; 3 | using DevExpress.Mvvm; 4 | using DevExpress.Mvvm.POCO; 5 | using DevExpress.Utils.MVVM; 6 | using MVVMExpenses.Models.MyDbContextDataModel; 7 | using MVVMExpenses.ViewModels; 8 | 9 | namespace MVVMExpenses.Models.ViewModels { 10 | public partial class MyDbContextViewModel { 11 | LoginViewModel loginViewModel; 12 | 13 | protected MyDbContextViewModel() 14 | : base(UnitOfWorkSource.GetUnitOfWorkFactory()) { 15 | loginViewModel = LoginViewModel.Create(); 16 | loginViewModel.SetParentViewModel(this); 17 | } 18 | protected IDialogService DialogService { 19 | get { return this.GetService(); } 20 | } 21 | protected IMessageBoxService MessageService { 22 | get { return this.GetService(); } 23 | } 24 | 25 | public override void OnLoaded(MyDbContextModuleDescription module) { 26 | base.OnLoaded(module); 27 | Login(); 28 | } 29 | public override void OnClosing(CancelEventArgs cancelEventArgs) { 30 | base.OnClosing(cancelEventArgs); 31 | if(!cancelEventArgs.Cancel) { 32 | if(State == AppState.Authorized && MessageService.ShowMessage("Do you really want to close the application?", "Confirm", MessageButton.YesNo) == MessageResult.No) 33 | cancelEventArgs.Cancel = true; 34 | } 35 | } 36 | // 37 | public virtual AppState State { get; set; } 38 | // Shows the Login View 39 | public void Login() { 40 | OnLogin(DialogService.ShowDialog(MessageButton.OKCancel, "Please enter you credentials", "LoginView", loginViewModel)); 41 | } 42 | public void Logout() { 43 | State = AppState.ExitQueued; 44 | System.Diagnostics.Process.Start(System.Windows.Forms.Application.ExecutablePath); 45 | } 46 | public bool CanLogout() { 47 | return State == AppState.Authorized; 48 | } 49 | //Occurs whenever the end-user clicks a dialog button 50 | void OnLogin(MessageResult result) { 51 | if(result == MessageResult.Cancel) 52 | State = AppState.ExitQueued; 53 | else { 54 | if(loginViewModel.IsCurrentUserCredentialsValid) 55 | State = AppState.Authorized; 56 | else 57 | Login(); 58 | } 59 | } 60 | protected void OnStateChanged() { 61 | this.RaiseCanExecuteChanged(x => x.Logout()); 62 | if(State == AppState.Authorized) 63 | Messenger.Default.Send(loginViewModel.CurrentUser.Login); 64 | else 65 | Messenger.Default.Send(string.Empty); 66 | } 67 | } 68 | 69 | public enum AppState { 70 | NotAuthorized, 71 | Authorized, 72 | ExitQueued 73 | } 74 | } -------------------------------------------------------------------------------- /CS/MVVMExpenses/ViewModels/Transaction/TransactionCollectionViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using DevExpress.Mvvm.POCO; 4 | using MVVMExpenses.Common.Utils; 5 | using MVVMExpenses.Models.MyDbContextDataModel; 6 | using MVVMExpenses.Common.DataModel; 7 | using MVVMExpenses.DataModels; 8 | using MVVMExpenses.DataBase; 9 | using MVVMExpenses.Common.ViewModel; 10 | 11 | namespace MVVMExpenses.Models.ViewModels { 12 | /// 13 | /// Represents the Transactions collection view model. 14 | /// 15 | public partial class TransactionCollectionViewModel : CollectionViewModel { 16 | 17 | /// 18 | /// Creates a new instance of TransactionCollectionViewModel as a POCO view model. 19 | /// 20 | /// A factory used to create a unit of work instance. 21 | public static TransactionCollectionViewModel Create(IUnitOfWorkFactory unitOfWorkFactory = null) { 22 | return ViewModelSource.Create(() => new TransactionCollectionViewModel(unitOfWorkFactory)); 23 | } 24 | 25 | /// 26 | /// Initializes a new instance of the TransactionCollectionViewModel class. 27 | /// This constructor is declared protected to avoid undesired instantiation of the TransactionCollectionViewModel type without the POCO proxy factory. 28 | /// 29 | /// A factory used to create a unit of work instance. 30 | protected TransactionCollectionViewModel(IUnitOfWorkFactory unitOfWorkFactory = null) 31 | : base(unitOfWorkFactory ?? UnitOfWorkSource.GetUnitOfWorkFactory(), x => x.Transactions) { 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /CS/MVVMExpenses/ViewModels/Transaction/TransactionViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Linq.Expressions; 4 | using System.Collections.Generic; 5 | using System.Collections.ObjectModel; 6 | using DevExpress.Mvvm; 7 | using DevExpress.Mvvm.POCO; 8 | using MVVMExpenses.Common.Utils; 9 | using MVVMExpenses.Models.MyDbContextDataModel; 10 | using MVVMExpenses.Common.DataModel; 11 | using MVVMExpenses.DataModels; 12 | using MVVMExpenses.DataBase; 13 | using MVVMExpenses.Common.ViewModel; 14 | 15 | namespace MVVMExpenses.Models.ViewModels { 16 | /// 17 | /// Represents the single Transaction object view model. 18 | /// 19 | public partial class TransactionViewModel : SingleObjectViewModel { 20 | 21 | /// 22 | /// Creates a new instance of TransactionViewModel as a POCO view model. 23 | /// 24 | /// A factory used to create a unit of work instance. 25 | public static TransactionViewModel Create(IUnitOfWorkFactory unitOfWorkFactory = null) { 26 | return ViewModelSource.Create(() => new TransactionViewModel(unitOfWorkFactory)); 27 | } 28 | 29 | /// 30 | /// Initializes a new instance of the TransactionViewModel class. 31 | /// This constructor is declared protected to avoid undesired instantiation of the TransactionViewModel type without the POCO proxy factory. 32 | /// 33 | /// A factory used to create a unit of work instance. 34 | protected TransactionViewModel(IUnitOfWorkFactory unitOfWorkFactory = null) 35 | : base(unitOfWorkFactory ?? UnitOfWorkSource.GetUnitOfWorkFactory(), x => x.Transactions, x => x.Comment) { 36 | } 37 | 38 | /// 39 | /// The view model that contains a look-up collection of Accounts for the corresponding navigation property in the view. 40 | /// 41 | public IEntitiesViewModel LookUpAccounts { 42 | get { return GetLookUpEntitiesViewModel((TransactionViewModel x) => x.LookUpAccounts, x => x.Accounts); } 43 | } 44 | 45 | /// 46 | /// The view model that contains a look-up collection of Categories for the corresponding navigation property in the view. 47 | /// 48 | public IEntitiesViewModel LookUpCategories { 49 | get { return GetLookUpEntitiesViewModel((TransactionViewModel x) => x.LookUpCategories, x => x.Categories); } 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /CS/MVVMExpenses/Views/Account/AccountsEditFormView.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Drawing; 5 | using System.Data; 6 | using System.Text; 7 | using System.Linq; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | using DevExpress.XtraEditors; 11 | using MVVMExpenses.Models; 12 | using MVVMExpenses.Models.ViewModels; 13 | using DevExpress.XtraGrid.Views.Grid; 14 | 15 | namespace MVVMExpenses.Common.Views.Account { 16 | [DevExpress.Utils.MVVM.UI.ViewType("AccountView")] 17 | public partial class AccountsEditFormView : DevExpress.XtraEditors.XtraUserControl { 18 | public AccountsEditFormView() { 19 | InitializeComponent(); 20 | if(!DesignMode) InitBindings(); 21 | } 22 | 23 | void InitBindings() { 24 | var fluent = mvvmContext1.OfType(); 25 | fluent.SetObjectDataSourceBinding( 26 | accountBindingSource, x => x.Entity, x => x.Update()); 27 | 28 | fluent.SetBinding( 29 | gridControl1, gc => gc.DataSource, x => x.AccountTransactionDetails.Entities); 30 | 31 | ((GridView)gridControl1.MainView).OptionsBehavior.Editable = false; 32 | ((GridView)gridControl1.MainView).Columns["Account"].Visible = false; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /CS/MVVMExpenses/Views/Account/AccountsView.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Drawing; 5 | using System.Data; 6 | using System.Text; 7 | using System.Linq; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | using DevExpress.XtraEditors; 11 | using DevExpress.Utils.MVVM.Services; 12 | using MVVMExpenses.Models.ViewModels; 13 | 14 | namespace MVVMExpenses.Common.Views.Account { 15 | [DevExpress.Utils.MVVM.UI.ViewType("AccountCollectionView")] 16 | public partial class AccountsView : DevExpress.XtraEditors.XtraUserControl { 17 | public AccountsView() { 18 | InitializeComponent(); 19 | if(!DesignMode) 20 | InitBindings(); 21 | gridView1.OptionsBehavior.Editable = false; 22 | gridView1.OptionsSelection.MultiSelect = true; 23 | gridView1.OptionsSelection.MultiSelectMode = DevExpress.XtraGrid.Views.Grid.GridMultiSelectMode.RowSelect; 24 | } 25 | 26 | void InitBindings() { 27 | var fluentAPI = mvvmContext1.OfType(); 28 | fluentAPI.SetBinding(gridView1, gView => gView.LoadingPanelVisible, x => x.IsLoading); 29 | fluentAPI.SetBinding(gridControl1, gControl => gControl.DataSource, x => x.Entities); 30 | 31 | fluentAPI.WithEvent(gridView1, "FocusedRowObjectChanged") 32 | .SetBinding(x => x.SelectedEntity, 33 | args => args.Row as DataModels.Account, 34 | (gView, entity) => gView.FocusedRowHandle = gView.FindRow(entity)); 35 | fluentAPI.WithEvent(gridView1, "RowCellClick") 36 | .EventToCommand( 37 | x => x.Edit(null), x => x.SelectedEntity, 38 | args => (args.Clicks == 2) && (args.Button == MouseButtons.Left)); 39 | 40 | fluentAPI.WithEvent(gridView1, "SelectionChanged") 41 | .SetBinding(x => x.Selection, e => GetSelectedAccounts()); 42 | } 43 | 44 | IEnumerable GetSelectedAccounts() { 45 | return gridView1.GetSelectedRows().Select(r => gridView1.GetRow(r) as MVVMExpenses.DataModels.Account); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /CS/MVVMExpenses/Views/Category/CategoriesEditFormView.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Drawing; 5 | using System.Data; 6 | using System.Text; 7 | using System.Linq; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | using DevExpress.XtraEditors; 11 | using MVVMExpenses.Models; 12 | using MVVMExpenses.Models.ViewModels; 13 | using DevExpress.XtraGrid.Views.Grid; 14 | 15 | namespace MVVMExpenses.Common.Views.Category { 16 | [DevExpress.Utils.MVVM.UI.ViewType("CategoryView")] 17 | public partial class CategoriesEditFormView : DevExpress.XtraEditors.XtraUserControl { 18 | public CategoriesEditFormView() { 19 | InitializeComponent(); 20 | this.TypeImageComboBoxEdit.Properties.Items.AddEnum(); 21 | if(!DesignMode) InitBindings(); 22 | } 23 | 24 | void InitBindings() { 25 | var fluent = mvvmContext1.OfType(); 26 | fluent.SetObjectDataSourceBinding( 27 | categoryBindingSource, x => x.Entity, x => x.Update()); 28 | 29 | fluent.SetBinding( 30 | gridControl1, gc => gc.DataSource, x => x.CategoryTransactionDetails.Entities); 31 | 32 | ((GridView)gridControl1.MainView).OptionsBehavior.Editable = false; 33 | ((GridView)gridControl1.MainView).Columns["Category"].Visible = false; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /CS/MVVMExpenses/Views/Category/CategoriesView.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Drawing; 5 | using System.Data; 6 | using System.Text; 7 | using System.Linq; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | using DevExpress.XtraEditors; 11 | using DevExpress.Utils.MVVM.Services; 12 | using MVVMExpenses.Models.ViewModels; 13 | 14 | namespace MVVMExpenses.Common.Views.Category { 15 | [DevExpress.Utils.MVVM.UI.ViewType("CategoryCollectionView")] 16 | public partial class CategoriesView : DevExpress.XtraEditors.XtraUserControl { 17 | public CategoriesView() { 18 | InitializeComponent(); 19 | if(!DesignMode) 20 | InitBindings(); 21 | gridView1.OptionsBehavior.Editable = false; 22 | gridView1.OptionsSelection.MultiSelect = true; 23 | gridView1.OptionsSelection.MultiSelectMode = DevExpress.XtraGrid.Views.Grid.GridMultiSelectMode.RowSelect; 24 | } 25 | 26 | void InitBindings() { 27 | var fluentAPI = mvvmContext1.OfType(); 28 | fluentAPI.SetBinding(gridView1, gView => gView.LoadingPanelVisible, x => x.IsLoading); 29 | fluentAPI.SetBinding(gridControl1, gControl => gControl.DataSource, x => x.Entities); 30 | 31 | fluentAPI.WithEvent(gridView1, "FocusedRowObjectChanged") 32 | .SetBinding(x => x.SelectedEntity, 33 | args => args.Row as DataModels.Category, 34 | (gView, entity) => gView.FocusedRowHandle = gView.FindRow(entity)); 35 | fluentAPI.WithEvent(gridView1, "RowCellClick") 36 | .EventToCommand( 37 | x => x.Edit(null), x => x.SelectedEntity, 38 | args => (args.Clicks == 2) && (args.Button == MouseButtons.Left)); 39 | 40 | fluentAPI.WithEvent(gridView1, "SelectionChanged") 41 | .SetBinding(x => x.Selection, e => GetSelectedCategories()); 42 | } 43 | 44 | IEnumerable GetSelectedCategories() { 45 | return gridView1.GetSelectedRows().Select(r => gridView1.GetRow(r) as MVVMExpenses.DataModels.Category); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /CS/MVVMExpenses/Views/LoginView.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Drawing; 5 | using System.Data; 6 | using System.Text; 7 | using System.Linq; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | using DevExpress.XtraEditors; 11 | using MVVMExpenses.ViewModels; 12 | 13 | namespace MVVMExpenses.Views { 14 | public partial class LoginView : DevExpress.XtraEditors.XtraUserControl { 15 | public LoginView() { 16 | InitializeComponent(); 17 | PasswordTextEdit.Properties.PasswordChar = '*'; 18 | } 19 | 20 | protected override void OnLoad(System.EventArgs e) { 21 | base.OnLoad(e); 22 | var fluentAPI = mvvmContext1.OfType(); 23 | fluentAPI.SetObjectDataSourceBinding(userBindingSource, 24 | x => x.CurrentUser, x => x.Update()); 25 | 26 | 27 | foreach(string item in mvvmContext1.GetViewModel().LookUpUsers) 28 | LoginTextEdit.Properties.Items.Add(item); 29 | fluentAPI.ViewModel.Init(); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /CS/MVVMExpenses/Views/MainView.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Windows.Forms; 4 | using DevExpress.Mvvm; 5 | using DevExpress.XtraEditors; 6 | using MVVMExpenses.Models.ViewModels; 7 | 8 | namespace MVVMExpenses { 9 | public partial class MainView : XtraForm { 10 | public MainView() { 11 | InitializeComponent(); 12 | this.Opacity = 0; 13 | if(!DesignMode) 14 | InitializeNavigation(); 15 | ribbonControl1.Merge += ribbonControl1_Merge; 16 | } 17 | void ribbonControl1_Merge(object sender, DevExpress.XtraBars.Ribbon.RibbonMergeEventArgs e) { 18 | ribbonControl1.SelectedPage = e.MergedChild.SelectedPage; 19 | } 20 | void InitializeNavigation() { 21 | var fluentAPI = mvvmContext1.OfType(); 22 | fluentAPI.BindCommand(biAccounts, (x, m) => x.Show(m), x => x.Modules[0]); 23 | fluentAPI.BindCommand(biCategories, (x, m) => x.Show(m), x => x.Modules[1]); 24 | fluentAPI.BindCommand(biTransactions, (x, m) => x.Show(m), x => x.Modules[2]); 25 | // 26 | fluentAPI.BindCommand(biLogout, x => x.Logout()); 27 | // 28 | fluentAPI.WithEvent(this, "Load") 29 | .EventToCommand(x => x.OnLoaded(null), x => x.DefaultModule); 30 | fluentAPI.WithEvent(this, "FormClosing") 31 | .EventToCommand(x => x.OnClosing(null), new Func((args) => args)); 32 | fluentAPI.SetTrigger(x => x.State, (state) => 33 | { 34 | if(state == AppState.Authorized) 35 | Opacity = 1; /*Show Main Form*/ 36 | if(state == AppState.ExitQueued) 37 | Close(); // exit the app; 38 | }); 39 | Messenger.Default.Register(this, OnUserNameMessage); 40 | } 41 | void OnUserNameMessage(string userName) { 42 | if(string.IsNullOrEmpty(userName)) 43 | this.Text = "Expenses Application"; 44 | else 45 | this.Text = "Expenses Application - (" + userName + ")"; 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /CS/MVVMExpenses/Views/Transaction/TransactionsEditFormView.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Drawing; 5 | using System.Data; 6 | using System.Text; 7 | using System.Linq; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | using DevExpress.XtraEditors; 11 | using MVVMExpenses.Models.ViewModels; 12 | 13 | namespace MVVMExpenses.Common.Views.Transaction { 14 | [DevExpress.Utils.MVVM.UI.ViewType("TransactionView")] 15 | public partial class TransactionsEditFormView : DevExpress.XtraEditors.XtraUserControl { 16 | public TransactionsEditFormView() { 17 | InitializeComponent(); 18 | if(!DesignMode) 19 | InitBindings(); 20 | } 21 | 22 | void InitBindings() { 23 | var fluent = mvvmContext1.OfType(); 24 | fluent.SetObjectDataSourceBinding( 25 | bindingSource, x => x.Entity, x => x.Update()); 26 | fluent.SetBinding(accountBindingSource, 27 | abs => abs.DataSource, x => x.LookUpAccounts.Entities); 28 | fluent.SetBinding(categoryBindingSource, 29 | cbs => cbs.DataSource, x => x.LookUpCategories.Entities); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /CS/MVVMExpenses/Views/Transaction/TransactionsView.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Drawing; 5 | using System.Data; 6 | using System.Text; 7 | using System.Linq; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | using DevExpress.XtraEditors; 11 | using MVVMExpenses.Models.ViewModels; 12 | using DevExpress.XtraGrid.Views.Base; 13 | using DevExpress.XtraGrid.Views.Grid; 14 | 15 | namespace MVVMExpenses.Common.Views.Transaction { 16 | [DevExpress.Utils.MVVM.UI.ViewType("TransactionCollectionView")] 17 | public partial class TransactionsView : DevExpress.XtraEditors.XtraUserControl { 18 | public TransactionsView() { 19 | InitializeComponent(); 20 | if(!DesignMode) 21 | InitBindings(); 22 | gridView1.OptionsBehavior.Editable = false; 23 | gridView1.OptionsSelection.MultiSelect = true; 24 | gridView1.OptionsSelection.MultiSelectMode = DevExpress.XtraGrid.Views.Grid.GridMultiSelectMode.RowSelect; 25 | } 26 | 27 | void InitBindings() { 28 | var fluentAPI = mvvmContext1.OfType(); 29 | fluentAPI.SetBinding(gridView1, gView => gView.LoadingPanelVisible, x => x.IsLoading); 30 | fluentAPI.SetBinding(gridControl1, gControl => gControl.DataSource, x => x.Entities); 31 | 32 | fluentAPI.WithEvent(gridView1, "FocusedRowObjectChanged") 33 | .SetBinding(x => x.SelectedEntity, 34 | args => args.Row as DataModels.Transaction, 35 | (gView, entity) => gView.FocusedRowHandle = gView.FindRow(entity)); 36 | fluentAPI.WithEvent(gridView1, "RowCellClick") 37 | .EventToCommand( 38 | x => x.Edit(null), x => x.SelectedEntity, 39 | args => (args.Clicks == 2) && (args.Button == MouseButtons.Left)); 40 | fluentAPI.WithEvent(gridView1, "SelectionChanged") 41 | .SetBinding(x => x.Selection, e => GetSelectedCategories()); 42 | } 43 | 44 | IEnumerable GetSelectedCategories() { 45 | return gridView1.GetSelectedRows().Select(r => gridView1.GetRow(r) as MVVMExpenses.DataModels.Transaction); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /CS/MVVMExpenses/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /CS/MVVMExpenses/sqlite/System.Data.SQLite.EF6.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevExpress-Examples/winforms-mvvm-expenses-app/70a139e6d5909c97e63090201977325d1be58b9a/CS/MVVMExpenses/sqlite/System.Data.SQLite.EF6.dll -------------------------------------------------------------------------------- /CS/MVVMExpenses/sqlite/System.Data.SQLite.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevExpress-Examples/winforms-mvvm-expenses-app/70a139e6d5909c97e63090201977325d1be58b9a/CS/MVVMExpenses/sqlite/System.Data.SQLite.dll -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This code example is provided "as is" without warranty of any kind. Developer Express Inc ("DevExpress") disclaims all warranties, 2 | either express or implied, including the warranties of merchantability and fitness for a particular purpose. 3 | 4 | For licensing terms and conditions of DevExpress product(s) required for, or associated with the use of this code example, 5 | please refer to the applicable End-User License Agreement at https://www.devexpress.com/Support/licensingfaq.xml -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | 2 | ![](https://img.shields.io/endpoint?url=https://codecentral.devexpress.com/api/v1/VersionRange/128614890/24.2.1%2B) 3 | [![](https://img.shields.io/badge/Open_in_DevExpress_Support_Center-FF7200?style=flat-square&logo=DevExpress&logoColor=white)](https://supportcenter.devexpress.com/ticket/details/T254492) 4 | [![](https://img.shields.io/badge/📖_How_to_use_DevExpress_Examples-e9f6fc?style=flat-square)](https://docs.devexpress.com/GeneralInformation/403183) 5 | [![](https://img.shields.io/badge/💬_Leave_Feedback-feecdd?style=flat-square)](#does-this-example-address-your-development-requirementsobjectives) 6 | 7 | # MVVM Expenses - Sample Application for WinForms 8 | 9 | 10 | **MVVM Expenses** is a sample money management application built with the DevExpress MVVM Framework. The application includes three modules, each bound to a related data source: "Accounts", "Categories", and "Transactions": 11 | 12 | * *Accounts* displays a list of user bank accounts. 13 | * *Categories* stores a list of transaction categories. 14 | * *Transactions* stores a list of all deposit and withdrawal operations. Each transaction references a specific Account and Category by their IDs. 15 | 16 | To log in, use one of the following credentials: 17 | 18 | * Administrator - admin 19 | * John - qwerty 20 | * Mary - 12345 21 | * Guest - *(no password set)* 22 | 23 | ## Documentation 24 | 25 | * [MVVM Step-by-Step Tutorials](https://documentation.devexpress.com/#WindowsForms/CustomDocument114101) 26 | * [DevExpress MVVM Framework (WinForms)](https://docs.devexpress.com/WindowsForms/113955/build-an-application/winforms-mvvm) 27 | 28 | 29 | 30 | ## Does this example address your development requirements/objectives? 31 | 32 | [](https://www.devexpress.com/support/examples/survey.xml?utm_source=github&utm_campaign=winforms-mvvm-expenses-app&~~~was_helpful=yes) [](https://www.devexpress.com/support/examples/survey.xml?utm_source=github&utm_campaign=winforms-mvvm-expenses-app&~~~was_helpful=no) 33 | 34 | (you will be redirected to DevExpress.com to submit your response) 35 | 36 | -------------------------------------------------------------------------------- /VB/MVVMExpenses.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio 2012 3 | Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "MVVMExpenses", "MVVMExpenses\MVVMExpenses.vbproj", "{E7AE86FF-3BDC-43E1-A33A-63A6970D3670}" 4 | EndProject 5 | Global 6 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 7 | Debug|Any CPU = Debug|Any CPU 8 | Release|Any CPU = Release|Any CPU 9 | EndGlobalSection 10 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 11 | {E7AE86FF-3BDC-43E1-A33A-63A6970D3670}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 12 | {E7AE86FF-3BDC-43E1-A33A-63A6970D3670}.Debug|Any CPU.Build.0 = Debug|Any CPU 13 | {E7AE86FF-3BDC-43E1-A33A-63A6970D3670}.Release|Any CPU.ActiveCfg = Release|Any CPU 14 | {E7AE86FF-3BDC-43E1-A33A-63A6970D3670}.Release|Any CPU.Build.0 = Release|Any CPU 15 | EndGlobalSection 16 | GlobalSection(SolutionProperties) = preSolution 17 | HideSolutionNode = FALSE 18 | EndGlobalSection 19 | EndGlobal 20 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/AppIcon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevExpress-Examples/winforms-mvvm-expenses-app/70a139e6d5909c97e63090201977325d1be58b9a/VB/MVVMExpenses/AppIcon.ico -------------------------------------------------------------------------------- /VB/MVVMExpenses/Common/AppIcon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevExpress-Examples/winforms-mvvm-expenses-app/70a139e6d5909c97e63090201977325d1be58b9a/VB/MVVMExpenses/Common/AppIcon.ico -------------------------------------------------------------------------------- /VB/MVVMExpenses/Common/DataModel/DbExceptions.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Linq 3 | Namespace Common.DataModel 4 | ''' 5 | ''' The database-independent exception used in Data Layer and View Model Layer to handle database errors. 6 | ''' 7 | Public Class DbException 8 | Inherits Exception 9 | Private _ErrorCaption As String 10 | Private _ErrorMessage As String 11 | ''' 12 | ''' Initializes a new instance of the DbRepository class. 13 | ''' 14 | ''' An error message text. 15 | ''' An error message caption text. 16 | ''' An underlying exception. 17 | Public Sub New(ByVal errorMessage As String, ByVal errorCaption As String, ByVal innerException As Exception) 18 | MyBase.New(innerException.Message, innerException) 19 | Me._ErrorMessage = errorMessage 20 | Me._ErrorCaption = errorCaption 21 | End Sub 22 | ''' The error message text. 23 | Public ReadOnly Property ErrorMessage As String 24 | Get 25 | Return _ErrorMessage 26 | End Get 27 | End Property 28 | ''' The error message caption text. 29 | Public ReadOnly Property ErrorCaption As String 30 | Get 31 | Return _ErrorCaption 32 | End Get 33 | End Property 34 | End Class 35 | End Namespace 36 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/Common/DataModel/EntityFramework/DbExceptionsConverter.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Data.Entity.Infrastructure 3 | Imports System.Data.Entity.Validation 4 | Imports System.Linq 5 | Imports System.Text 6 | Namespace Common.DataModel.EntityFramework 7 | ''' 8 | ''' Provides methods to convert Entity Framework exceptions to database-independent exceptions used in Data Layer and View Model Layer. 9 | ''' 10 | Public Module DbExceptionsConverter 11 | ''' 12 | ''' Converts System.Data.Entity.Infrastructure.DbUpdateException exception to database-independent DbException exception used in Data Layer and View Model Layer. 13 | ''' 14 | ''' Exception to convert. 15 | Public Function Convert(ByVal exception As DbUpdateException) As DbException 16 | Dim originalException As Exception = exception 17 | While originalException.InnerException IsNot Nothing 18 | originalException = originalException.InnerException 19 | End While 20 | Return New DbException(originalException.Message, CommonResources.Exception_UpdateErrorCaption, exception) 21 | End Function 22 | ''' 23 | ''' Converts System.Data.Entity.Validation.DbEntityValidationException exception to database-independent DbException exception used in Data Layer and View Model Layer. 24 | ''' 25 | ''' Exception to convert. 26 | Public Function Convert(ByVal exception As DbEntityValidationException) As DbException 27 | Dim stringBuilder As StringBuilder = New StringBuilder() 28 | For Each validationResult As DbEntityValidationResult In exception.EntityValidationErrors 29 | For Each [error] As DbValidationError In validationResult.ValidationErrors 30 | If stringBuilder.Length > 0 Then 31 | stringBuilder.AppendLine() 32 | End If 33 | stringBuilder.Append([error].PropertyName + ": " + [error].ErrorMessage) 34 | Next 35 | Next 36 | Return New DbException(stringBuilder.ToString(), CommonResources.Exception_ValidationErrorCaption, exception) 37 | End Function 38 | End Module 39 | End Namespace 40 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/Common/DataModel/EntityFramework/DbReadOnlyRepository.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Linq 3 | Imports System.Linq.Expressions 4 | Imports System.Data.Entity 5 | Imports System.Collections.Generic 6 | Imports System.Collections.ObjectModel 7 | Namespace Common.DataModel.EntityFramework 8 | ''' 9 | ''' A DbReadOnlyRepository is a IReadOnlyRepository interface implementation representing the collection of all entities in the unit of work, or that can be queried from the database, of a given type. 10 | ''' DbReadOnlyRepository objects are created from a DbUnitOfWork using the GetReadOnlyRepository method. 11 | ''' DbReadOnlyRepository provides only read-only operations against entities of a given type. 12 | ''' 13 | ''' Repository entity type. 14 | ''' DbContext type. 15 | Public Class DbReadOnlyRepository(Of TEntity As Class, TDbContext As DbContext) 16 | Inherits DbRepositoryQuery(Of TEntity) 17 | Implements IReadOnlyRepository(Of TEntity) 18 | Private ReadOnly _dbSetAccessor As Func(Of TDbContext, DbSet(Of TEntity)) 19 | Private ReadOnly _unitOfWork As DbUnitOfWork(Of TDbContext) 20 | ''' 21 | ''' Initializes a new instance of DbReadOnlyRepository class. 22 | ''' 23 | ''' Owner unit of work that provides context for repository entities. 24 | ''' Function that returns DbSet entities from Entity Framework DbContext. 25 | Public Sub New(ByVal unitOfWork As DbUnitOfWork(Of TDbContext), ByVal dbSetAccessor As Func(Of TDbContext, DbSet(Of TEntity))) 26 | MyBase.New(Function() dbSetAccessor(unitOfWork.Context)) 27 | Me._dbSetAccessor = dbSetAccessor 28 | Me._unitOfWork = unitOfWork 29 | End Sub 30 | Protected ReadOnly Property DbSet As DbSet(Of TEntity) 31 | Get 32 | Return _dbSetAccessor(_unitOfWork.Context) 33 | End Get 34 | End Property 35 | Protected ReadOnly Property Context As TDbContext 36 | Get 37 | Return _unitOfWork.Context 38 | End Get 39 | End Property 40 | Private ReadOnly Property UnitOfWork As IUnitOfWork Implements IReadOnlyRepository(Of TEntity).UnitOfWork 41 | Get 42 | Return _unitOfWork 43 | End Get 44 | End Property 45 | End Class 46 | ''' 47 | ''' DbRepositoryQuery is an IRepositoryQuery interface implementation that is an extension of IQueryable designed to specify the related objects to include in query results. 48 | ''' 49 | ''' An entity type. 50 | Public Class DbRepositoryQuery(Of TEntity As Class) 51 | Inherits RepositoryQueryBase(Of TEntity) 52 | Implements IRepositoryQuery(Of TEntity) 53 | ''' 54 | ''' Initializes a new instance of the DesignTimeRepositoryQuery class. 55 | ''' 56 | ''' A function that returns an IQueryable instance which is used by DbRepositoryQuery to perform queries. 57 | Public Sub New(ByVal getQueryable As Func(Of IQueryable(Of TEntity))) 58 | MyBase.New(getQueryable) 59 | End Sub 60 | Private Function Include(Of TProperty)(ByVal path As Expression(Of Func(Of TEntity, TProperty))) As IRepositoryQuery(Of TEntity) Implements IRepositoryQuery(Of TEntity).Include 61 | Return New DbRepositoryQuery(Of TEntity)(Function() Queryable.Include(path)) 62 | End Function 63 | Private Function Where(ByVal predicate As Expression(Of Func(Of TEntity, Boolean))) As IRepositoryQuery(Of TEntity) Implements IRepositoryQuery(Of TEntity).Where 64 | Return New DbRepositoryQuery(Of TEntity)(Function() Queryable.Where(predicate)) 65 | End Function 66 | End Class 67 | End Namespace 68 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/Common/DataModel/EntityFramework/DbUnitOfWork.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Collections.Generic 3 | Imports System.Data.Entity 4 | Imports System.Data.Entity.Validation 5 | Imports System.Data.Entity.Infrastructure 6 | Imports System.Linq 7 | Imports System.Linq.Expressions 8 | Namespace Common.DataModel.EntityFramework 9 | ''' 10 | ''' A DbUnitOfWork instance represents the implementation of the Unit Of Work pattern 11 | ''' such that it can be used to query from a database and group together changes that will then be written back to the store as a unit. 12 | ''' 13 | ''' DbContext type. 14 | Public MustInherit Class DbUnitOfWork(Of TContext As DbContext) 15 | Inherits UnitOfWorkBase 16 | Implements IUnitOfWork 17 | Private ReadOnly _context As Lazy(Of TContext) 18 | Public Sub New(ByVal contextFactory As Func(Of TContext)) 19 | _context = New Lazy(Of TContext)(contextFactory) 20 | End Sub 21 | ''' 22 | ''' Instance of underlying DbContext. 23 | ''' 24 | Public ReadOnly Property Context As TContext 25 | Get 26 | Return _context.Value 27 | End Get 28 | End Property 29 | Private Sub SaveChanges() Implements IUnitOfWork.SaveChanges 30 | Try 31 | Context.SaveChanges() 32 | Catch ex As DbEntityValidationException 33 | Throw DbExceptionsConverter.Convert(ex) 34 | Catch ex As DbUpdateException 35 | Throw DbExceptionsConverter.Convert(ex) 36 | End Try 37 | End Sub 38 | Private Function HasChanges() As Boolean Implements IUnitOfWork.HasChanges 39 | Return Context.ChangeTracker.HasChanges() 40 | End Function 41 | Protected Function GetRepository(Of TEntity As Class, TPrimaryKey)(ByVal dbSetAccessor As Func(Of TContext, DbSet(Of TEntity)), ByVal getPrimaryKeyExpression As Expression(Of Func(Of TEntity, TPrimaryKey))) As IRepository(Of TEntity, TPrimaryKey) 42 | Return GetRepositoryCore(Of IRepository(Of TEntity, TPrimaryKey), TEntity)(Function() New DbRepository(Of TEntity, TPrimaryKey, TContext)(Me, dbSetAccessor, getPrimaryKeyExpression)) 43 | End Function 44 | Protected Function GetReadOnlyRepository(Of TEntity As Class)(ByVal dbSetAccessor As Func(Of TContext, DbSet(Of TEntity))) As IReadOnlyRepository(Of TEntity) 45 | Return GetRepositoryCore(Of IReadOnlyRepository(Of TEntity), TEntity)(Function() New DbReadOnlyRepository(Of TEntity, TContext)(Me, dbSetAccessor)) 46 | End Function 47 | End Class 48 | End Namespace 49 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/Common/DataModel/EntityFramework/DbUnitOfWorkFactory.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Linq 3 | Imports System.Data 4 | Imports System.Data.Entity 5 | Imports System.Linq.Expressions 6 | Imports System.Collections.Generic 7 | Imports Common.Utils 8 | Imports Common.DataModel 9 | Imports DevExpress.Mvvm 10 | Imports System.Collections 11 | Imports System.ComponentModel 12 | Imports DevExpress.Data.Linq 13 | Imports DevExpress.Data.Linq.Helpers 14 | Imports DevExpress.Data.Async.Helpers 15 | Namespace Common.DataModel.EntityFramework 16 | Friend Class DbUnitOfWorkFactory(Of TUnitOfWork As IUnitOfWork) 17 | Implements IUnitOfWorkFactory(Of TUnitOfWork) 18 | Private _createUnitOfWork As Func(Of TUnitOfWork) 19 | Public Sub New(ByVal createUnitOfWork As Func(Of TUnitOfWork)) 20 | Me._createUnitOfWork = createUnitOfWork 21 | End Sub 22 | Private Function CreateUnitOfWork() As TUnitOfWork Implements IUnitOfWorkFactory(Of TUnitOfWork).CreateUnitOfWork 23 | Return _createUnitOfWork() 24 | End Function 25 | Private Function CreateInstantFeedbackSource(Of TEntity As {Class, New}, TProjection As Class, TPrimaryKey)(ByVal getRepositoryFunc As Func(Of TUnitOfWork, IRepository(Of TEntity, TPrimaryKey)), ByVal projection As Func(Of IRepositoryQuery(Of TEntity), IQueryable(Of TProjection))) As IInstantFeedbackSource(Of TProjection) Implements IUnitOfWorkFactory(Of TUnitOfWork).CreateInstantFeedbackSource 26 | Dim threadSafeProperties = New TypeInfoProxied(TypeDescriptor.GetProperties(GetType(TProjection)), Nothing).UIDescriptors 27 | If projection Is Nothing Then 28 | projection = Function(x) TryCast(x, IQueryable(Of TProjection)) 29 | End If 30 | Dim source = New EntityInstantFeedbackSource(Sub(e As GetQueryableEventArgs) e.QueryableSource = projection(getRepositoryFunc(_createUnitOfWork()))) With {.KeyExpression = getRepositoryFunc(_createUnitOfWork()).GetPrimaryKeyPropertyName()} 31 | Return New InstantFeedbackSource(Of TProjection)(source, threadSafeProperties) 32 | End Function 33 | End Class 34 | End Namespace 35 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/Common/DataModel/EntityFramework/InstantFeedbackSource.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Linq 3 | Imports System.Data 4 | Imports System.Data.Entity 5 | Imports System.Linq.Expressions 6 | Imports System.Collections.Generic 7 | Imports Common.Utils 8 | Imports Common.DataModel 9 | Imports DevExpress.Mvvm 10 | Imports System.Collections 11 | Imports System.ComponentModel 12 | Imports DevExpress.Data.Linq 13 | Imports DevExpress.Data.Linq.Helpers 14 | Imports DevExpress.Data.Async.Helpers 15 | Namespace Common.DataModel.EntityFramework 16 | Friend Class InstantFeedbackSource(Of TEntity As Class) 17 | Implements IInstantFeedbackSource(Of TEntity) 18 | Private ReadOnly _source As EntityInstantFeedbackSource 19 | Private ReadOnly _threadSafeProperties As PropertyDescriptorCollection 20 | Public Sub New(ByVal source As EntityInstantFeedbackSource, ByVal threadSafeProperties As PropertyDescriptorCollection) 21 | Me._source = source 22 | Me._threadSafeProperties = threadSafeProperties 23 | End Sub 24 | Private ReadOnly Property ContainsListCollection As Boolean Implements IListSource.ContainsListCollection 25 | Get 26 | Return CType(_source, IListSource).ContainsListCollection 27 | End Get 28 | End Property 29 | Private Function GetList() As IList Implements IListSource.GetList 30 | Return CType(_source, IListSource).GetList() 31 | End Function 32 | Private Function GetPropertyValue(Of TProperty)(ByVal threadSafeProxy As Object, ByVal propertyExpression As Expression(Of Func(Of TEntity, TProperty))) As TProperty Implements IInstantFeedbackSource(Of TEntity).GetPropertyValue 33 | Dim propertyName = ExpressionHelper.GetPropertyName(propertyExpression) 34 | Dim threadSafeProperty = _threadSafeProperties(propertyName) 35 | Return CType(threadSafeProperty.GetValue(threadSafeProxy), TProperty) 36 | End Function 37 | Private Function IsLoadedProxy(ByVal threadSafeProxy As Object) As Boolean Implements IInstantFeedbackSource(Of TEntity).IsLoadedProxy 38 | Return TypeOf threadSafeProxy Is ReadonlyThreadSafeProxyForObjectFromAnotherThread 39 | End Function 40 | Private Sub Refresh() Implements IInstantFeedbackSource(Of TEntity).Refresh 41 | _source.Refresh() 42 | End Sub 43 | End Class 44 | End Namespace 45 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/Common/DataModel/EntityState.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Linq 3 | Namespace Common.DataModel 4 | ''' 5 | ''' Represents the state of the entity relative to the unit of work. 6 | ''' 7 | Public Enum EntityState 8 | ''' 9 | ''' The object exists but is not being tracked. 10 | ''' An entity is in this state immediately after it has been created and before it is added to the unit of work. 11 | ''' An entity is also in this state after it has been removed from the unit of work by calling the IUnitOfWork.Detach method. 12 | ''' 13 | Detached = 1 14 | ''' 15 | ''' The object has not been modified since it was attached to the unit of work or since the last time that the IUnitOfWork.SaveChanges method was called. 16 | ''' 17 | Unchanged = 2 18 | ''' 19 | ''' The object is new, has been added to the unit of work, and the IUnitOfWork.SaveChanges method has not been called. 20 | ''' After the changes are saved, the object state changes to Unchanged. 21 | ''' 22 | Added = 4 23 | ''' 24 | ''' The object has been deleted from the unit of work. After the changes are saved, the object state changes to Detached. 25 | ''' 26 | Deleted = 8 27 | ''' 28 | ''' One of the scalar properties on the object has been modified and the IUnitOfWork.SaveChanges method has not been called. 29 | ''' After the changes are saved, the object state changes to Unchanged. 30 | ''' 31 | Modified = 16 32 | End Enum 33 | End Namespace 34 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/Common/DataModel/IUnitOfWork.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.ComponentModel 3 | Imports System.Linq 4 | Imports System.Linq.Expressions 5 | Namespace Common.DataModel 6 | ''' 7 | ''' The IUnitOfWork interface represents the Unit Of Work pattern 8 | ''' such that it can be used to query from a database and group together changes that will then be written back to the store as a unit. 9 | ''' 10 | Public Interface IUnitOfWork 11 | ''' 12 | ''' Saves all changes made in this unit of work to the underlying store. 13 | ''' 14 | Sub SaveChanges() 15 | ''' 16 | ''' Checks if the unit of work is tracking any new, deleted, or changed entities or relationships that will be sent to the store if SaveChanges() is called. 17 | ''' 18 | Function HasChanges() As Boolean 19 | End Interface 20 | ''' 21 | ''' Provides the method to create a unit of work of a given type. 22 | ''' 23 | ''' A unit of work type. 24 | Public Interface IUnitOfWorkFactory(Of TUnitOfWork As IUnitOfWork) 25 | ''' 26 | ''' Creates a new unit of work. 27 | ''' 28 | Function CreateUnitOfWork() As TUnitOfWork 29 | Function CreateInstantFeedbackSource(Of TEntity As {Class, New}, TProjection As Class, TPrimaryKey)(ByVal getRepositoryFunc As Func(Of TUnitOfWork, IRepository(Of TEntity, TPrimaryKey)), ByVal projection As Func(Of IRepositoryQuery(Of TEntity), IQueryable(Of TProjection))) As IInstantFeedbackSource(Of TProjection) 30 | End Interface 31 | Public Interface IInstantFeedbackSource(Of TEntity As Class) 32 | Inherits IListSource 33 | Sub Refresh() 34 | Function GetPropertyValue(Of TProperty)(ByVal threadSafeProxy As Object, ByVal propertyExpression As Expression(Of Func(Of TEntity, TProperty))) As TProperty 35 | Function IsLoadedProxy(ByVal threadSafeProxy As Object) As Boolean 36 | End Interface 37 | End Namespace 38 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/Common/DataModel/UnitOfWorkBase.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Linq 3 | Imports System.Collections.Generic 4 | Imports System.Linq.Expressions 5 | Namespace Common.DataModel 6 | ''' 7 | ''' The base class for unit of works that provides the storage for repositories. 8 | ''' 9 | Public Class UnitOfWorkBase 10 | Private ReadOnly _repositories As Dictionary(Of Type, Object) = New Dictionary(Of Type, Object)() 11 | Protected Function GetRepositoryCore(Of TRepository As IReadOnlyRepository(Of TEntity), TEntity As Class)(ByVal createRepositoryFunc As Func(Of TRepository)) As TRepository 12 | Dim result As Object = Nothing 13 | If Not _repositories.TryGetValue(GetType(TEntity), result) Then 14 | result = createRepositoryFunc() 15 | _repositories(GetType(TEntity)) = result 16 | End If 17 | Return CType(result, TRepository) 18 | End Function 19 | End Class 20 | End Namespace 21 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/Common/Utils/DbExtensions.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Collections 3 | Imports System.Linq 4 | Namespace Common.Utils 5 | ''' 6 | ''' Provides the extension method for implementations of the IQueryable interface. 7 | ''' 8 | Public Module DbExtensions 9 | ''' 10 | ''' Forces entities to be loaded locally from the IQueryable instance. 11 | ''' 12 | ''' An instance of the IQueryable interface from which to load entities. 13 | _ 14 | Public Sub Load(ByVal source As IQueryable) 15 | Dim enumerator As IEnumerator = source.GetEnumerator() 16 | While enumerator.MoveNext() 17 | End While 18 | End Sub 19 | End Module 20 | End Namespace 21 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/Common/ViewModel/ISingleObjectViewModel.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.ComponentModel.DataAnnotations 3 | Imports System.Linq 4 | Imports System.Linq.Expressions 5 | Imports DevExpress.Mvvm 6 | Imports DevExpress.Mvvm.POCO 7 | Imports DevExpress.Mvvm.DataAnnotations 8 | Imports Common.Utils 9 | Imports Common.DataModel 10 | Namespace Common.ViewModel 11 | ''' 12 | ''' The base interface for view models representing a single entity. 13 | ''' 14 | ''' An entity type. 15 | ''' An entity primary key type. 16 | Public Interface ISingleObjectViewModel(Of TEntity, TPrimaryKey) 17 | ''' 18 | ''' The entity represented by a view model. 19 | ''' 20 | ReadOnly Property Entity As TEntity 21 | ''' 22 | ''' The entity primary key value. 23 | ''' 24 | ReadOnly Property PrimaryKey As TPrimaryKey 25 | End Interface 26 | End Namespace 27 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/Common/ViewModel/LayoutSettings.Designer.vb: -------------------------------------------------------------------------------- 1 | '------------------------------------------------------------------------------ 2 | ' 3 | ' This code was generated by a tool. 4 | ' Runtime Version:4.0.30319.34209 5 | ' 6 | ' Changes to this file may cause incorrect behavior and will be lost if 7 | ' the code is regenerated. 8 | ' 9 | '------------------------------------------------------------------------------ 10 | 11 | Option Strict On 12 | Option Explicit On 13 | 14 | 15 | 16 | _ 18 | Partial Friend NotInheritable Class LayoutSettings 19 | Inherits Global.System.Configuration.ApplicationSettingsBase 20 | 21 | Private Shared defaultInstance As LayoutSettings = CType(Global.System.Configuration.ApplicationSettingsBase.Synchronized(New LayoutSettings()), LayoutSettings) 22 | 23 | Public Shared ReadOnly Property [Default]() As LayoutSettings 24 | Get 25 | Return defaultInstance 26 | End Get 27 | End Property 28 | 29 | _ 32 | Public Property LogicalLayout() As String 33 | Get 34 | Return CType(Me("LogicalLayout"), String) 35 | End Get 36 | Set(value As String) 37 | Me("LogicalLayout") = Value 38 | End Set 39 | End Property 40 | 41 | _ 44 | Public Property ViewsLayout() As String 45 | Get 46 | Return CType(Me("ViewsLayout"), String) 47 | End Get 48 | Set(value As String) 49 | Me("ViewsLayout") = Value 50 | End Set 51 | End Property 52 | End Class 53 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/Common/ViewModel/LayoutSettings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/Common/ViewModel/LookUpEntitiesViewModel.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Linq 3 | Imports System.ComponentModel 4 | Imports DevExpress.Mvvm 5 | Imports DevExpress.Mvvm.POCO 6 | Imports System.Collections.ObjectModel 7 | Imports Common.Utils 8 | Imports Common.DataModel 9 | Namespace Common.ViewModel 10 | ''' 11 | ''' Represents a POCO view models used by SingleObjectViewModel to exposing collections of related entities. 12 | ''' This is a partial class that provides an extension point to add custom properties, commands and override methods without modifying the auto-generated code. 13 | ''' 14 | ''' A repository entity type. 15 | ''' A projection entity type. 16 | ''' A primary key value type. 17 | ''' A unit of work type. 18 | Public Class LookUpEntitiesViewModel(Of TEntity As Class, TProjection As Class, TPrimaryKey, TUnitOfWork As IUnitOfWork) 19 | Inherits EntitiesViewModel(Of TEntity, TProjection, TUnitOfWork) 20 | Implements IDocumentContent 21 | ''' 22 | ''' Creates a new instance of LookUpEntitiesViewModel as a POCO view model. 23 | ''' 24 | ''' A factory used to create a unit of work instance. 25 | ''' A function that returns a repository representing entities of the given type. 26 | ''' An optional parameter that provides a LINQ function used to customize a query for entities. The parameter, for example, can be used for sorting data and/or for projecting data to a custom type that does not match the repository entity type. 27 | Public Shared Function Create(ByVal unitOfWorkFactory As IUnitOfWorkFactory(Of TUnitOfWork), ByVal getRepositoryFunc As Func(Of TUnitOfWork, IReadOnlyRepository(Of TEntity)), Optional ByVal projection As Func(Of IRepositoryQuery(Of TEntity), IQueryable(Of TProjection)) = Nothing) As LookUpEntitiesViewModel(Of TEntity, TProjection, TPrimaryKey, TUnitOfWork) 28 | Return ViewModelSource.Create(Function() New LookUpEntitiesViewModel(Of TEntity, TProjection, TPrimaryKey, TUnitOfWork)(unitOfWorkFactory, getRepositoryFunc, projection)) 29 | End Function 30 | ''' 31 | ''' Initializes a new instance of the LookUpEntitiesViewModel class. 32 | ''' This constructor is declared protected to avoid an undesired instantiation of the LookUpEntitiesViewModel type without the POCO proxy factory. 33 | ''' 34 | ''' A factory used to create a unit of work instance. 35 | ''' A function that returns a repository representing entities of the given type. 36 | ''' A LINQ function used to customize a query for entities. The parameter, for example, can be used for sorting data and/or for projecting data to a custom type that does not match the repository entity type. 37 | Protected Sub New(ByVal unitOfWorkFactory As IUnitOfWorkFactory(Of TUnitOfWork), ByVal getRepositoryFunc As Func(Of TUnitOfWork, IReadOnlyRepository(Of TEntity)), ByVal projection As Func(Of IRepositoryQuery(Of TEntity), IQueryable(Of TProjection))) 38 | MyBase.New(unitOfWorkFactory, getRepositoryFunc, projection) 39 | End Sub 40 | Protected Overrides Function CreateEntitiesChangeTracker() As IEntitiesChangeTracker 41 | Return New EntitiesChangeTracker(Of TPrimaryKey)(Me) 42 | End Function 43 | End Class 44 | End Namespace 45 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/Common/ViewModel/Messages.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Linq 3 | Imports System.ComponentModel 4 | Namespace Common.ViewModel 5 | ''' 6 | ''' Represents the type of an entity state change notification that is shown when the IUnitOfWork.SaveChanges method has been called. 7 | ''' 8 | Public Enum EntityMessageType 9 | ''' 10 | ''' A new entity has been added to the unit of work. 11 | ''' 12 | Added 13 | ''' 14 | ''' An entity has been removed from the unit of work. 15 | ''' 16 | Deleted 17 | ''' 18 | ''' One of the entity properties has been modified. 19 | ''' 20 | Changed 21 | End Enum 22 | ''' 23 | ''' Provides the information about an entity state change notification that is shown when an entity has been added, removed or modified, and the IUnitOfWork.SaveChanges method has been called. 24 | ''' 25 | ''' An entity type. 26 | ''' A primary key value type. 27 | Public Class EntityMessage(Of TEntity, TPrimaryKey) 28 | Private _MessageType As EntityMessageType 29 | Private _PrimaryKey As TPrimaryKey 30 | ''' 31 | ''' Initializes a new instance of the EntityMessage class. 32 | ''' 33 | ''' A primary key of an entity that has been added, removed or modified. 34 | ''' An entity state change notification type. 35 | Public Sub New(ByVal primaryKey As TPrimaryKey, ByVal messageType As EntityMessageType) 36 | Me._PrimaryKey = primaryKey 37 | Me._MessageType = messageType 38 | End Sub 39 | ''' 40 | ''' The primary key of entity that has been added, deleted or modified. 41 | ''' 42 | Public ReadOnly Property PrimaryKey As TPrimaryKey 43 | Get 44 | Return _PrimaryKey 45 | End Get 46 | End Property 47 | ''' 48 | ''' The entity state change notification type. 49 | ''' 50 | Public ReadOnly Property MessageType As EntityMessageType 51 | Get 52 | Return _MessageType 53 | End Get 54 | End Property 55 | End Class 56 | ''' 57 | ''' A message notifying that all view models should save changes. Usually sent by DocumentsViewModel when the SaveAll command is executed. 58 | ''' 59 | Public Class SaveAllMessage 60 | End Class 61 | ''' 62 | ''' A message notifying that all view models should close itself. Usually sent by DocumentsViewModel when the CloseAll command is executed. 63 | ''' 64 | Public Class CloseAllMessage 65 | Private ReadOnly _cancelEventArgs As CancelEventArgs 66 | ''' 67 | ''' Initializes a new instance of the CloseAllMessage class. 68 | ''' 69 | ''' An argument of the System.ComponentModel.CancelEventArgs type which can be used to cancel closing. 70 | Public Sub New(ByVal cancelEventArgs As CancelEventArgs) 71 | Me._cancelEventArgs = cancelEventArgs 72 | End Sub 73 | ''' 74 | ''' Used to cancel closing and check whether the closing has already been cancelled. 75 | ''' 76 | Public Property Cancel As Boolean 77 | Get 78 | Return _cancelEventArgs.Cancel 79 | End Get 80 | Set(value As Boolean) 81 | _cancelEventArgs.Cancel = value 82 | End Set 83 | End Property 84 | End Class 85 | Public Class DestroyOrphanedDocumentsMessage 86 | End Class 87 | ''' 88 | ''' Used by the PeekCollectionViewModel to notify that DocumentsViewModel should navigate to the specified module. 89 | ''' 90 | ''' The navigation token type. 91 | Public Class NavigateMessage(Of TNavigationToken) 92 | Private _Token As TNavigationToken 93 | ''' 94 | ''' Initializes a new instance of the NavigateMessage class. 95 | ''' 96 | ''' An object that is used to identify the module to which the DocumentsViewModel should navigate. 97 | Public Sub New(ByVal token As TNavigationToken) 98 | Me._Token = token 99 | End Sub 100 | ''' 101 | ''' An object that is used to identify the module to which the DocumentsViewModel should navigate. 102 | ''' 103 | Public ReadOnly Property Token As TNavigationToken 104 | Get 105 | Return _Token 106 | End Get 107 | End Property 108 | End Class 109 | End Namespace 110 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/Common/ViewModel/PeekCollectionViewModel.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.ComponentModel 3 | Imports System.ComponentModel.DataAnnotations 4 | Imports System.Collections.Generic 5 | Imports System.Linq 6 | Imports System.Linq.Expressions 7 | Imports DevExpress.Mvvm 8 | Imports DevExpress.Mvvm.POCO 9 | Imports DevExpress.Mvvm.DataAnnotations 10 | Imports Common.Utils 11 | Imports Common.DataModel 12 | Namespace Common.ViewModel 13 | ''' 14 | ''' A POCO view model exposing a read-only collection of entities of a given type. It is designed for quick navigation between collection views. 15 | ''' This is a partial class that provides an extension point to add custom properties, commands and override methods without modifying the auto-generated code. 16 | ''' 17 | ''' A navigation token type. 18 | ''' An entity type. 19 | ''' A primary key value type. 20 | ''' A unit of work type. 21 | Partial Public Class PeekCollectionViewModel(Of TNavigationToken, TEntity As Class, TPrimaryKey, TUnitOfWork As IUnitOfWork) 22 | Inherits CollectionViewModelBase(Of TEntity, TEntity, TPrimaryKey, TUnitOfWork) 23 | ''' 24 | ''' Creates a new instance of PeekCollectionViewModel as a POCO view model. 25 | ''' 26 | ''' Identifies the module that is the navigation target. 27 | ''' A factory that is used to create a unit of work instance. 28 | ''' A function that returns a repository representing entities of a given type. 29 | ''' An optional parameter that provides a LINQ function used to customize a query for entities. The parameter, for example, can be used for sorting data. 30 | Public Shared Function Create(ByVal navigationToken As TNavigationToken, ByVal unitOfWorkFactory As IUnitOfWorkFactory(Of TUnitOfWork), ByVal getRepositoryFunc As Func(Of TUnitOfWork, IRepository(Of TEntity, TPrimaryKey)), Optional ByVal projection As Func(Of IRepositoryQuery(Of TEntity), IQueryable(Of TEntity)) = Nothing) As PeekCollectionViewModel(Of TNavigationToken, TEntity, TPrimaryKey, TUnitOfWork) 31 | Return ViewModelSource.Create(Function() New PeekCollectionViewModel(Of TNavigationToken, TEntity, TPrimaryKey, TUnitOfWork)(navigationToken, unitOfWorkFactory, getRepositoryFunc, projection)) 32 | End Function 33 | Private _navigationToken As TNavigationToken 34 | Private _pickedEntity As TEntity 35 | ''' 36 | ''' Initializes a new instance of the PeekCollectionViewModel class. 37 | ''' This constructor is declared protected to avoid an undesired instantiation of the PeekCollectionViewModel type without the POCO proxy factory. 38 | ''' 39 | ''' Identifies the module that is the navigation target. 40 | ''' A factory that is used to create a unit of work instance. 41 | ''' A function that returns a repository representing entities of a given type. 42 | ''' An optional parameter that provides a LINQ function used to customize a query for entities. The parameter, for example, can be used for sorting data. 43 | Protected Sub New(ByVal navigationToken As TNavigationToken, ByVal unitOfWorkFactory As IUnitOfWorkFactory(Of TUnitOfWork), ByVal getRepositoryFunc As Func(Of TUnitOfWork, IRepository(Of TEntity, TPrimaryKey)), Optional ByVal projection As Func(Of IRepositoryQuery(Of TEntity), IQueryable(Of TEntity)) = Nothing) 44 | MyBase.New(unitOfWorkFactory, getRepositoryFunc, projection, Nothing, Nothing, True) 45 | Me._navigationToken = navigationToken 46 | End Sub 47 | ''' 48 | ''' Navigates to the corresponding collection view and selects the given entity. 49 | ''' Since PeekCollectionViewModel is a POCO view model, an instance of this class will also expose the NavigateCommand property that can be used as a binding source in views. 50 | ''' 51 | ''' An entity to select within the collection view. 52 | _ 53 | Public Sub Navigate(ByVal projectionEntity As TEntity) 54 | _pickedEntity = projectionEntity 55 | SendSelectEntityMessage() 56 | Messenger.[Default].Send(New NavigateMessage(Of TNavigationToken)(_navigationToken), _navigationToken) 57 | End Sub 58 | ''' 59 | ''' Determines if a navigation to corresponding collection view can be performed. 60 | ''' Since PeekCollectionViewModel is a POCO view model, this method will be used as a CanExecute callback for NavigateCommand. 61 | ''' 62 | ''' An entity to select in the collection view. 63 | Public Function CanNavigate(ByVal projectionEntity As TEntity) As Boolean 64 | Return projectionEntity IsNot Nothing 65 | End Function 66 | Protected Overrides Sub OnInitializeInRuntime() 67 | MyBase.OnInitializeInRuntime() 68 | Messenger.[Default].Register(Of SelectedEntityRequest)(Me, Sub(x) SendSelectEntityMessage()) 69 | End Sub 70 | Private Sub SendSelectEntityMessage() 71 | If IsLoaded AndAlso _pickedEntity IsNot Nothing Then 72 | Messenger.[Default].Send(New SelectEntityMessage(CreateRepository().GetProjectionPrimaryKey(_pickedEntity))) 73 | End If 74 | End Sub 75 | End Class 76 | End Namespace 77 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/Common/ViewModel/ViewModelLogicalLayoutHelper.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Collections.Generic 3 | Imports System.IO 4 | Imports System.Linq 5 | Imports System.Text 6 | Imports DevExpress.Mvvm 7 | Namespace Common.ViewModel 8 | Public Class ViewModelLogicalLayoutHelper 9 | Public Shared Property PersistentLogicalLayout As String 10 | Get 11 | Return LayoutSettings.[Default].LogicalLayout 12 | End Get 13 | Set(value As String) 14 | LayoutSettings.[Default].LogicalLayout = value 15 | End Set 16 | End Property 17 | Private Shared _persistentViewsLayout As Dictionary(Of String, String) 18 | Public Shared ReadOnly Property PersistentViewsLayout As Dictionary(Of String, String) 19 | Get 20 | If _persistentViewsLayout Is Nothing Then 21 | _persistentViewsLayout = LogicalLayoutSerializationHelper.Deserialize(LayoutSettings.[Default].ViewsLayout) 22 | End If 23 | Return _persistentViewsLayout 24 | End Get 25 | End Property 26 | Public Shared Sub SaveLayout() 27 | LayoutSettings.[Default].ViewsLayout = LogicalLayoutSerializationHelper.Serialize(PersistentViewsLayout) 28 | LayoutSettings.[Default].Save() 29 | End Sub 30 | Public Shared Sub ResetLayout() 31 | PersistentViewsLayout.Clear() 32 | PersistentLogicalLayout = Nothing 33 | SaveLayout() 34 | End Sub 35 | End Class 36 | End Namespace 37 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/Data/Expenses.sqlite3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevExpress-Examples/winforms-mvvm-expenses-app/70a139e6d5909c97e63090201977325d1be58b9a/VB/MVVMExpenses/Data/Expenses.sqlite3 -------------------------------------------------------------------------------- /VB/MVVMExpenses/DataBase/DbContext.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Collections.Generic 3 | Imports System.Linq 4 | Imports System.Text 5 | Imports System.Threading.Tasks 6 | Imports System.Data.Common 7 | Imports System.Data.Entity 8 | Imports System.Data.SQLite 9 | Imports System.IO 10 | Imports DevExpress.Internal 11 | Imports MVVMExpenses.DataModels 12 | Imports System.Data.Entity.Infrastructure 13 | Imports System.Data.SQLite.EF6 14 | Imports System.Data.Entity.Core.Common 15 | Imports System.Reflection 16 | 17 | Namespace MVVMExpenses.DataBase 18 | 19 | Public Class MyDbContext 20 | Inherits System.Data.Entity.DbContext 21 | Shared Sub New() 22 | System.Data.Entity.Database.SetInitializer(Of MyDbContext)(Nothing) 23 | End Sub 24 | 25 | Public Property Accounts() As DbSet(Of Account) 26 | Public Property Categories() As DbSet(Of Category) 27 | Public Property Transactions() As DbSet(Of Transaction) 28 | End Class 29 | End Namespace -------------------------------------------------------------------------------- /VB/MVVMExpenses/DataBase/MyDbSQLiteConfiguration.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Collections.Generic 3 | Imports System.Data.Common 4 | Imports System.Data.SQLite 5 | Imports System.Data.SQLite.EF6 6 | Imports System.IO 7 | Imports System.Linq 8 | Imports System.Text 9 | Imports System.Threading.Tasks 10 | Imports DevExpress.DocumentServices.ServiceModel.DataContracts.Xpf.Designer 11 | Imports DevExpress.Internal 12 | 13 | Namespace MVVMExpenses.Common.DataModel.EntityFramework 14 | Public Class SQLiteConnectionFactory 15 | Implements System.Data.Entity.Infrastructure.IDbConnectionFactory 16 | 17 | Private Shared filePath As String 18 | Public Function CreateConnection(ByVal nameOrConnectionString As String) As DbConnection Implements System.Data.Entity.Infrastructure.IDbConnectionFactory.CreateConnection 19 | If filePath Is Nothing Then 20 | filePath = DataDirectoryHelper.GetFile("expenses.sqlite3", DataDirectoryHelper.DataFolderName) 21 | File.SetAttributes(filePath, File.GetAttributes(filePath) And (Not FileAttributes.ReadOnly)) 22 | End If 23 | Return New SQLiteConnection(New SQLiteConnectionStringBuilder() With {.DataSource = filePath}.ConnectionString) 24 | End Function 25 | End Class 26 | 27 | Public Class MyDbSQLiteConfiguration 28 | Inherits System.Data.Entity.DbConfiguration 29 | 30 | Public Sub New() 31 | SetDefaultConnectionFactory(New SQLiteConnectionFactory()) 32 | SetProviderFactory("System.Data.SQLite", SQLiteFactory.Instance) 33 | SetProviderFactory("System.Data.SQLite.EF6", System.Data.SQLite.EF6.SQLiteProviderFactory.Instance) 34 | Dim t As Type = Type.GetType("System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6", True, True) 35 | Dim fi As System.Reflection.FieldInfo = t.GetField("Instance", System.Reflection.BindingFlags.NonPublic Or System.Reflection.BindingFlags.Static) 36 | SetProviderServices("System.Data.SQLite", DirectCast(fi.GetValue(Nothing), System.Data.Entity.Core.Common.DbProviderServices)) 37 | End Sub 38 | End Class 39 | End Namespace -------------------------------------------------------------------------------- /VB/MVVMExpenses/Models/Account.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Collections.Generic 3 | Imports System.Linq 4 | Imports System.Text 5 | Imports System.Threading.Tasks 6 | Imports System.ComponentModel.DataAnnotations 7 | 8 | Namespace MVVMExpenses.DataModels 9 | Public Class Account 10 | 11 | Public Property ID() As Long 12 | 13 | Public Property Name() As String 14 | 15 | Public Property Amount() As Decimal 16 | Public Overrides Function ToString() As String 17 | Return Name & " (" & Amount.ToString("C") & ")" 18 | End Function 19 | End Class 20 | End Namespace -------------------------------------------------------------------------------- /VB/MVVMExpenses/Models/Category.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Collections.Generic 3 | Imports System.Linq 4 | Imports System.Text 5 | Imports System.Threading.Tasks 6 | Imports System.ComponentModel.DataAnnotations 7 | 8 | Namespace MVVMExpenses.DataModels 9 | Public Class Category 10 | 11 | Public Property ID() As Long 12 | 13 | Public Property Name() As String 14 | 15 | Public Property Type() As TransactionType 16 | Public Overrides Function ToString() As String 17 | Return Name & " (" & Type.ToString() & ")" 18 | End Function 19 | End Class 20 | End Namespace -------------------------------------------------------------------------------- /VB/MVVMExpenses/Models/CredentialsSource.vb: -------------------------------------------------------------------------------- 1 | Imports System.Collections.Generic 2 | Imports DevExpress.Mvvm.POCO 3 | 4 | Namespace MVVMExpenses.Models 5 | ' 6 | ' TODO - your implementation 7 | Friend NotInheritable Class CredentialsSource 8 | 9 | Private Sub New() 10 | End Sub 11 | 12 | Private Shared credentials As System.Collections.Hashtable 13 | Shared Sub New() 14 | credentials = New System.Collections.Hashtable() 15 | credentials.Add("Guest", GetHash(Nothing)) 16 | credentials.Add("John", GetHash("qwerty")) 17 | credentials.Add("Administrator", GetHash("admin")) 18 | credentials.Add("Mary", GetHash("12345")) 19 | End Sub 20 | Friend Shared Function Check(ByVal login As String, ByVal pwd As String) As Boolean 21 | Return Object.Equals(credentials(login), GetHash(pwd)) 22 | End Function 23 | Private Shared Function GetHash(ByVal password As String) As Object 24 | Return password 25 | End Function 26 | Friend Shared Iterator Function GetUserNames() As System.Collections.Generic.IEnumerable(Of String) 27 | For Each item As String In credentials.Keys 28 | Yield item 29 | Next item 30 | End Function 31 | End Class 32 | End Namespace 33 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/Models/MyDbContextDataModel/IMyDbContextUnitOfWork.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Linq 3 | Imports System.Data 4 | Imports System.Data.Entity 5 | Imports System.Linq.Expressions 6 | Imports System.Collections.Generic 7 | Imports Common.Utils 8 | Imports Common.DataModel 9 | Imports Common.DataModel.EntityFramework 10 | Imports MVVMExpenses.DataBase 11 | Imports MVVMExpenses.DataModels 12 | Namespace MVVMExpenses.Models.MyDbContextDataModel 13 | ''' 14 | ''' IMyDbContextUnitOfWork extends the IUnitOfWork interface with repositories representing specific entities. 15 | ''' 16 | Public Interface IMyDbContextUnitOfWork 17 | Inherits IUnitOfWork 18 | ''' 19 | ''' The Account entities repository. 20 | ''' 21 | ReadOnly Property Accounts As IRepository(Of Account, Long) 22 | ''' 23 | ''' The Category entities repository. 24 | ''' 25 | ReadOnly Property Categories As IRepository(Of Category, Long) 26 | ''' 27 | ''' The Transaction entities repository. 28 | ''' 29 | ReadOnly Property Transactions As IRepository(Of Transaction, Long) 30 | End Interface 31 | End Namespace 32 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/Models/MyDbContextDataModel/MyDbContextUnitOfWork.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Linq 3 | Imports System.Data 4 | Imports System.Data.Entity 5 | Imports System.Linq.Expressions 6 | Imports System.Collections.Generic 7 | Imports Common.Utils 8 | Imports Common.DataModel 9 | Imports Common.DataModel.EntityFramework 10 | Imports MVVMExpenses.DataBase 11 | Imports MVVMExpenses.DataModels 12 | Namespace MVVMExpenses.Models.MyDbContextDataModel 13 | ''' 14 | ''' A MyDbContextUnitOfWork instance that represents the run-time implementation of the IMyDbContextUnitOfWork interface. 15 | ''' 16 | Public Class MyDbContextUnitOfWork 17 | Inherits DbUnitOfWork(Of MyDbContext) 18 | Implements IMyDbContextUnitOfWork 19 | Public Sub New(ByVal contextFactory As Func(Of MyDbContext)) 20 | MyBase.New(contextFactory) 21 | End Sub 22 | Private ReadOnly Property Accounts As IRepository(Of Account, Long) Implements IMyDbContextUnitOfWork.Accounts 23 | Get 24 | Return GetRepository(Function(x) x.[Set](Of Account)(), Function(x) x.ID) 25 | End Get 26 | End Property 27 | Private ReadOnly Property Categories As IRepository(Of Category, Long) Implements IMyDbContextUnitOfWork.Categories 28 | Get 29 | Return GetRepository(Function(x) x.[Set](Of Category)(), Function(x) x.ID) 30 | End Get 31 | End Property 32 | Private ReadOnly Property Transactions As IRepository(Of Transaction, Long) Implements IMyDbContextUnitOfWork.Transactions 33 | Get 34 | Return GetRepository(Function(x) x.[Set](Of Transaction)(), Function(x) x.ID) 35 | End Get 36 | End Property 37 | End Class 38 | End Namespace 39 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/Models/MyDbContextDataModel/UnitOfWorkSource.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Linq 3 | Imports System.Data 4 | Imports System.Data.Entity 5 | Imports System.Linq.Expressions 6 | Imports System.Collections.Generic 7 | Imports Common.Utils 8 | Imports Common.DataModel 9 | Imports Common.DataModel.EntityFramework 10 | Imports MVVMExpenses.DataBase 11 | Imports MVVMExpenses.DataModels 12 | Imports DevExpress.Mvvm 13 | Imports System.Collections 14 | Imports System.ComponentModel 15 | Imports DevExpress.Data.Linq 16 | Imports DevExpress.Data.Linq.Helpers 17 | Imports DevExpress.Data.Async.Helpers 18 | Namespace MVVMExpenses.Models.MyDbContextDataModel 19 | ''' 20 | ''' Provides methods to obtain the relevant IUnitOfWorkFactory. 21 | ''' 22 | Public Module UnitOfWorkSource 23 | ''' 24 | ''' Returns the IUnitOfWorkFactory implementation. 25 | ''' 26 | Public Function GetUnitOfWorkFactory() As IUnitOfWorkFactory(Of IMyDbContextUnitOfWork) 27 | Return New DbUnitOfWorkFactory(Of IMyDbContextUnitOfWork)(Function() New MyDbContextUnitOfWork(Function() New MyDbContext())) 28 | End Function 29 | End Module 30 | End Namespace 31 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/Models/Transaction.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Collections.Generic 3 | Imports System.Linq 4 | Imports System.Text 5 | Imports System.Threading.Tasks 6 | Imports System.ComponentModel.DataAnnotations 7 | 8 | Namespace MVVMExpenses.DataModels 9 | Public Enum TransactionType 10 | Expense 11 | Income 12 | End Enum 13 | Public Class Transaction 14 | 15 | Public Property ID() As Long 16 | 17 | Public Property AccountID() As Long 18 | 19 | Public Overridable Property Account() As Account 20 | 21 | Public Property CategoryID() As Long 22 | 23 | Public Overridable Property Category() As Category 24 | 25 | Public Property [Date]() As Date 26 | 27 | Public Property Amount() As Decimal 28 | 29 | Public Property Comment() As String 30 | End Class 31 | End Namespace -------------------------------------------------------------------------------- /VB/MVVMExpenses/Models/User.vb: -------------------------------------------------------------------------------- 1 | Namespace MVVMExpenses.DataModels 2 | Public Class User 3 | Public Property Login() As String 4 | Public Property Password() As String 5 | End Class 6 | End Namespace 7 | 8 | 9 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/My Project/AssemblyInfo.vb: -------------------------------------------------------------------------------- 1 | Imports System.Reflection 2 | Imports System.Runtime.CompilerServices 3 | Imports System.Runtime.InteropServices 4 | 5 | ' General Information about an assembly is controlled through the following 6 | ' set of attributes. Change these attribute values to modify the information 7 | ' associated with an assembly. 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | ' Setting ComVisible to false makes the types in this assembly not visible 18 | ' to COM components. If you need to access a type in this assembly from 19 | ' COM, set the ComVisible attribute to true on that type. 20 | 21 | 22 | ' The following GUID is for the ID of the typelib if this project is exposed to COM 23 | 24 | 25 | ' Version information for an assembly consists of the following four values: 26 | ' 27 | ' Major Version 28 | ' Minor Version 29 | ' Build Number 30 | ' Revision 31 | ' 32 | ' You can specify all the values or you can default the Build and Revision Numbers 33 | ' by using the '*' as shown below: 34 | ' [assembly: AssemblyVersion("1.0.*")] 35 | 36 | 37 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/My Project/DataSources/MVVMExpenses.DataModels.Account.datasource: -------------------------------------------------------------------------------- 1 |  2 | 8 | 9 | MVVMExpenses.DataModels.Account, MVVMExpenses, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null 10 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/My Project/DataSources/MVVMExpenses.DataModels.Category.datasource: -------------------------------------------------------------------------------- 1 |  2 | 8 | 9 | MVVMExpenses.DataModels.Category, MVVMExpenses, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null 10 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/My Project/DataSources/MVVMExpenses.DataModels.Transaction.datasource: -------------------------------------------------------------------------------- 1 |  2 | 8 | 9 | MVVMExpenses.DataModels.Transaction, MVVMExpenses, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null 10 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/My Project/Resources.Designer.vb: -------------------------------------------------------------------------------- 1 | '------------------------------------------------------------------------------ 2 | ' 3 | ' This code was generated by a tool. 4 | ' Runtime Version:4.0.30319.18052 5 | ' 6 | ' Changes to this file may cause incorrect behavior and will be lost if 7 | ' the code is regenerated. 8 | ' 9 | '------------------------------------------------------------------------------ 10 | 11 | Namespace My.Resources 12 | 13 | 14 | ''' 15 | ''' A strongly-typed resource class, for looking up localized strings, etc. 16 | ''' 17 | ' This class was auto-generated by the StronglyTypedResourceBuilder 18 | ' class via a tool like ResGen or Visual Studio. 19 | ' To add or remove a member, edit your .ResX file then rerun ResGen 20 | ' with the /str option, or rebuild your VS project. 21 | 23 | Friend Module Resources 24 | 25 | Private resourceMan As Global.System.Resources.ResourceManager 26 | 27 | Private resourceCulture As Global.System.Globalization.CultureInfo 28 | 29 | ' internal Resources() 30 | ' { 31 | ' } 32 | 33 | ''' 34 | ''' Returns the cached ResourceManager instance used by this class. 35 | ''' 36 | 37 | Friend ReadOnly Property ResourceManager() As Global.System.Resources.ResourceManager 38 | Get 39 | If (resourceMan Is Nothing) Then 40 | Dim temp As New Global.System.Resources.ResourceManager("Resources", GetType(Resources).Assembly) 41 | resourceMan = temp 42 | End If 43 | Return resourceMan 44 | End Get 45 | End Property 46 | 47 | ''' 48 | ''' Overrides the current thread's CurrentUICulture property for all 49 | ''' resource lookups using this strongly typed resource class. 50 | ''' 51 | 52 | Friend Property Culture() As Global.System.Globalization.CultureInfo 53 | Get 54 | Return resourceCulture 55 | End Get 56 | Set(ByVal value As System.Globalization.CultureInfo) 57 | resourceCulture = value 58 | End Set 59 | End Property 60 | End Module 61 | End Namespace 62 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/My Project/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/My Project/Settings.Designer.vb: -------------------------------------------------------------------------------- 1 | '------------------------------------------------------------------------------ 2 | ' 3 | ' This code was generated by a tool. 4 | ' Runtime Version:4.0.30319.18052 5 | ' 6 | ' Changes to this file may cause incorrect behavior and will be lost if 7 | ' the code is regenerated. 8 | ' 9 | '------------------------------------------------------------------------------ 10 | 11 | Namespace My 12 | 13 | 14 | 15 | Friend NotInheritable Partial Class Settings 16 | Inherits System.Configuration.ApplicationSettingsBase 17 | 18 | Private Shared defaultInstance As Settings = (CType(Global.System.Configuration.ApplicationSettingsBase.Synchronized(New Settings()), Settings)) 19 | 20 | Public Shared ReadOnly Property [Default]() As Settings 21 | Get 22 | Return defaultInstance 23 | End Get 24 | End Property 25 | End Class 26 | End Namespace 27 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/My Project/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/Program.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Collections.Generic 3 | Imports System.Linq 4 | Imports System.Threading.Tasks 5 | Imports System.Windows.Forms 6 | Imports DevExpress.Skins 7 | 8 | Namespace MVVMExpenses 9 | Friend NotInheritable Class Program 10 | 11 | Private Sub New() 12 | End Sub 13 | 14 | ''' 15 | ''' The main entry point for the application. 16 | ''' 17 | 18 | Shared Sub Main() 19 | SkinManager.EnableFormSkins() 20 | Application.EnableVisualStyles() 21 | Application.SetCompatibleTextRenderingDefault(False) 22 | Application.Run(New MainView()) 23 | End Sub 24 | End Class 25 | End Namespace 26 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/ViewModels/Account/AccountCollectionViewModel.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Linq 3 | Imports DevExpress.Mvvm.POCO 4 | Imports Common.Utils 5 | Imports MVVMExpenses.Models.MyDbContextDataModel 6 | Imports Common.DataModel 7 | Imports MVVMExpenses.DataModels 8 | Imports MVVMExpenses.DataBase 9 | Imports Common.ViewModel 10 | Namespace MVVMExpenses.ViewModels 11 | ''' 12 | ''' Represents the Accounts collection view model. 13 | ''' 14 | Partial Public Class AccountCollectionViewModel 15 | Inherits CollectionViewModel(Of Account, Long, IMyDbContextUnitOfWork) 16 | ''' 17 | ''' Creates a new instance of AccountCollectionViewModel as a POCO view model. 18 | ''' 19 | ''' A factory used to create a unit of work instance. 20 | Public Shared Function Create(Optional ByVal unitOfWorkFactory As IUnitOfWorkFactory(Of IMyDbContextUnitOfWork) = Nothing) As AccountCollectionViewModel 21 | Return ViewModelSource.Create(Function() New AccountCollectionViewModel(unitOfWorkFactory)) 22 | End Function 23 | ''' 24 | ''' Initializes a new instance of the AccountCollectionViewModel class. 25 | ''' This constructor is declared protected to avoid undesired instantiation of the AccountCollectionViewModel type without the POCO proxy factory. 26 | ''' 27 | ''' A factory used to create a unit of work instance. 28 | Protected Sub New(Optional ByVal unitOfWorkFactory As IUnitOfWorkFactory(Of IMyDbContextUnitOfWork) = Nothing) 29 | MyBase.New(If(unitOfWorkFactory, UnitOfWorkSource.GetUnitOfWorkFactory()), Function(x) x.Accounts) 30 | End Sub 31 | End Class 32 | End Namespace 33 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/ViewModels/Account/AccountViewModel.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Linq 3 | Imports System.Linq.Expressions 4 | Imports System.Collections.Generic 5 | Imports System.Collections.ObjectModel 6 | Imports DevExpress.Mvvm 7 | Imports DevExpress.Mvvm.POCO 8 | Imports Common.Utils 9 | Imports MVVMExpenses.Models.MyDbContextDataModel 10 | Imports Common.DataModel 11 | Imports MVVMExpenses.DataModels 12 | Imports MVVMExpenses.DataBase 13 | Imports Common.ViewModel 14 | Namespace MVVMExpenses.ViewModels 15 | ''' 16 | ''' Represents the single Account object view model. 17 | ''' 18 | Partial Public Class AccountViewModel 19 | Inherits SingleObjectViewModel(Of Account, Long, IMyDbContextUnitOfWork) 20 | ''' 21 | ''' Creates a new instance of AccountViewModel as a POCO view model. 22 | ''' 23 | ''' A factory used to create a unit of work instance. 24 | Public Shared Function Create(Optional ByVal unitOfWorkFactory As IUnitOfWorkFactory(Of IMyDbContextUnitOfWork) = Nothing) As AccountViewModel 25 | Return ViewModelSource.Create(Function() New AccountViewModel(unitOfWorkFactory)) 26 | End Function 27 | ''' 28 | ''' Initializes a new instance of the AccountViewModel class. 29 | ''' This constructor is declared protected to avoid undesired instantiation of the AccountViewModel type without the POCO proxy factory. 30 | ''' 31 | ''' A factory used to create a unit of work instance. 32 | Protected Sub New(Optional ByVal unitOfWorkFactory As IUnitOfWorkFactory(Of IMyDbContextUnitOfWork) = Nothing) 33 | MyBase.New(If(unitOfWorkFactory, UnitOfWorkSource.GetUnitOfWorkFactory()), Function(x) x.Accounts, Function(x) x.Name) 34 | End Sub 35 | 36 | Public ReadOnly Property AccountTransactionDetails() As CollectionViewModel(Of Transaction, Long, IMyDbContextUnitOfWork) 37 | Get 38 | Return GetDetailsCollectionViewModel(Function(x As AccountViewModel) x.AccountTransactionDetails, Function(x) x.Transactions, Function(x) x.AccountID, Sub(x, key) x.AccountID = key) 39 | End Get 40 | End Property 41 | End Class 42 | End Namespace 43 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/ViewModels/Category/CategoryCollectionViewModel.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Linq 3 | Imports DevExpress.Mvvm.POCO 4 | Imports Common.Utils 5 | Imports MVVMExpenses.Models.MyDbContextDataModel 6 | Imports Common.DataModel 7 | Imports MVVMExpenses.DataModels 8 | Imports MVVMExpenses.DataBase 9 | Imports Common.ViewModel 10 | Namespace MVVMExpenses.ViewModels 11 | ''' 12 | ''' Represents the Categories collection view model. 13 | ''' 14 | Partial Public Class CategoryCollectionViewModel 15 | Inherits CollectionViewModel(Of Category, Long, IMyDbContextUnitOfWork) 16 | ''' 17 | ''' Creates a new instance of CategoryCollectionViewModel as a POCO view model. 18 | ''' 19 | ''' A factory used to create a unit of work instance. 20 | Public Shared Function Create(Optional ByVal unitOfWorkFactory As IUnitOfWorkFactory(Of IMyDbContextUnitOfWork) = Nothing) As CategoryCollectionViewModel 21 | Return ViewModelSource.Create(Function() New CategoryCollectionViewModel(unitOfWorkFactory)) 22 | End Function 23 | ''' 24 | ''' Initializes a new instance of the CategoryCollectionViewModel class. 25 | ''' This constructor is declared protected to avoid undesired instantiation of the CategoryCollectionViewModel type without the POCO proxy factory. 26 | ''' 27 | ''' A factory used to create a unit of work instance. 28 | Protected Sub New(Optional ByVal unitOfWorkFactory As IUnitOfWorkFactory(Of IMyDbContextUnitOfWork) = Nothing) 29 | MyBase.New(If(unitOfWorkFactory, UnitOfWorkSource.GetUnitOfWorkFactory()), Function(x) x.Categories) 30 | End Sub 31 | End Class 32 | End Namespace 33 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/ViewModels/Category/CategoryViewModel.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Linq 3 | Imports System.Linq.Expressions 4 | Imports System.Collections.Generic 5 | Imports System.Collections.ObjectModel 6 | Imports DevExpress.Mvvm 7 | Imports DevExpress.Mvvm.POCO 8 | Imports Common.Utils 9 | Imports MVVMExpenses.Models.MyDbContextDataModel 10 | Imports Common.DataModel 11 | Imports MVVMExpenses.DataModels 12 | Imports MVVMExpenses.DataBase 13 | Imports Common.ViewModel 14 | Namespace MVVMExpenses.ViewModels 15 | ''' 16 | ''' Represents the single Category object view model. 17 | ''' 18 | Partial Public Class CategoryViewModel 19 | Inherits SingleObjectViewModel(Of Category, Long, IMyDbContextUnitOfWork) 20 | ''' 21 | ''' Creates a new instance of CategoryViewModel as a POCO view model. 22 | ''' 23 | ''' A factory used to create a unit of work instance. 24 | Public Shared Function Create(Optional ByVal unitOfWorkFactory As IUnitOfWorkFactory(Of IMyDbContextUnitOfWork) = Nothing) As CategoryViewModel 25 | Return ViewModelSource.Create(Function() New CategoryViewModel(unitOfWorkFactory)) 26 | End Function 27 | ''' 28 | ''' Initializes a new instance of the CategoryViewModel class. 29 | ''' This constructor is declared protected to avoid undesired instantiation of the CategoryViewModel type without the POCO proxy factory. 30 | ''' 31 | ''' A factory used to create a unit of work instance. 32 | Protected Sub New(Optional ByVal unitOfWorkFactory As IUnitOfWorkFactory(Of IMyDbContextUnitOfWork) = Nothing) 33 | MyBase.New(If(unitOfWorkFactory, UnitOfWorkSource.GetUnitOfWorkFactory()), Function(x) x.Categories, Function(x) x.Name) 34 | End Sub 35 | 36 | Public ReadOnly Property CategoryTransactionDetails() As CollectionViewModel(Of Transaction, Long, IMyDbContextUnitOfWork) 37 | Get 38 | Return GetDetailsCollectionViewModel(Function(x As CategoryViewModel) x.CategoryTransactionDetails, Function(x) x.Transactions, Function(x) x.CategoryID, Sub(x, key) x.CategoryID = key) 39 | End Get 40 | End Property 41 | End Class 42 | End Namespace 43 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/ViewModels/LoginViewModel.vb: -------------------------------------------------------------------------------- 1 | Imports MVVMExpenses.Models 2 | Imports DevExpress.Mvvm.POCO 3 | 4 | Namespace MVVMExpenses.ViewModels 5 | Public Class LoginViewModel 6 | Public ReadOnly Property LookUpUsers() As IEnumerable(Of String) 7 | Get 8 | Return CredentialsSource.GetUserNames() 9 | End Get 10 | End Property 11 | 12 | Public Overridable Property CurrentUser() As MVVMExpenses.DataModels.User 13 | Private privateIsCurrentUserCredentialsValid As Boolean 14 | 15 | Public Property IsCurrentUserCredentialsValid() As Boolean 16 | Get 17 | Return privateIsCurrentUserCredentialsValid 18 | End Get 19 | Private Set(ByVal value As Boolean) 20 | privateIsCurrentUserCredentialsValid = value 21 | End Set 22 | End Property 23 | 24 | 25 | Public Sub Init() 26 | Me.CurrentUser = New MVVMExpenses.DataModels.User() 27 | End Sub 28 | 29 | Public Sub Update() 30 | IsCurrentUserCredentialsValid = CredentialsSource.Check(CurrentUser.Login, CurrentUser.Password) 31 | End Sub 32 | 33 | Public Shared Function Create() As LoginViewModel 34 | Return ViewModelSource.Create(Of LoginViewModel)() 35 | End Function 36 | End Class 37 | End Namespace 38 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/ViewModels/MyDbContextViewModel.partial.vb: -------------------------------------------------------------------------------- 1 | Imports System.ComponentModel 2 | Imports System.Windows 3 | Imports DevExpress.Mvvm 4 | Imports DevExpress.Mvvm.POCO 5 | Imports DevExpress.Utils.MVVM 6 | Imports MVVMExpenses.Models.MyDbContextDataModel 7 | Imports MVVMExpenses.ViewModels 8 | Imports Common.ViewModel 9 | 10 | Namespace MVVMExpenses.ViewModels 11 | Partial Public Class MyDbContextViewModel 12 | Private loginViewModel As LoginViewModel 13 | 14 | Protected Sub New() 15 | MyBase.New(UnitOfWorkSource.GetUnitOfWorkFactory()) 16 | loginViewModel = loginViewModel.Create() 17 | loginViewModel.SetParentViewModel(Me) 18 | End Sub 19 | Protected ReadOnly Property DialogService() As IDialogService 20 | Get 21 | Return Me.GetService(Of IDialogService)() 22 | End Get 23 | End Property 24 | Protected ReadOnly Property MessageService() As IMessageBoxService 25 | Get 26 | Return Me.GetService(Of IMessageBoxService)() 27 | End Get 28 | End Property 29 | 30 | Public Overrides Sub OnLoaded(ByVal [module] As MyDbContextModuleDescription) 31 | MyBase.OnLoaded([module]) 32 | Login() 33 | End Sub 34 | Public Overrides Sub OnClosing(ByVal cancelEventArgs As CancelEventArgs) 35 | MyBase.OnClosing(cancelEventArgs) 36 | If Not cancelEventArgs.Cancel Then 37 | If State = AppState.Authorized AndAlso MessageService.ShowMessage("Do you really want to close the application?", "Confirm", MessageButton.YesNo) = MessageResult.No Then 38 | cancelEventArgs.Cancel = True 39 | End If 40 | End If 41 | End Sub 42 | ' 43 | Public Overridable Property State() As AppState 44 | ' Shows the Login View 45 | Public Sub Login() 46 | OnLogin(DialogService.ShowDialog(MessageButton.OKCancel, "Please enter you credentials", "LoginView", loginViewModel)) 47 | End Sub 48 | Public Sub Logout() 49 | State = AppState.ExitQueued 50 | System.Diagnostics.Process.Start(System.Windows.Forms.Application.ExecutablePath) 51 | End Sub 52 | Public Function CanLogout() As Boolean 53 | Return State = AppState.Authorized 54 | End Function 55 | 'Occurs whenever the end-user clicks a dialog button 56 | Private Sub OnLogin(ByVal result As MessageResult) 57 | If result = MessageResult.Cancel Then 58 | State = AppState.ExitQueued 59 | Else 60 | If loginViewModel.IsCurrentUserCredentialsValid Then 61 | State = AppState.Authorized 62 | Else 63 | Login() 64 | End If 65 | End If 66 | End Sub 67 | Protected Sub OnStateChanged() 68 | Me.RaiseCanExecuteChanged(Sub(x) x.Logout()) 69 | If State = AppState.Authorized Then 70 | Messenger.Default.Send(Of String)(loginViewModel.CurrentUser.Login) 71 | Else 72 | Messenger.Default.Send(Of String)(String.Empty) 73 | End If 74 | End Sub 75 | End Class 76 | 77 | Public Enum AppState 78 | NotAuthorized 79 | Authorized 80 | ExitQueued 81 | End Enum 82 | End Namespace -------------------------------------------------------------------------------- /VB/MVVMExpenses/ViewModels/MyDbContextViewModel.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Collections.Generic 3 | Imports System.Linq 4 | Imports System.ComponentModel 5 | Imports DevExpress.Mvvm 6 | Imports DevExpress.Mvvm.POCO 7 | Imports Common.DataModel 8 | Imports Common.ViewModel 9 | Imports MVVMExpenses.Models.MyDbContextDataModel 10 | Imports MVVMExpenses.DataBase 11 | Imports MVVMExpenses.DataModels 12 | Namespace MVVMExpenses.ViewModels 13 | ''' 14 | ''' Represents the root POCO view model for the MyDbContext data model. 15 | ''' 16 | Partial Public Class MyDbContextViewModel 17 | Inherits DocumentsViewModel(Of MyDbContextModuleDescription, IMyDbContextUnitOfWork) 18 | Private Const _TablesGroup As String = "Tables" 19 | Private Const _ViewsGroup As String = "Views" 20 | ''' 21 | ''' Creates a new instance of MyDbContextViewModel as a POCO view model. 22 | ''' 23 | Public Shared Function Create() As MyDbContextViewModel 24 | Return ViewModelSource.Create(Function() New MyDbContextViewModel()) 25 | End Function 26 | ''' 27 | ''' Initializes a new instance of the MyDbContextViewModel class. 28 | ''' This constructor is declared protected to avoid undesired instantiation of the MyDbContextViewModel type without the POCO proxy factory. 29 | ''' 30 | 'Protected Sub New() 31 | ' MyBase.New(UnitOfWorkSource.GetUnitOfWorkFactory()) 32 | 'End Sub 33 | Protected Overrides Function CreateModules() As MyDbContextModuleDescription() 34 | Return New MyDbContextModuleDescription() {New MyDbContextModuleDescription("Accounts", "AccountCollectionView", _TablesGroup, GetPeekCollectionViewModelFactory(Function(x) x.Accounts)), New MyDbContextModuleDescription("Categories", "CategoryCollectionView", _TablesGroup, GetPeekCollectionViewModelFactory(Function(x) x.Categories)), New MyDbContextModuleDescription("Transactions", "TransactionCollectionView", _TablesGroup, GetPeekCollectionViewModelFactory(Function(x) x.Transactions))} 35 | End Function 36 | End Class 37 | Partial Public Class MyDbContextModuleDescription 38 | Inherits ModuleDescription(Of MyDbContextModuleDescription) 39 | Public Sub New(ByVal title As String, ByVal documentType As String, ByVal group As String, Optional ByVal peekCollectionViewModelFactory As Func(Of MyDbContextModuleDescription, Object) = Nothing) 40 | MyBase.New(title, documentType, group, peekCollectionViewModelFactory) 41 | End Sub 42 | End Class 43 | End Namespace 44 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/ViewModels/Transaction/TransactionCollectionViewModel.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Linq 3 | Imports DevExpress.Mvvm.POCO 4 | Imports Common.Utils 5 | Imports MVVMExpenses.Models.MyDbContextDataModel 6 | Imports Common.DataModel 7 | Imports MVVMExpenses.DataModels 8 | Imports MVVMExpenses.DataBase 9 | Imports Common.ViewModel 10 | Namespace MVVMExpenses.ViewModels 11 | ''' 12 | ''' Represents the Transactions collection view model. 13 | ''' 14 | Partial Public Class TransactionCollectionViewModel 15 | Inherits CollectionViewModel(Of Transaction, Long, IMyDbContextUnitOfWork) 16 | ''' 17 | ''' Creates a new instance of TransactionCollectionViewModel as a POCO view model. 18 | ''' 19 | ''' A factory used to create a unit of work instance. 20 | Public Shared Function Create(Optional ByVal unitOfWorkFactory As IUnitOfWorkFactory(Of IMyDbContextUnitOfWork) = Nothing) As TransactionCollectionViewModel 21 | Return ViewModelSource.Create(Function() New TransactionCollectionViewModel(unitOfWorkFactory)) 22 | End Function 23 | ''' 24 | ''' Initializes a new instance of the TransactionCollectionViewModel class. 25 | ''' This constructor is declared protected to avoid undesired instantiation of the TransactionCollectionViewModel type without the POCO proxy factory. 26 | ''' 27 | ''' A factory used to create a unit of work instance. 28 | Protected Sub New(Optional ByVal unitOfWorkFactory As IUnitOfWorkFactory(Of IMyDbContextUnitOfWork) = Nothing) 29 | MyBase.New(If(unitOfWorkFactory, UnitOfWorkSource.GetUnitOfWorkFactory()), Function(x) x.Transactions) 30 | End Sub 31 | End Class 32 | End Namespace 33 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/ViewModels/Transaction/TransactionViewModel.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Linq 3 | Imports System.Linq.Expressions 4 | Imports System.Collections.Generic 5 | Imports System.Collections.ObjectModel 6 | Imports DevExpress.Mvvm 7 | Imports DevExpress.Mvvm.POCO 8 | Imports Common.Utils 9 | Imports MVVMExpenses.Models.MyDbContextDataModel 10 | Imports Common.DataModel 11 | Imports MVVMExpenses.DataModels 12 | Imports MVVMExpenses.DataBase 13 | Imports Common.ViewModel 14 | Namespace MVVMExpenses.ViewModels 15 | ''' 16 | ''' Represents the single Transaction object view model. 17 | ''' 18 | Partial Public Class TransactionViewModel 19 | Inherits SingleObjectViewModel(Of Transaction, Long, IMyDbContextUnitOfWork) 20 | ''' 21 | ''' Creates a new instance of TransactionViewModel as a POCO view model. 22 | ''' 23 | ''' A factory used to create a unit of work instance. 24 | Public Shared Function Create(Optional ByVal unitOfWorkFactory As IUnitOfWorkFactory(Of IMyDbContextUnitOfWork) = Nothing) As TransactionViewModel 25 | Return ViewModelSource.Create(Function() New TransactionViewModel(unitOfWorkFactory)) 26 | End Function 27 | ''' 28 | ''' Initializes a new instance of the TransactionViewModel class. 29 | ''' This constructor is declared protected to avoid undesired instantiation of the TransactionViewModel type without the POCO proxy factory. 30 | ''' 31 | ''' A factory used to create a unit of work instance. 32 | Protected Sub New(Optional ByVal unitOfWorkFactory As IUnitOfWorkFactory(Of IMyDbContextUnitOfWork) = Nothing) 33 | MyBase.New(If(unitOfWorkFactory, UnitOfWorkSource.GetUnitOfWorkFactory()), Function(x) x.Transactions, Function(x) x.Comment) 34 | End Sub 35 | ''' 36 | ''' The view model that contains a look-up collection of Accounts for the corresponding navigation property in the view. 37 | ''' 38 | Public ReadOnly Property LookUpAccounts As IEntitiesViewModel(Of Account) 39 | Get 40 | Return GetLookUpEntitiesViewModel(Function(x As TransactionViewModel) x.LookUpAccounts, Function(x) x.Accounts) 41 | End Get 42 | End Property 43 | ''' 44 | ''' The view model that contains a look-up collection of Categories for the corresponding navigation property in the view. 45 | ''' 46 | Public ReadOnly Property LookUpCategories As IEntitiesViewModel(Of Category) 47 | Get 48 | Return GetLookUpEntitiesViewModel(Function(x As TransactionViewModel) x.LookUpCategories, Function(x) x.Categories) 49 | End Get 50 | End Property 51 | End Class 52 | End Namespace 53 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/Views/Account/AccountsEditFormView.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Collections.Generic 3 | Imports System.ComponentModel 4 | Imports System.Drawing 5 | Imports System.Data 6 | Imports System.Text 7 | Imports System.Linq 8 | Imports System.Threading.Tasks 9 | Imports System.Windows.Forms 10 | Imports DevExpress.XtraEditors 11 | Imports MVVMExpenses.ViewModels 12 | Imports DevExpress.XtraGrid.Views 13 | 14 | Namespace MVVMExpenses.Common.Views.Account 15 | 16 | Partial Public Class AccountsEditFormView 17 | Inherits DevExpress.XtraEditors.XtraUserControl 18 | 19 | Public Sub New() 20 | InitializeComponent() 21 | If Not DesignMode Then 22 | InitBindings() 23 | End If 24 | End Sub 25 | 26 | Private Sub InitBindings() 27 | Dim fluent = mvvmContext1.OfType(Of AccountViewModel)() 28 | fluent.SetObjectDataSourceBinding(accountBindingSource, Function(x) x.Entity, Sub(x) x.Update()) 29 | fluent.SetBinding(GridControl1, Function(gc) gc.DataSource, Function(x) x.AccountTransactionDetails.Entities) 30 | CType(GridControl1.MainView, DevExpress.XtraGrid.Views.Grid.GridView).Columns("Account").Visible = False 31 | End Sub 32 | 33 | 34 | End Class 35 | End Namespace 36 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/Views/Account/AccountsView.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Collections.Generic 3 | Imports System.ComponentModel 4 | Imports System.Drawing 5 | Imports System.Data 6 | Imports System.Text 7 | Imports System.Linq 8 | Imports System.Threading.Tasks 9 | Imports System.Windows.Forms 10 | Imports DevExpress.XtraEditors 11 | Imports MVVMExpenses.ViewModels 12 | Imports DevExpress.Utils.MVVM.Services 13 | 14 | Namespace MVVMExpenses.Common.Views.Account 15 | 16 | Partial Public Class AccountsView 17 | Inherits DevExpress.XtraEditors.XtraUserControl 18 | 19 | Public Sub New() 20 | InitializeComponent() 21 | If Not DesignMode Then 22 | InitBindings() 23 | End If 24 | gridView1.OptionsBehavior.Editable = False 25 | gridView1.OptionsSelection.MultiSelect = True 26 | gridView1.OptionsSelection.MultiSelectMode = DevExpress.XtraGrid.Views.Grid.GridMultiSelectMode.RowSelect 27 | End Sub 28 | 29 | Private Sub InitBindings() 30 | Dim fluentAPI = mvvmContext1.OfType(Of AccountCollectionViewModel)() 31 | fluentAPI.SetBinding(gridView1, Function(gView) gView.LoadingPanelVisible, Function(x) x.IsLoading) 32 | fluentAPI.SetBinding(gridControl1, Function(gControl) gControl.DataSource, Function(x) x.Entities) 33 | 34 | fluentAPI.WithEvent(Of DevExpress.XtraGrid.Views.Base.ColumnView, DevExpress.XtraGrid.Views.Base.FocusedRowObjectChangedEventArgs)(gridView1, "FocusedRowObjectChanged").SetBinding(Function(x) x.SelectedEntity, Function(args) TryCast(args.Row, DataModels.Account), Sub(gView, entity) gView.FocusedRowHandle = gView.FindRow(entity)) 35 | fluentAPI.WithEvent(Of DevExpress.XtraGrid.Views.Grid.RowCellClickEventArgs)(gridView1, "RowCellClick").EventToCommand(Sub(x) x.Edit(Nothing), Function(x) x.SelectedEntity, Function(args) (args.Clicks = 2) AndAlso (args.Button = MouseButtons.Left)) 36 | 37 | fluentAPI.WithEvent(Of DevExpress.Data.SelectionChangedEventArgs)(gridView1, "SelectionChanged").SetBinding(Function(x) x.Selection, Function(e) GetSelectedAccounts()) 38 | End Sub 39 | 40 | Private Function GetSelectedAccounts() As IEnumerable(Of MVVMExpenses.DataModels.Account) 41 | Return gridView1.GetSelectedRows().Select(Function(r) TryCast(gridView1.GetRow(r), MVVMExpenses.DataModels.Account)) 42 | End Function 43 | 44 | Private Sub BarButtonItem8_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) 45 | 46 | End Sub 47 | 48 | Private Sub BarButtonItem7_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) 49 | End Sub 50 | End Class 51 | End Namespace 52 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/Views/Category/CategoriesEditFormView.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Collections.Generic 3 | Imports System.ComponentModel 4 | Imports System.Drawing 5 | Imports System.Data 6 | Imports System.Text 7 | Imports System.Linq 8 | Imports System.Threading.Tasks 9 | Imports System.Windows.Forms 10 | Imports DevExpress.XtraEditors 11 | Imports MVVMExpenses.ViewModels 12 | 13 | 14 | Namespace MVVMExpenses.Common.Views.Category 15 | 16 | Partial Public Class CategoriesEditFormView 17 | Inherits DevExpress.XtraEditors.XtraUserControl 18 | 19 | Public Sub New() 20 | InitializeComponent() 21 | Me.TypeImageComboBoxEdit.Properties.Items.AddEnum(Of DataModels.TransactionType)() 22 | If Not DesignMode Then 23 | InitBindings() 24 | End If 25 | End Sub 26 | 27 | Private Sub InitBindings() 28 | Dim fluent = mvvmContext1.OfType(Of CategoryViewModel)() 29 | fluent.SetObjectDataSourceBinding(categoryBindingSource, Function(x) x.Entity, Sub(x) x.Update()) 30 | fluent.SetBinding(GridControl1, Function(gc) gc.DataSource, Function(x) x.CategoryTransactionDetails.Entities) 31 | CType(GridControl1.MainView, DevExpress.XtraGrid.Views.Grid.GridView).Columns("Category").Visible = False 32 | End Sub 33 | End Class 34 | End Namespace 35 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/Views/Category/CategoriesView.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Collections.Generic 3 | Imports System.ComponentModel 4 | Imports System.Drawing 5 | Imports System.Data 6 | Imports System.Text 7 | Imports System.Linq 8 | Imports System.Threading.Tasks 9 | Imports System.Windows.Forms 10 | Imports DevExpress.XtraEditors 11 | Imports DevExpress.Utils.MVVM.Services 12 | Imports MVVMExpenses.ViewModels 13 | 14 | Namespace MVVMExpenses.Common.Views.Category 15 | 16 | Partial Public Class CategoriesView 17 | Inherits DevExpress.XtraEditors.XtraUserControl 18 | 19 | Public Sub New() 20 | InitializeComponent() 21 | If Not DesignMode Then 22 | InitBindings() 23 | End If 24 | gridView1.OptionsBehavior.Editable = False 25 | gridView1.OptionsSelection.MultiSelect = True 26 | gridView1.OptionsSelection.MultiSelectMode = DevExpress.XtraGrid.Views.Grid.GridMultiSelectMode.RowSelect 27 | End Sub 28 | 29 | Private Sub InitBindings() 30 | Dim fluent = mvvmContext1.OfType(Of CategoryCollectionViewModel)() 31 | Dim fluentAPI = mvvmContext1.OfType(Of CategoryCollectionViewModel)() 32 | fluentAPI.SetBinding(gridView1, Function(gView) gView.LoadingPanelVisible, Function(x) x.IsLoading) 33 | fluentAPI.SetBinding(gridControl1, Function(gControl) gControl.DataSource, Function(x) x.Entities) 34 | 35 | fluentAPI.WithEvent(Of DevExpress.XtraGrid.Views.Base.ColumnView, DevExpress.XtraGrid.Views.Base.FocusedRowObjectChangedEventArgs)(gridView1, "FocusedRowObjectChanged").SetBinding(Function(x) x.SelectedEntity, Function(args) TryCast(args.Row, DataModels.Category), Sub(gView, entity) gView.FocusedRowHandle = gView.FindRow(entity)) 36 | fluentAPI.WithEvent(Of DevExpress.XtraGrid.Views.Grid.RowCellClickEventArgs)(gridView1, "RowCellClick").EventToCommand(Sub(x) x.Edit(Nothing), Function(x) x.SelectedEntity, Function(args) (args.Clicks = 2) AndAlso (args.Button = MouseButtons.Left)) 37 | 38 | fluentAPI.WithEvent(Of DevExpress.Data.SelectionChangedEventArgs)(gridView1, "SelectionChanged").SetBinding(Function(x) x.Selection, Function(e) GetSelectedCategories()) 39 | End Sub 40 | 41 | Private Function GetSelectedCategories() As IEnumerable(Of MVVMExpenses.DataModels.Category) 42 | Return gridView1.GetSelectedRows().Select(Function(r) TryCast(gridView1.GetRow(r), MVVMExpenses.DataModels.Category)) 43 | End Function 44 | End Class 45 | End Namespace 46 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/Views/LoginView.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Collections.Generic 3 | Imports System.ComponentModel 4 | Imports System.Drawing 5 | Imports System.Data 6 | Imports System.Text 7 | Imports System.Linq 8 | Imports System.Threading.Tasks 9 | Imports System.Windows.Forms 10 | Imports DevExpress.XtraEditors 11 | Imports MVVMExpenses.ViewModels 12 | Imports DevExpress.Utils.MVVM.Services 13 | 14 | Namespace MVVMExpenses.Common.Views 15 | Partial Public Class LoginView 16 | Inherits DevExpress.XtraEditors.XtraUserControl 17 | 18 | Public Sub New() 19 | InitializeComponent() 20 | PasswordTextEdit.Properties.PasswordChar = "*"c 21 | End Sub 22 | 23 | Protected Overrides Sub OnLoad(ByVal e As System.EventArgs) 24 | MyBase.OnLoad(e) 25 | Dim fluentAPI = mvvmContext1.OfType(Of LoginViewModel)() 26 | fluentAPI.SetObjectDataSourceBinding(UserBindingSource, Function(x) x.CurrentUser, Sub(x) x.Update()) 27 | 28 | 29 | For Each item As String In mvvmContext1.GetViewModel(Of LoginViewModel)().LookUpUsers 30 | LoginTextEdit.Properties.Items.Add(item) 31 | Next item 32 | fluentAPI.ViewModel.Init() 33 | End Sub 34 | 35 | End Class 36 | End Namespace 37 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/Views/MainView.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.ComponentModel 3 | Imports System.Windows.Forms 4 | Imports DevExpress.Mvvm 5 | Imports DevExpress.XtraEditors 6 | Imports MVVMExpenses.ViewModels 7 | 8 | Namespace MVVMExpenses 9 | Partial Public Class MainView 10 | Inherits XtraForm 11 | 12 | Public Sub New() 13 | InitializeComponent() 14 | Me.Opacity = 0 15 | If Not DesignMode Then 16 | InitializeNavigation() 17 | End If 18 | AddHandler ribbonControl1.Merge, AddressOf ribbonControl1_Merge 19 | End Sub 20 | Private Sub ribbonControl1_Merge(ByVal sender As Object, ByVal e As DevExpress.XtraBars.Ribbon.RibbonMergeEventArgs) 21 | ribbonControl1.SelectedPage = e.MergedChild.SelectedPage 22 | End Sub 23 | Private Sub InitializeNavigation() 24 | Dim fluentAPI = mvvmContext1.OfType(Of MyDbContextViewModel)() 25 | fluentAPI.BindCommand(biAccounts, Sub(x, m) x.Show(m), Function(x) x.Modules(0)) 26 | fluentAPI.BindCommand(biCategories, Sub(x, m) x.Show(m), Function(x) x.Modules(1)) 27 | fluentAPI.BindCommand(biTransactions, Sub(x, m) x.Show(m), Function(x) x.Modules(2)) 28 | ' 29 | fluentAPI.BindCommand(biLogout, Sub(x) x.Logout()) 30 | ' 31 | fluentAPI.WithEvent(Me, "Load").EventToCommand(Sub(x) x.OnLoaded(Nothing), Function(x) x.DefaultModule) 32 | fluentAPI.WithEvent(Of FormClosingEventArgs)(Me, "FormClosing").EventToCommand(Sub(x) x.OnClosing(Nothing), New Func(Of CancelEventArgs, Object)(Function(args) args)) 33 | fluentAPI.SetTrigger(Function(x) x.State, Sub(state) 34 | If state = AppState.Authorized Then 35 | Opacity = 1 36 | End If 37 | If state = AppState.ExitQueued Then 38 | Close() 39 | End If 40 | End Sub) 41 | Messenger.Default.Register(Of String)(Me, AddressOf OnUserNameMessage) 42 | End Sub 43 | Public Sub OnUserNameMessage(ByVal userName As String) 44 | If String.IsNullOrEmpty(userName) Then 45 | Me.Text = "Expenses Application" 46 | Else 47 | Me.Text = "Expenses Application - (" & userName & ")" 48 | End If 49 | End Sub 50 | End Class 51 | End Namespace 52 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/Views/Transaction/TransactionsEditFormView.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Collections.Generic 3 | Imports System.ComponentModel 4 | Imports System.Drawing 5 | Imports System.Data 6 | Imports System.Text 7 | Imports System.Linq 8 | Imports System.Threading.Tasks 9 | Imports System.Windows.Forms 10 | Imports DevExpress.XtraEditors 11 | Imports MVVMExpenses.ViewModels 12 | 13 | Namespace MVVMExpenses.Common.Views.Transaction 14 | 15 | Partial Public Class TransactionsEditFormView 16 | Inherits DevExpress.XtraEditors.XtraUserControl 17 | 18 | Public Sub New() 19 | InitializeComponent() 20 | If Not DesignMode Then 21 | InitBindings() 22 | End If 23 | End Sub 24 | 25 | Private Sub InitBindings() 26 | Dim fluent = mvvmContext1.OfType(Of TransactionViewModel)() 27 | fluent.SetObjectDataSourceBinding(bindingSource, Function(x) x.Entity, Sub(x) x.Update()) 28 | fluent.SetBinding(accountBindingSource, Function(abs) abs.DataSource, Function(x) x.LookUpAccounts.Entities) 29 | fluent.SetBinding(categoryBindingSource, Function(cbs) cbs.DataSource, Function(x) x.LookUpCategories.Entities) 30 | End Sub 31 | End Class 32 | End Namespace 33 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/Views/Transaction/TransactionsView.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Collections.Generic 3 | Imports System.ComponentModel 4 | Imports System.Drawing 5 | Imports System.Data 6 | Imports System.Text 7 | Imports System.Linq 8 | Imports System.Threading.Tasks 9 | Imports System.Windows.Forms 10 | Imports DevExpress.XtraEditors 11 | Imports DevExpress.XtraGrid.Views.Base 12 | Imports DevExpress.XtraGrid.Views.Grid 13 | Imports MVVMExpenses.ViewModels 14 | 15 | Namespace MVVMExpenses.Common.Views.Transaction 16 | 17 | Partial Public Class TransactionsView 18 | Inherits DevExpress.XtraEditors.XtraUserControl 19 | 20 | Public Sub New() 21 | InitializeComponent() 22 | If Not DesignMode Then 23 | InitBindings() 24 | End If 25 | gridView1.OptionsBehavior.Editable = False 26 | gridView1.OptionsSelection.MultiSelect = True 27 | gridView1.OptionsSelection.MultiSelectMode = DevExpress.XtraGrid.Views.Grid.GridMultiSelectMode.RowSelect 28 | End Sub 29 | 30 | Private Sub InitBindings() 31 | Dim fluentAPI = mvvmContext1.OfType(Of TransactionCollectionViewModel)() 32 | fluentAPI.SetBinding(gridView1, Function(gView) gView.LoadingPanelVisible, Function(x) x.IsLoading) 33 | fluentAPI.SetBinding(gridControl1, Function(gControl) gControl.DataSource, Function(x) x.Entities) 34 | 35 | fluentAPI.WithEvent(Of ColumnView, FocusedRowObjectChangedEventArgs)(gridView1, "FocusedRowObjectChanged").SetBinding(Function(x) x.SelectedEntity, Function(args) TryCast(args.Row, DataModels.Transaction), Sub(gView, entity) gView.FocusedRowHandle = gView.FindRow(entity)) 36 | fluentAPI.WithEvent(Of RowCellClickEventArgs)(gridView1, "RowCellClick").EventToCommand(Sub(x) x.Edit(Nothing), Function(x) x.SelectedEntity, Function(args) (args.Clicks = 2) AndAlso (args.Button = MouseButtons.Left)) 37 | fluentAPI.WithEvent(Of DevExpress.Data.SelectionChangedEventArgs)(gridView1, "SelectionChanged").SetBinding(Function(x) x.Selection, Function(e) GetSelectedCategories()) 38 | End Sub 39 | 40 | Private Function GetSelectedCategories() As IEnumerable(Of MVVMExpenses.DataModels.Transaction) 41 | Return gridView1.GetSelectedRows().Select(Function(r) TryCast(gridView1.GetRow(r), MVVMExpenses.DataModels.Transaction)) 42 | End Function 43 | End Class 44 | End Namespace 45 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/app.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 | 10 | 11 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /VB/MVVMExpenses/sqlite/System.Data.SQLite.EF6.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevExpress-Examples/winforms-mvvm-expenses-app/70a139e6d5909c97e63090201977325d1be58b9a/VB/MVVMExpenses/sqlite/System.Data.SQLite.EF6.dll -------------------------------------------------------------------------------- /VB/MVVMExpenses/sqlite/System.Data.SQLite.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevExpress-Examples/winforms-mvvm-expenses-app/70a139e6d5909c97e63090201977325d1be58b9a/VB/MVVMExpenses/sqlite/System.Data.SQLite.dll -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "runOnWeb": false, 3 | "autoGenerateVb": false 4 | } --------------------------------------------------------------------------------