diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 731dfee..0000000 --- a/.editorconfig +++ /dev/null @@ -1,100 +0,0 @@ -# To learn more about .editorconfig see https://aka.ms/editorconfigdocs -root = true -[*.cs] -charset = utf-8-bom -indent_style = space -indent_size = 4 -trim_trailing_whitespace = true -end_of_line = crlf -insert_final_newline = true -# Organize usings -dotnet_sort_system_directives_first = true -# this. preferences -dotnet_style_qualification_for_field = false:silent -dotnet_style_qualification_for_property = false:silent -dotnet_style_qualification_for_method = false:silent -dotnet_style_qualification_for_event = false:silent -# Language keywords vs BCL types preferences -dotnet_style_predefined_type_for_locals_parameters_members = true:silent -dotnet_style_predefined_type_for_member_access = true:silent -# Parentheses preferences -dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent -dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent -dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent -dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent -# Modifier preferences -dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent -dotnet_style_readonly_field = true:suggestion -# Expression-level preferences -dotnet_style_object_initializer = true:silent -dotnet_style_collection_initializer = true:silent -dotnet_style_explicit_tuple_names = true:suggestion -dotnet_style_null_propagation = true:silent -dotnet_style_coalesce_expression = true:suggestion -dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent -dotnet_style_prefer_inferred_tuple_names = true:silent -dotnet_style_prefer_inferred_anonymous_type_member_names = true:silent -dotnet_style_prefer_auto_properties = true:silent -dotnet_style_prefer_conditional_expression_over_assignment = true:silent -dotnet_style_prefer_conditional_expression_over_return = true:silent -# Style Definitions -dotnet_naming_style.pascal_case_style.capitalization = pascal_case -# Use PascalCase for constant fields -dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion -dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields -dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style -dotnet_naming_symbols.constant_fields.applicable_kinds = field -dotnet_naming_symbols.constant_fields.applicable_accessibilities = * -dotnet_naming_symbols.constant_fields.required_modifiers = const -# var preferences -csharp_style_var_for_built_in_types = false:silent -csharp_style_var_when_type_is_apparent = false:silent -csharp_style_var_elsewhere = false:silent -# Expression-bodied members -csharp_style_expression_bodied_methods = false:silent -csharp_style_expression_bodied_constructors = false:silent -csharp_style_expression_bodied_operators = false:silent -csharp_style_expression_bodied_properties = false:silent -csharp_style_expression_bodied_indexers = false:silent -csharp_style_expression_bodied_accessors = false:silent -# Pattern matching preferences -csharp_style_pattern_matching_over_is_with_cast_check = true:silent -csharp_style_pattern_matching_over_as_with_null_check = true:silent -# Null-checking preferences -csharp_style_throw_expression = true:silent -csharp_style_conditional_delegate_call = true:silent -# Modifier preferences -csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion -# Expression-level preferences -csharp_prefer_braces = true:suggestion -csharp_style_deconstructed_variable_declaration = true:silent -csharp_prefer_simple_default_expression = true:silent -csharp_style_pattern_local_over_anonymous_function = true:silent -csharp_style_inlined_variable_declaration = true:silent -# New line preferences -csharp_new_line_before_open_brace = none -csharp_new_line_before_else = true -csharp_new_line_before_catch = true -csharp_new_line_before_finally = true -csharp_new_line_before_members_in_object_initializers = true -csharp_new_line_before_members_in_anonymous_types = true -csharp_new_line_between_query_expression_clauses = true -# Indentation preferences -csharp_indent_case_contents = true -csharp_indent_switch_labels = true -csharp_indent_labels = flush_left -# Space preferences -csharp_space_after_cast = false -csharp_space_after_keywords_in_control_flow_statements = false -csharp_space_between_method_call_parameter_list_parentheses = false -csharp_space_between_method_declaration_parameter_list_parentheses = false -csharp_space_between_parentheses = false -csharp_space_before_colon_in_inheritance_clause = true -csharp_space_after_colon_in_inheritance_clause = true -csharp_space_around_binary_operators = before_and_after -csharp_space_between_method_declaration_empty_parameter_list_parentheses = false -csharp_space_between_method_call_name_and_opening_parenthesis = false -csharp_space_between_method_call_empty_parameter_list_parentheses = false -# Wrapping preferences -csharp_preserve_single_line_statements = false -csharp_preserve_single_line_blocks = true diff --git a/.gitignore b/.gitignore index 12a2548..5bb757a 100644 --- a/.gitignore +++ b/.gitignore @@ -29,6 +29,7 @@ bld/ [Bb]in/ [Oo]bj/ [Ll]og/ +CSOld/ # Visual Studio 2015/2017 cache/options directory .vs/ diff --git a/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/App.razor b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/App.razor new file mode 100644 index 0000000..3b8af49 --- /dev/null +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/App.razor @@ -0,0 +1,11 @@ + + + + + + + Not found +

Sorry, there's nothing at this address.

+
+
+
diff --git a/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/BlazorApplication.cs b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/BlazorApplication.cs new file mode 100644 index 0000000..d3889f1 --- /dev/null +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/BlazorApplication.cs @@ -0,0 +1,48 @@ +using DevExpress.ExpressApp; +using DevExpress.ExpressApp.ApplicationBuilder; +using DevExpress.ExpressApp.Blazor; +using DevExpress.ExpressApp.SystemModule; +using NonPersistentFilteringEF.Module.BusinessObjects; +using Microsoft.EntityFrameworkCore; +using DevExpress.ExpressApp.EFCore; + +namespace NonPersistentFilteringEF.Blazor.Server; + +public class NonPersistentFilteringEFBlazorApplication : BlazorApplication { + public NonPersistentFilteringEFBlazorApplication() { + ApplicationName = "NonPersistentFilteringEF"; + CheckCompatibilityType = DevExpress.ExpressApp.CheckCompatibilityType.DatabaseSchema; + DatabaseVersionMismatch += NonPersistentFilteringEFBlazorApplication_DatabaseVersionMismatch; + } + protected override void OnSetupStarted() { + base.OnSetupStarted(); +#if DEBUG + if(System.Diagnostics.Debugger.IsAttached && CheckCompatibilityType == CheckCompatibilityType.DatabaseSchema) { + DatabaseUpdateMode = DatabaseUpdateMode.UpdateDatabaseAlways; + } +#endif + } + private void NonPersistentFilteringEFBlazorApplication_DatabaseVersionMismatch(object sender, DatabaseVersionMismatchEventArgs e) { +#if EASYTEST + e.Updater.Update(); + e.Handled = true; +#else + if(System.Diagnostics.Debugger.IsAttached) { + e.Updater.Update(); + e.Handled = true; + } + else { + string message = "The application cannot connect to the specified database, " + + "because the database doesn't exist, its version is older " + + "than that of the application or its schema does not match " + + "the ORM data model structure. To avoid this error, use one " + + "of the solutions from the https://www.devexpress.com/kb=T367835 KB Article."; + + if(e.CompatibilityError != null && e.CompatibilityError.Exception != null) { + message += "\r\n\r\nInner exception: " + e.CompatibilityError.Exception.Message; + } + throw new InvalidOperationException(message); + } +#endif + } +} diff --git a/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/BlazorModule.cs b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/BlazorModule.cs new file mode 100644 index 0000000..2336148 --- /dev/null +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/BlazorModule.cs @@ -0,0 +1,26 @@ +using System.ComponentModel; +using DevExpress.ExpressApp; +using DevExpress.ExpressApp.DC; +using DevExpress.ExpressApp.Model; +using DevExpress.ExpressApp.Editors; +using DevExpress.ExpressApp.Actions; +using DevExpress.ExpressApp.Updating; +using DevExpress.ExpressApp.Model.Core; +using DevExpress.ExpressApp.Model.DomainLogics; +using DevExpress.ExpressApp.Model.NodeGenerators; +using DevExpress.Persistent.BaseImpl.EF; + +namespace NonPersistentFilteringEF.Blazor.Server; + +[ToolboxItemFilter("Xaf.Platform.Blazor")] +// For more typical usage scenarios, be sure to check out https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.ModuleBase. +public sealed class NonPersistentFilteringEFBlazorModule : ModuleBase { + public NonPersistentFilteringEFBlazorModule() { + } + public override IEnumerable GetModuleUpdaters(IObjectSpace objectSpace, Version versionFromDB) { + return ModuleUpdater.EmptyModuleUpdaters; + } + public override void Setup(XafApplication application) { + base.Setup(application); + } +} diff --git a/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/Controllers/ReadMe.txt b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/Controllers/ReadMe.txt new file mode 100644 index 0000000..42f3017 --- /dev/null +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/Controllers/ReadMe.txt @@ -0,0 +1,25 @@ +Folder Description + +The "Controllers" project folder is intended for storing Blazor-specific Controller classes +that can change the default XAF application flow and add new features. + + +Relevant Documentation + +Controllers and Actions +https://docs.devexpress.com/eXpressAppFramework/112623 + +Implement Custom Controllers +https://docs.devexpress.com/eXpressAppFramework/112621 + +Define the Scope of Controllers and Actions +https://docs.devexpress.com/eXpressAppFramework/113103 + +Ways to Show a View +https://docs.devexpress.com/eXpressAppFramework/112803 + +Ways to Implement Business Logic +https://docs.devexpress.com/eXpressAppFramework/113710 + +Debugging, Unit and Functional Testing +https://docs.devexpress.com/eXpressAppFramework/112572 diff --git a/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/Editors/ReadMe.txt b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/Editors/ReadMe.txt new file mode 100644 index 0000000..827fd95 --- /dev/null +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/Editors/ReadMe.txt @@ -0,0 +1,25 @@ +Folder Description + +This project folder is intended for storing custom Blazor List Editors, +Property Editors and View Items. + + +Relevant Documentation + +Using a Custom Control that is not Integrated by Default +https://docs.devexpress.com/eXpressAppFramework/113610 + +Ways to Access UI Elements and Their Controls +https://docs.devexpress.com/eXpressAppFramework/120092 + +Views +https://docs.devexpress.com/eXpressAppFramework/112611 + +List Editors +https://docs.devexpress.com/eXpressAppFramework/113189 + +View Items +https://docs.devexpress.com/eXpressAppFramework/112612 + +Debugging, Unit and Functional Testing +https://docs.devexpress.com/eXpressAppFramework/112572 diff --git a/CS/NonPersistentObjectsDemo.Module.Web/Images/ReadMe.txt b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/Images/ReadMe.txt similarity index 100% rename from CS/NonPersistentObjectsDemo.Module.Web/Images/ReadMe.txt rename to CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/Images/ReadMe.txt diff --git a/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/Model.xafml b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/Model.xafml new file mode 100644 index 0000000..2877e3b --- /dev/null +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/Model.xafml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/NonPersistentFilteringEF.Blazor.Server.csproj b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/NonPersistentFilteringEF.Blazor.Server.csproj new file mode 100644 index 0000000..c3b777b --- /dev/null +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/NonPersistentFilteringEF.Blazor.Server.csproj @@ -0,0 +1,26 @@ + + + net6.0 + false + false + 1.0.* + 1.0.0.0 + Debug;Release;EasyTest + enable + + + + + + + Always + + + + + + + + + + diff --git a/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/Pages/_Host.cshtml b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/Pages/_Host.cshtml new file mode 100644 index 0000000..0c8fd68 --- /dev/null +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/Pages/_Host.cshtml @@ -0,0 +1,55 @@ +@page "/" +@namespace NonPersistentFilteringEF.Blazor.Server +@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers +@using DevExpress.ExpressApp.Blazor.Components + + + + + + + + + + NonPersistentFilteringEF + + + + + @{ + string userAgent = Request.Headers["User-Agent"]; + bool isIE = userAgent.Contains("MSIE") || userAgent.Contains("Trident"); + } + @if(isIE) { + +
+
+ +
+
Internet Explorer is not supported.
+

NonPersistentFilteringEF cannot be loaded in Internet Explorer.
Please use a different browser.

+
+
+
+ } + else { + + + + + + + + + + + + +
+ +
+ + + } + + diff --git a/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/Program.cs b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/Program.cs new file mode 100644 index 0000000..77528f1 --- /dev/null +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/Program.cs @@ -0,0 +1,50 @@ +using System.Reflection; +using DevExpress.ExpressApp; +using DevExpress.ExpressApp.Blazor.DesignTime; +using DevExpress.ExpressApp.Blazor.Services; +using DevExpress.ExpressApp.Design; +using DevExpress.ExpressApp.Utils; + +namespace NonPersistentFilteringEF.Blazor.Server; + +public class Program : IDesignTimeApplicationFactory { + private static bool ContainsArgument(string[] args, string argument) { + return args.Any(arg => arg.TrimStart('/').TrimStart('-').ToLower() == argument.ToLower()); + } + public static int Main(string[] args) { + if(ContainsArgument(args, "help") || ContainsArgument(args, "h")) { + Console.WriteLine("Updates the database when its version does not match the application's version."); + Console.WriteLine(); + Console.WriteLine($" {Assembly.GetExecutingAssembly().GetName().Name}.exe --updateDatabase [--forceUpdate --silent]"); + Console.WriteLine(); + Console.WriteLine("--forceUpdate - Marks that the database must be updated whether its version matches the application's version or not."); + Console.WriteLine("--silent - Marks that database update proceeds automatically and does not require any interaction with the user."); + Console.WriteLine(); + Console.WriteLine($"Exit codes: 0 - {DBUpdaterStatus.UpdateCompleted}"); + Console.WriteLine($" 1 - {DBUpdaterStatus.UpdateError}"); + Console.WriteLine($" 2 - {DBUpdaterStatus.UpdateNotNeeded}"); + } + else { + DevExpress.ExpressApp.FrameworkSettings.DefaultSettingsCompatibilityMode = DevExpress.ExpressApp.FrameworkSettingsCompatibilityMode.Latest; + IHost host = CreateHostBuilder(args).Build(); + if(ContainsArgument(args, "updateDatabase")) { + using(var serviceScope = host.Services.CreateScope()) { + return serviceScope.ServiceProvider.GetRequiredService().Update(ContainsArgument(args, "forceUpdate"), ContainsArgument(args, "silent")); + } + } + else { + host.Run(); + } + } + return 0; + } + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => { + webBuilder.UseStartup(); + }); + XafApplication IDesignTimeApplicationFactory.Create() { + IHostBuilder hostBuilder = CreateHostBuilder(Array.Empty()); + return DesignTimeApplicationFactoryHelper.Create(hostBuilder); + } +} diff --git a/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/Properties/launchSettings.json b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/Properties/launchSettings.json new file mode 100644 index 0000000..a4c5058 --- /dev/null +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:65201", + "sslPort": 44318 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "NonPersistentFilteringEF.Blazor.Server": { + "commandName": "Project", + "launchBrowser": true, + "applicationUrl": "https://localhost:5001;http://localhost:5000", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} \ No newline at end of file diff --git a/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/ReadMe.txt b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/ReadMe.txt new file mode 100644 index 0000000..a229505 --- /dev/null +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/ReadMe.txt @@ -0,0 +1,40 @@ +Project Description + +This project implements an ASP.NET Core Blazor Server application (https://docs.microsoft.com/en-us/aspnet/core/blazor/). +The root project folder contains the BlazorApplication.cs file with the class that inherits +BlazorApplication. This class allows you to view and customize application components: referenced modules, +security settings, data connection. Additionally, the root folder contains +Application Model difference files (XAFML files) that keep settings +specific to the current application. Difference files can be customized in code +or in the Model Editor. +The appsettings.json file contains database connection, logging, and theme settings (https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration). + + +Relevant Documentation + +Application Solution Components +https://docs.devexpress.com/eXpressAppFramework/112569 + +Debugging, Testing and Error Handling +https://docs.devexpress.com/eXpressAppFramework/112572 + +XafApplication Class +https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.XafApplication + +Application Model (UI Settings Storage) +https://docs.devexpress.com/eXpressAppFramework/112579 + +Model Editor +https://docs.devexpress.com/eXpressAppFramework/112582 + +ASP.NET Core Blazor UI +https://docs.devexpress.com/eXpressAppFramework/401675/overview/supported-ui-platforms#aspnet-core-blazor-ui + +Frequently Asked Questions - Blazor UI (FAQ) +https://docs.devexpress.com/eXpressAppFramework/403277/support-qa-troubleshooting/frequently-asked-questions-blazor-faq + +Backend WebApi Service +https://docs.devexpress.com/eXpressAppFramework/403394/backend-web-api-service + +XAF Community Extensions +https://www.devexpress.com/products/net/application_framework/#extensions \ No newline at end of file diff --git a/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/Services/CircuitHandlerProxy.cs b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/Services/CircuitHandlerProxy.cs new file mode 100644 index 0000000..5c3396a --- /dev/null +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/Services/CircuitHandlerProxy.cs @@ -0,0 +1,23 @@ +using DevExpress.ExpressApp.Blazor.Services; +using Microsoft.AspNetCore.Components.Server.Circuits; + +namespace NonPersistentFilteringEF.Blazor.Server.Services; + +internal class CircuitHandlerProxy : CircuitHandler { + private readonly IScopedCircuitHandler scopedCircuitHandler; + public CircuitHandlerProxy(IScopedCircuitHandler scopedCircuitHandler) { + this.scopedCircuitHandler = scopedCircuitHandler; + } + public override Task OnCircuitOpenedAsync(Circuit circuit, CancellationToken cancellationToken) { + return scopedCircuitHandler.OnCircuitOpenedAsync(cancellationToken); + } + public override Task OnConnectionUpAsync(Circuit circuit, CancellationToken cancellationToken) { + return scopedCircuitHandler.OnConnectionUpAsync(cancellationToken); + } + public override Task OnCircuitClosedAsync(Circuit circuit, CancellationToken cancellationToken) { + return scopedCircuitHandler.OnCircuitClosedAsync(cancellationToken); + } + public override Task OnConnectionDownAsync(Circuit circuit, CancellationToken cancellationToken) { + return scopedCircuitHandler.OnConnectionDownAsync(cancellationToken); + } +} diff --git a/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/Services/ProxyHubConnectionHandler.cs b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/Services/ProxyHubConnectionHandler.cs new file mode 100644 index 0000000..74b53c4 --- /dev/null +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/Services/ProxyHubConnectionHandler.cs @@ -0,0 +1,27 @@ +using DevExpress.ExpressApp.Blazor.Services; +using Microsoft.AspNetCore.Connections; +using Microsoft.AspNetCore.SignalR; +using Microsoft.Extensions.Options; + +namespace NonPersistentFilteringEF.Blazor.Server.Services; + +internal class ProxyHubConnectionHandler : HubConnectionHandler where THub : Hub { + private readonly IValueManagerStorageContainerInitializer storageContainerInitializer; + public ProxyHubConnectionHandler( + HubLifetimeManager lifetimeManager, + IHubProtocolResolver protocolResolver, + IOptions globalHubOptions, + IOptions> hubOptions, + ILoggerFactory loggerFactory, + IUserIdProvider userIdProvider, + IServiceScopeFactory serviceScopeFactory, + IValueManagerStorageContainerInitializer storageContainerAccessor) + : base(lifetimeManager, protocolResolver, globalHubOptions, hubOptions, loggerFactory, userIdProvider, serviceScopeFactory) { + this.storageContainerInitializer = storageContainerAccessor; + } + + public override Task OnConnectedAsync(ConnectionContext connection) { + storageContainerInitializer.Initialize(); + return base.OnConnectedAsync(connection); + } +} diff --git a/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/Startup.cs b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/Startup.cs new file mode 100644 index 0000000..4c3ea5d --- /dev/null +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/Startup.cs @@ -0,0 +1,81 @@ +using DevExpress.ExpressApp.ApplicationBuilder; +using DevExpress.ExpressApp.Blazor.ApplicationBuilder; +using DevExpress.ExpressApp.Blazor.Services; +using DevExpress.Persistent.Base; +using Microsoft.AspNetCore.Authentication.Cookies; +using Microsoft.AspNetCore.Components.Server.Circuits; +using Microsoft.EntityFrameworkCore; +using NonPersistentFilteringEF.Blazor.Server.Services; +using DevExpress.ExpressApp.Core; + +namespace NonPersistentFilteringEF.Blazor.Server; + +public class Startup { + public Startup(IConfiguration configuration) { + Configuration = configuration; + } + + public IConfiguration Configuration { get; } + + // This method gets called by the runtime. Use this method to add services to the container. + // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 + public void ConfigureServices(IServiceCollection services) { + services.AddSingleton(typeof(Microsoft.AspNetCore.SignalR.HubConnectionHandler<>), typeof(ProxyHubConnectionHandler<>)); + + services.AddRazorPages(); + services.AddServerSideBlazor(); + services.AddHttpContextAccessor(); + services.AddScoped(); + services.AddXaf(Configuration, builder => { + builder.UseApplication(); + builder.Modules + .Add() + .Add(); + builder.ObjectSpaceProviders + .AddEFCore().WithDbContext((serviceProvider, options) => { + // Uncomment this code to use an in-memory database. This database is recreated each time the server starts. With the in-memory database, you don't need to make a migration when the data model is changed. + // Do not use this code in production environment to avoid data loss. + // We recommend that you refer to the following help topic before you use an in-memory database: https://docs.microsoft.com/en-us/ef/core/testing/in-memory + //options.UseInMemoryDatabase("InMemory"); + string connectionString = null; + if(Configuration.GetConnectionString("ConnectionString") != null) { + connectionString = Configuration.GetConnectionString("ConnectionString"); + } +#if EASYTEST + if(Configuration.GetConnectionString("EasyTestConnectionString") != null) { + connectionString = Configuration.GetConnectionString("EasyTestConnectionString"); + } +#endif + ArgumentNullException.ThrowIfNull(connectionString); + options.UseSqlServer(connectionString); + options.UseChangeTrackingProxies(); + options.UseObjectSpaceLinkProxies(); + options.UseLazyLoadingProxies(); + }) + .AddNonPersistent(); + }); + } + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { + if(env.IsDevelopment()) { + app.UseDeveloperExceptionPage(); + } + else { + app.UseExceptionHandler("/Error"); + // The default HSTS value is 30 days. To change this for production scenarios, see: https://aka.ms/aspnetcore-hsts. + app.UseHsts(); + } + app.UseHttpsRedirection(); + app.UseRequestLocalization(); + app.UseStaticFiles(); + app.UseRouting(); + app.UseXaf(); + app.UseEndpoints(endpoints => { + endpoints.MapXafEndpoints(); + endpoints.MapBlazorHub(); + endpoints.MapFallbackToPage("/_Host"); + endpoints.MapControllers(); + }); + } +} diff --git a/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/_Imports.razor b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/_Imports.razor new file mode 100644 index 0000000..67b7f92 --- /dev/null +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/_Imports.razor @@ -0,0 +1,11 @@ +@using System.Net.Http +@using Microsoft.AspNetCore.Authorization +@using Microsoft.AspNetCore.Components.Authorization +@using Microsoft.AspNetCore.Components.Forms +@using Microsoft.AspNetCore.Components.Routing +@using Microsoft.AspNetCore.Components.Web +@using Microsoft.AspNetCore.Components.Web.Virtualization +@using Microsoft.JSInterop +@using DevExpress.Blazor +@using DevExpress.ExpressApp.Blazor.Components +@using NonPersistentFilteringEF.Blazor.Server diff --git a/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/appsettings.Development.json b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/appsettings.Development.json new file mode 100644 index 0000000..437008f --- /dev/null +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/appsettings.Development.json @@ -0,0 +1,16 @@ +{ + "DetailedErrors": true, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information", + "DevExpress.ExpressApp": "Information" + } + }, + "DevExpress": { + "ExpressApp": { + "EnableDiagnosticActions": false + } + } +} \ No newline at end of file diff --git a/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/appsettings.json b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/appsettings.json new file mode 100644 index 0000000..d6f0358 --- /dev/null +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/appsettings.json @@ -0,0 +1,52 @@ +{ + "ConnectionStrings": { + "ConnectionString": "Integrated Security=SSPI;Pooling=false;MultipleActiveResultSets=true;Data Source=(localdb)\\mssqllocaldb;Initial Catalog=NonPersistentFilteringEF", + "EasyTestConnectionString": "Integrated Security=SSPI;Pooling=false;MultipleActiveResultSets=true;Data Source=(localdb)\\mssqllocaldb;Initial Catalog=NonPersistentFilteringEFEasyTest" + }, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information", + "DevExpress.ExpressApp": "Information" + } + }, + "AllowedHosts": "*", + "DevExpress": { + "ExpressApp": { + "Languages": "en-US;", + "ShowLanguageSwitcher": false, + "ThemeSwitcher": { + "DefaultItemName": "Office White", + "ShowSizeModeSwitcher": true, + "Groups": [ + { + "Caption": "DevExpress Themes", + "Items": [ + { + "Caption": "Blazing Berry", + "Url": "_content/DevExpress.Blazor.Themes/blazing-berry.bs5.min.css", + "Color": "#5c2d91" + }, + { + "Caption": "Blazing Dark", + "Url": "_content/DevExpress.Blazor.Themes/blazing-dark.bs5.min.css", + "Color": "#46444a" + }, + { + "Caption": "Office White", + "Url": "_content/DevExpress.Blazor.Themes/office-white.bs5.min.css", + "Color": "#fe7109" + }, + { + "Caption": "Purple", + "Url": "_content/DevExpress.Blazor.Themes/purple.bs5.min.css", + "Color": "#7989ff" + } + ] + } + ] + } + } + } +} \ No newline at end of file diff --git a/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/wwwroot/css/site.css b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/wwwroot/css/site.css new file mode 100644 index 0000000..2e1c9a0 --- /dev/null +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/wwwroot/css/site.css @@ -0,0 +1,31 @@ +html, body { + height: 100%; +} + +app { + display: block; + height: 100%; +} + +.header-logo { + flex-shrink: 0; + background-color: currentColor; + -webkit-mask: url('../images/Logo.svg'); + mask: url('../images/Logo.svg'); + -webkit-mask-position: center; + mask-position: center; + -webkit-mask-repeat: no-repeat; + mask-repeat: no-repeat; + width: 180px; + height: 24px; +} + +#blazor-error-ui { + background: inherit; + bottom: 0; + display: none; + position: fixed; + width: 100%; + height: 100%; + z-index: 100001; +} \ No newline at end of file diff --git a/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/wwwroot/favicon.ico b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/wwwroot/favicon.ico new file mode 100644 index 0000000..91de870 Binary files /dev/null and b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/wwwroot/favicon.ico differ diff --git a/CS/NonPersistentObjectsDemo.Web/Images/Logo.svg b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/wwwroot/images/Logo.svg similarity index 100% rename from CS/NonPersistentObjectsDemo.Web/Images/Logo.svg rename to CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/wwwroot/images/Logo.svg diff --git a/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/wwwroot/images/SplashScreen.svg b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/wwwroot/images/SplashScreen.svg new file mode 100644 index 0000000..d68f0e7 --- /dev/null +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Blazor.Server/wwwroot/images/SplashScreen.svg @@ -0,0 +1,13 @@ + + + + + + + diff --git a/CS/NonPersistentObjectsDemo.Module/BusinessObjects/Article.cs b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/BusinessObjects/Article.cs similarity index 76% rename from CS/NonPersistentObjectsDemo.Module/BusinessObjects/Article.cs rename to CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/BusinessObjects/Article.cs index df0c4d2..72ad8af 100644 --- a/CS/NonPersistentObjectsDemo.Module/BusinessObjects/Article.cs +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/BusinessObjects/Article.cs @@ -11,17 +11,17 @@ namespace NonPersistentObjectsDemo.Module.BusinessObjects { [DefaultClassOptions] - [DefaultProperty(nameof(Title))] + [DefaultProperty(nameof(Article.Title))] [DevExpress.ExpressApp.ConditionalAppearance.Appearance("", Enabled = false, TargetItems = "*")] [DevExpress.ExpressApp.DC.DomainComponent] public class Article : NonPersistentObjectBase { internal Article() { } - private int id; + private int _ID; [Browsable(false)] [DevExpress.ExpressApp.Data.Key] public int ID { - get { return id; } - set { id = value; } + get { return _ID; } + set { _ID = value; } } private Contact _Author; public Contact Author { @@ -52,14 +52,14 @@ public ArticleAdapter(NonPersistentObjectSpace npos) { private void ObjectSpace_ObjectsGetting(object sender, ObjectsGettingEventArgs e) { if(e.ObjectType == typeof(Article)) { var collection = new DynamicCollection(objectSpace, e.ObjectType, e.Criteria, e.Sorting, e.InTransaction); - collection.ObjectsGetting += DynamicCollection_ObjectsGetting; + collection.FetchObjects += DynamicCollection_FetchObjects; e.Objects = collection; } } - private void DynamicCollection_ObjectsGetting(object sender, DynamicObjectsGettingEventArgs e) { + private void DynamicCollection_FetchObjects(object sender, FetchObjectsEventArgs e) { if(e.ObjectType == typeof(Article)) { e.Objects = articles; - e.ShapeRawData = true; + e.ShapeData = true; } } @@ -70,17 +70,17 @@ static ArticleAdapter() { #region DemoData static void CreateDemoData() { - var gen = new GenHelper(); + // var gen = new GenHelper(); var contacts = ContactAdapter.GetAllContacts(); - for(int i = 0; i < 5000; i++) { - var id1 = gen.Next(contacts.Count); - var id2 = gen.Next(contacts.Count - 1); + + for (int i = 0; i < 70; i++) { + var cntIndex = new Random(i).Next(0, contacts.Count); articles.Add(new Article() { ID = i, - Title = GenHelper.ToTitle(gen.MakeBlah(gen.Next(7))), - Content = gen.MakeBlahBlahBlah(5 + gen.Next(100), 7), - Author = contacts[id1] - }); + Title = "Title" + i, + Content = "Content" + i, + Author = contacts[cntIndex] + }) ; } } #endregion diff --git a/CS/NonPersistentObjectsDemo.Module/BusinessObjects/Contact.cs b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/BusinessObjects/Contact.cs similarity index 84% rename from CS/NonPersistentObjectsDemo.Module/BusinessObjects/Contact.cs rename to CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/BusinessObjects/Contact.cs index 4d0ce92..87ca349 100644 --- a/CS/NonPersistentObjectsDemo.Module/BusinessObjects/Contact.cs +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/BusinessObjects/Contact.cs @@ -13,21 +13,21 @@ namespace NonPersistentObjectsDemo.Module.BusinessObjects { [DefaultClassOptions] - [DefaultProperty(nameof(FullName))] + [DefaultProperty(nameof(Contact.FullName))] [DevExpress.ExpressApp.ConditionalAppearance.Appearance("", Enabled = false, TargetItems = "*")] [DevExpress.ExpressApp.DC.DomainComponent] public class Contact : NonPersistentObjectBase { internal Contact() { } - private string userName; + private string _UserName; [DevExpress.ExpressApp.Data.Key] public string UserName { - get { return userName; } - set { userName = value; } + get { return _UserName; } + set { _UserName = value; } } - private string fullName; + private string _FullName; public string FullName { - get { return fullName; } - set { SetPropertyValue(nameof(FullName), ref fullName, value); } + get { return _FullName; } + set { SetPropertyValue(nameof(FullName), ref _FullName, value); } } private int _Age; public int Age { @@ -51,11 +51,11 @@ public ContactAdapter(NonPersistentObjectSpace npos) { private void ObjectSpace_ObjectsGetting(object sender, ObjectsGettingEventArgs e) { if(e.ObjectType == typeof(Contact)) { var collection = new DynamicCollection(objectSpace, e.ObjectType, e.Criteria, e.Sorting, e.InTransaction); - collection.ObjectsGetting += DynamicCollection_ObjectsGetting; + collection.FetchObjects += DynamicCollection_FetchObjects; e.Objects = collection; } } - private void DynamicCollection_ObjectsGetting(object sender, DynamicObjectsGettingEventArgs e) { + private void DynamicCollection_FetchObjects(object sender, FetchObjectsEventArgs e) { if(e.ObjectType == typeof(Contact)) { var rows = contactsStorage.GetContactRows(e.Criteria, e.Sorting); e.Objects = rows.Select(row => GetContact(row)); @@ -112,12 +112,11 @@ public ContactStorage() { } public void LoadDemoData() { var dt = dataSet.Tables["Contacts"]; - var gen = new GenHelper(); - for(int i = 0; i < 200; i++) { - var id = gen.MakeTosh(20); - var fullName = gen.GetFullName(); - var age = 16 + gen.Next(80); - var rating = gen.Next(100) * gen.Next(100) * 0.001f; + for(int i = 0; i < 50; i++) { + var id = i; + var fullName = "FullName"+i; + var age = 16 + i; + var rating = new Random(i).Next(10,90); dt.LoadDataRow(new object[] { id, fullName, age, rating }, LoadOption.OverwriteChanges); } } diff --git a/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/BusinessObjects/NonPersistentFilteringEFDbContext.cs b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/BusinessObjects/NonPersistentFilteringEFDbContext.cs new file mode 100644 index 0000000..9fa6ab5 --- /dev/null +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/BusinessObjects/NonPersistentFilteringEFDbContext.cs @@ -0,0 +1,43 @@ +using DevExpress.ExpressApp.EFCore.Updating; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Design; +using DevExpress.Persistent.BaseImpl.EF.PermissionPolicy; +using DevExpress.Persistent.BaseImpl.EF; +using DevExpress.ExpressApp.Design; +using DevExpress.ExpressApp.EFCore.DesignTime; + +namespace NonPersistentFilteringEF.Module.BusinessObjects; + +// This code allows our Model Editor to get relevant EF Core metadata at design time. +// For details, please refer to https://supportcenter.devexpress.com/ticket/details/t933891. +public class NonPersistentFilteringEFContextInitializer : DbContextTypesInfoInitializerBase { + protected override DbContext CreateDbContext() { + var optionsBuilder = new DbContextOptionsBuilder() + .UseSqlServer(";") + .UseChangeTrackingProxies() + .UseObjectSpaceLinkProxies(); + return new NonPersistentFilteringEFEFCoreDbContext(optionsBuilder.Options); + } +} +//This factory creates DbContext for design-time services. For example, it is required for database migration. +public class NonPersistentFilteringEFDesignTimeDbContextFactory : IDesignTimeDbContextFactory { + public NonPersistentFilteringEFEFCoreDbContext CreateDbContext(string[] args) { + throw new InvalidOperationException("Make sure that the database connection string and connection provider are correct. After that, uncomment the code below and remove this exception."); + //var optionsBuilder = new DbContextOptionsBuilder(); + //optionsBuilder.UseSqlServer("Integrated Security=SSPI;Pooling=false;Data Source=(localdb)\\mssqllocaldb;Initial Catalog=NonPersistentFilteringEF"); + //optionsBuilder.UseChangeTrackingProxies(); + //optionsBuilder.UseObjectSpaceLinkProxies(); + //return new NonPersistentFilteringEFEFCoreDbContext(optionsBuilder.Options); + } +} +[TypesInfoInitializer(typeof(NonPersistentFilteringEFContextInitializer))] +public class NonPersistentFilteringEFEFCoreDbContext : DbContext { + public NonPersistentFilteringEFEFCoreDbContext(DbContextOptions options) : base(options) { + } + //public DbSet ModulesInfo { get; set; } + + protected override void OnModelCreating(ModelBuilder modelBuilder) { + base.OnModelCreating(modelBuilder); + modelBuilder.HasChangeTrackingStrategy(ChangeTrackingStrategy.ChangingAndChangedNotificationsWithOriginalValues); + } +} diff --git a/CS/NonPersistentObjectsDemo.Module/BusinessObjects/NonPersistentObjects.cs b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/BusinessObjects/NonPersistentObjectBase.cs similarity index 76% rename from CS/NonPersistentObjectsDemo.Module/BusinessObjects/NonPersistentObjects.cs rename to CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/BusinessObjects/NonPersistentObjectBase.cs index b74c81c..b712117 100644 --- a/CS/NonPersistentObjectsDemo.Module/BusinessObjects/NonPersistentObjects.cs +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/BusinessObjects/NonPersistentObjectBase.cs @@ -10,15 +10,15 @@ namespace NonPersistentObjectsDemo.Module.BusinessObjects { - - public abstract class NonPersistentObjectBase : INotifyPropertyChanged, IObjectSpaceLink { - private IObjectSpace objectSpace; - public IObjectSpace ObjectSpace { - get { return objectSpace; } + public abstract class BoundNonPersistentObjectBase : NonPersistentObjectBase, IObjectSpaceLink { + private IObjectSpace _ObjectSpace; + protected IObjectSpace ObjectSpace { get { return _ObjectSpace; } } + IObjectSpace IObjectSpaceLink.ObjectSpace { + get { return _ObjectSpace; } set { - if(objectSpace != value) { + if(_ObjectSpace != value) { OnObjectSpaceChanging(); - objectSpace = value; + _ObjectSpace = value; OnObjectSpaceChanged(); } } @@ -28,6 +28,9 @@ protected virtual void OnObjectSpaceChanged() { } protected IObjectSpace FindPersistentObjectSpace(Type type) { return ((NonPersistentObjectSpace)ObjectSpace).AdditionalObjectSpaces.FirstOrDefault(os => os.IsKnownType(type)); } + } + + public abstract class NonPersistentObjectBase : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); diff --git a/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/BusinessObjects/ReadMe.txt b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/BusinessObjects/ReadMe.txt new file mode 100644 index 0000000..12268e9 --- /dev/null +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/BusinessObjects/ReadMe.txt @@ -0,0 +1,29 @@ +Folder Description + +The "BusinessObjects" project folder is intended for storing code of your data model. +In XAF, a business object can be implemented as an ORM-based persistent class +or a non-persistent POCO. + + +Relevant Documentation + +Business Model Design +https://docs.devexpress.com/eXpressAppFramework/113461 + +Use the Entity Framework Core Data Model +https://docs.devexpress.com/eXpressAppFramework/402972 + +Non-Persistent Objects +https://docs.devexpress.com/eXpressAppFramework/116516 + +Data Types Supported by built-in Editors +https://docs.devexpress.com/eXpressAppFramework/113014 + +Implement Custom Business Classes and Reference Properties (EF Core) +https://docs.devexpress.com/eXpressAppFramework/402978 + +Ways to Implement Business Logic +https://docs.devexpress.com/eXpressAppFramework/113710 + +Debugging, Unit and Functional Testing +https://docs.devexpress.com/eXpressAppFramework/112572 diff --git a/CS/NonPersistentObjectsDemo.Module/Controllers/FindArticlesController.cs b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/Controllers/FindArticlesController.cs similarity index 96% rename from CS/NonPersistentObjectsDemo.Module/Controllers/FindArticlesController.cs rename to CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/Controllers/FindArticlesController.cs index 4ba3ab7..7d75671 100644 --- a/CS/NonPersistentObjectsDemo.Module/Controllers/FindArticlesController.cs +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/Controllers/FindArticlesController.cs @@ -33,7 +33,7 @@ private void Action_Execute(object sender, PopupWindowShowActionExecuteEventArgs } [DomainComponent] - public class FindArticlesDialog : NonPersistentObjectBase { + public class FindArticlesDialog : BoundNonPersistentObjectBase { private Contact _Author; [ImmediatePostData] public Contact Author { @@ -76,7 +76,7 @@ private CriteriaOperator GetCriteria() { return CriteriaOperator.Parse("Author.Rating >= ?", AuthorMinRating); } } - [Action(PredefinedCategory.Filters)] + [Action(PredefinedCategory.PopupActions)] public void Find() { UpdateArticles(); } diff --git a/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/Controllers/ReadMe.txt b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/Controllers/ReadMe.txt new file mode 100644 index 0000000..9389414 --- /dev/null +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/Controllers/ReadMe.txt @@ -0,0 +1,25 @@ +Folder Description + +The "Controllers" project folder is intended for storing platform-agnostic Controller classes +that can change the default XAF application flow and add new features. + + +Relevant Documentation + +Controllers and Actions +https://docs.devexpress.com/eXpressAppFramework/112623 + +Implement Custom Controllers +https://docs.devexpress.com/eXpressAppFramework/112621 + +Define the Scope of Controllers and Actions +https://docs.devexpress.com/eXpressAppFramework/113103 + +Ways to Show a View +https://docs.devexpress.com/eXpressAppFramework/112803 + +Ways to Implement Business Logic +https://docs.devexpress.com/eXpressAppFramework/113710 + +Debugging, Unit and Functional Testing +https://docs.devexpress.com/eXpressAppFramework/112572 diff --git a/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/DatabaseUpdate/ReadMe.txt b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/DatabaseUpdate/ReadMe.txt new file mode 100644 index 0000000..fc20baa --- /dev/null +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/DatabaseUpdate/ReadMe.txt @@ -0,0 +1,23 @@ +Folder Description + +The "DatabaseUpdate" project folder is intended for storing code that supplies +initial data (default User objects, etc) and handles a database update when the +application version changes. + + +Relevant Documentation + +Supply Initial Data (EF Core) +https://docs.devexpress.com/eXpressAppFramework/402985 + +ModuleUpdater Class +https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.Updating.ModuleUpdater + +Application Update +https://docs.devexpress.com/eXpressAppFramework/113239 + +Migrations Overview (EF Core) +https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations + +Debugging, Unit and Functional Testing +https://docs.devexpress.com/eXpressAppFramework/112572 diff --git a/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/DatabaseUpdate/Updater.cs b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/DatabaseUpdate/Updater.cs new file mode 100644 index 0000000..8fd9c97 --- /dev/null +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/DatabaseUpdate/Updater.cs @@ -0,0 +1,29 @@ +using DevExpress.ExpressApp; +using DevExpress.Data.Filtering; +using DevExpress.Persistent.Base; +using DevExpress.ExpressApp.Updating; +using DevExpress.ExpressApp.EF; +using DevExpress.Persistent.BaseImpl.EF; + +namespace NonPersistentFilteringEF.Module.DatabaseUpdate; + +// For more typical usage scenarios, be sure to check out https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.Updating.ModuleUpdater +public class Updater : ModuleUpdater { + public Updater(IObjectSpace objectSpace, Version currentDBVersion) : + base(objectSpace, currentDBVersion) { + } + public override void UpdateDatabaseAfterUpdateSchema() { + base.UpdateDatabaseAfterUpdateSchema(); + //string name = "MyName"; + //EntityObject1 theObject = ObjectSpace.FirstOrDefault(u => u.Name == name); + //if(theObject == null) { + // theObject = ObjectSpace.CreateObject(); + // theObject.Name = name; + //} + + //ObjectSpace.CommitChanges(); //Uncomment this line to persist created object(s). + } + public override void UpdateDatabaseBeforeUpdateSchema() { + base.UpdateDatabaseBeforeUpdateSchema(); + } +} diff --git a/CS/NonPersistentObjectsDemo.Module.Win/Images/ReadMe.txt b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/Images/ReadMe.txt similarity index 100% rename from CS/NonPersistentObjectsDemo.Module.Win/Images/ReadMe.txt rename to CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/Images/ReadMe.txt diff --git a/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/Model.DesignedDiffs.xafml b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/Model.DesignedDiffs.xafml new file mode 100644 index 0000000..b1c8695 --- /dev/null +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/Model.DesignedDiffs.xafml @@ -0,0 +1,5 @@ + + + + + diff --git a/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/Module.cs b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/Module.cs new file mode 100644 index 0000000..5723d48 --- /dev/null +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/Module.cs @@ -0,0 +1,44 @@ +using System.ComponentModel; +using DevExpress.ExpressApp; +using DevExpress.ExpressApp.DC; +using DevExpress.Persistent.Base; +using DevExpress.ExpressApp.Model; +using DevExpress.ExpressApp.Actions; +using DevExpress.ExpressApp.Editors; +using DevExpress.ExpressApp.Updating; +using DevExpress.ExpressApp.Model.Core; +using DevExpress.ExpressApp.Model.DomainLogics; +using DevExpress.ExpressApp.Model.NodeGenerators; +using NonPersistentObjectsDemo.Module.BusinessObjects; + +namespace NonPersistentFilteringEF.Module; + +// For more typical usage scenarios, be sure to check out https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.ModuleBase. +public sealed class NonPersistentFilteringEFModule : ModuleBase { + public NonPersistentFilteringEFModule() { + // + // NonPersistentFilteringEFModule + // + RequiredModuleTypes.Add(typeof(DevExpress.ExpressApp.SystemModule.SystemModule)); + RequiredModuleTypes.Add(typeof(DevExpress.ExpressApp.Objects.BusinessClassLibraryCustomizationModule)); + } + public override IEnumerable GetModuleUpdaters(IObjectSpace objectSpace, Version versionFromDB) { + ModuleUpdater updater = new DatabaseUpdate.Updater(objectSpace, versionFromDB); + return new ModuleUpdater[] { updater }; + } + public override void Setup(XafApplication application) { + base.Setup(application); + // Manage various aspects of the application UI and behavior at the module level. + application.SetupComplete += Application_SetupComplete; + } + private void Application_SetupComplete(object sender, EventArgs e) { + Application.ObjectSpaceCreated += Application_ObjectSpaceCreated; + } + private void Application_ObjectSpaceCreated(object sender, ObjectSpaceCreatedEventArgs e) { + var npos = e.ObjectSpace as NonPersistentObjectSpace; + if (npos != null) { + new ArticleAdapter(npos); + new ContactAdapter(npos); + } + } +} diff --git a/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/NonPersistentFilteringEF.Module.csproj b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/NonPersistentFilteringEF.Module.csproj new file mode 100644 index 0000000..3f8027c --- /dev/null +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/NonPersistentFilteringEF.Module.csproj @@ -0,0 +1,27 @@ + + + net6.0 + false + false + 1.0.* + 1.0.0.0 + Debug;Release;EasyTest + enable + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/ReadMe.txt b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/ReadMe.txt new file mode 100644 index 0000000..087d288 --- /dev/null +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/ReadMe.txt @@ -0,0 +1,32 @@ +Project Description + +This project implements a platform-agnostic Module. UI-independent application +elements can be implemented here (Business Objects, Controllers, etc.). The root project +folder contains the Module.cs(vb) file with the class that inherits ModuleBase. +This class allows you to view and customize Module components: +referenced modules, Controllers and business classes. Additionally, the root folder +contains Application Model difference files (XAFML files) that keep application +settings specific for the current Module. Difference files can be customized in code +or in the Model Editor. + + +Relevant Documentation + +Application Solution Components +https://docs.devexpress.com/eXpressAppFramework/112569 + +XAF Community Extensions +https://www.devexpress.com/products/net/application_framework/#extensions + +Debugging, Unit and Functional Testing +https://docs.devexpress.com/eXpressAppFramework/112572 + +ModuleBase Class +https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.ModuleBase + + +Application Model +https://docs.devexpress.com/eXpressAppFramework/112579 + +Model Editor +https://docs.devexpress.com/eXpressAppFramework/112582 \ No newline at end of file diff --git a/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/Welcome.html b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/Welcome.html new file mode 100644 index 0000000..70af898 --- /dev/null +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/Welcome.html @@ -0,0 +1,191 @@ + + + + + Your XAF application + + + + +
+ + + + + +
+
+

The XAF Solution Wizard has successfully generated the solution according to your settings.

+
    +
  • The NonPersistentFilteringEF.Module project keeps your platform-agnostic code. + Its Business Objects folder contains the autogenerated data model filled with entities required by the chosen set of modules. Add your custom entities to this model and XAF will automatically create a UI to create, read, update and delete these entities.
  • +
  • The NonPersistentFilteringEF.Win project is a startup project for the desktop application.
  • +
  • To specify the database used by your application, modify the ConnectionString attribute in the configuration file located in the startup project.
  • +
+
+
+ + + + + +
+
+ + + diff --git a/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/App.config b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/App.config new file mode 100644 index 0000000..9fc8ea0 --- /dev/null +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/App.config @@ -0,0 +1,36 @@ + + + + +
+ + + + + + System + + + + + + + + + + + + + + + + + diff --git a/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/Controllers/ReadMe.txt b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/Controllers/ReadMe.txt new file mode 100644 index 0000000..a2c3f7a --- /dev/null +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/Controllers/ReadMe.txt @@ -0,0 +1,25 @@ +Folder Description + +The "Controllers" project folder is intended for storing WinForms-specific Controller classes +that can change the default XAF application flow and add new features. + + +Relevant Documentation + +Controllers and Actions +https://docs.devexpress.com/eXpressAppFramework/112623 + +Implement Custom Controllers +https://docs.devexpress.com/eXpressAppFramework/112621 + +Define the Scope of Controllers and Actions +https://docs.devexpress.com/eXpressAppFramework/113103 + +Ways to Show a View +https://docs.devexpress.com/eXpressAppFramework/112803 + +Ways to Implement Business Logic +https://docs.devexpress.com/eXpressAppFramework/113710 + +Debugging, Unit and Functional Testing +https://docs.devexpress.com/eXpressAppFramework/112572 diff --git a/CS/NonPersistentObjectsDemo.Module.Win/Editors/ReadMe.txt b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/Editors/ReadMe.txt similarity index 73% rename from CS/NonPersistentObjectsDemo.Module.Win/Editors/ReadMe.txt rename to CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/Editors/ReadMe.txt index 3d405d8..00ff025 100644 --- a/CS/NonPersistentObjectsDemo.Module.Win/Editors/ReadMe.txt +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/Editors/ReadMe.txt @@ -1,10 +1,20 @@ Folder Description -This project folder is intended for storing custom WinForms List Editors, +This project folder is intended for storing custom WinForms List Editors, Property Editors and View Items. + Relevant Documentation +Using a Custom Control that is not Integrated by Default +https://docs.devexpress.com/eXpressAppFramework/113610 + +Ways to Access UI Elements and Their Controls +https://docs.devexpress.com/eXpressAppFramework/120092 + +Views +https://docs.devexpress.com/eXpressAppFramework/112611 + List Editors https://docs.devexpress.com/eXpressAppFramework/113189 @@ -31,3 +41,6 @@ https://docs.devexpress.com/eXpressAppFramework/113104 How to: Implement a View Item https://docs.devexpress.com/eXpressAppFramework/112641 + +Debugging, Unit and Functional Testing +https://docs.devexpress.com/eXpressAppFramework/112572 diff --git a/CS/NonPersistentObjectsDemo.Win/ExpressApp.ico b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/ExpressApp.ico similarity index 100% rename from CS/NonPersistentObjectsDemo.Win/ExpressApp.ico rename to CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/ExpressApp.ico diff --git a/CS/NonPersistentObjectsDemo.Module.Win/Images/ExpressAppLogo.png b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/Images/ExpressAppLogo.png similarity index 100% rename from CS/NonPersistentObjectsDemo.Module.Win/Images/ExpressAppLogo.png rename to CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/Images/ExpressAppLogo.png diff --git a/CS/NonPersistentObjectsDemo.Win/Images/Logo.svg b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/Images/Logo.svg similarity index 100% rename from CS/NonPersistentObjectsDemo.Win/Images/Logo.svg rename to CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/Images/Logo.svg diff --git a/CS/NonPersistentObjectsDemo.Module/Images/ReadMe.txt b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/Images/ReadMe.txt similarity index 100% rename from CS/NonPersistentObjectsDemo.Module/Images/ReadMe.txt rename to CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/Images/ReadMe.txt diff --git a/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/Model.xafml b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/Model.xafml new file mode 100644 index 0000000..594847b --- /dev/null +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/Model.xafml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/NonPersistentFilteringEF.Win.csproj b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/NonPersistentFilteringEF.Win.csproj new file mode 100644 index 0000000..321eba0 --- /dev/null +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/NonPersistentFilteringEF.Win.csproj @@ -0,0 +1,43 @@ + + + WinExe + net6.0-windows + false + true + ExpressApp.ico + false + 1.0.* + 1.0.0.0 + Debug;Release;EasyTest + enable + + + + + + + + + + + Always + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/Program.cs b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/Program.cs new file mode 100644 index 0000000..f88ac9f --- /dev/null +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/Program.cs @@ -0,0 +1,81 @@ +using System.Configuration; +using DevExpress.ExpressApp; +using DevExpress.ExpressApp.ApplicationBuilder; +using DevExpress.ExpressApp.Win.ApplicationBuilder; +using DevExpress.ExpressApp.Security; +using DevExpress.ExpressApp.Win; +using DevExpress.Persistent.Base; +using Microsoft.EntityFrameworkCore; +using DevExpress.ExpressApp.EFCore; +using DevExpress.XtraEditors; +using DevExpress.ExpressApp.Utils; +using DevExpress.ExpressApp.Win.Utils; +using System.Reflection; + +namespace NonPersistentFilteringEF.Win; + +static class Program { + private static bool ContainsArgument(string[] args, string argument) { + return args.Any(arg => arg.TrimStart('/').TrimStart('-').ToLower() == argument.ToLower()); + } + /// + /// The main entry point for the application. + /// + [STAThread] + public static int Main(string[] args) { + if(ContainsArgument(args, "help") || ContainsArgument(args, "h")) { + Console.WriteLine("Updates the database when its version does not match the application's version."); + Console.WriteLine(); + Console.WriteLine($" {Assembly.GetExecutingAssembly().GetName().Name}.exe --updateDatabase [--forceUpdate --silent]"); + Console.WriteLine(); + Console.WriteLine("--forceUpdate - Marks that the database must be updated whether its version matches the application's version or not."); + Console.WriteLine("--silent - Marks that database update proceeds automatically and does not require any interaction with the user."); + Console.WriteLine(); + Console.WriteLine($"Exit codes: 0 - {DBUpdaterStatus.UpdateCompleted}"); + Console.WriteLine($" 1 - {DBUpdaterStatus.UpdateError}"); + Console.WriteLine($" 2 - {DBUpdaterStatus.UpdateNotNeeded}"); + return 0; + } + DevExpress.ExpressApp.FrameworkSettings.DefaultSettingsCompatibilityMode = DevExpress.ExpressApp.FrameworkSettingsCompatibilityMode.Latest; +#if EASYTEST + DevExpress.ExpressApp.Win.EasyTest.EasyTestRemotingRegistration.Register(); +#endif + WindowsFormsSettings.LoadApplicationSettings(); + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + DevExpress.Utils.ToolTipController.DefaultController.ToolTipType = DevExpress.Utils.ToolTipType.SuperTip; + if(Tracing.GetFileLocationFromSettings() == DevExpress.Persistent.Base.FileLocation.CurrentUserApplicationDataFolder) { + Tracing.LocalUserAppDataPath = Application.LocalUserAppDataPath; + } + Tracing.Initialize(); + + string connectionString = null; + if(ConfigurationManager.ConnectionStrings["ConnectionString"] != null) { + connectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString; + } +#if EASYTEST + if(ConfigurationManager.ConnectionStrings["EasyTestConnectionString"] != null) { + connectionString = ConfigurationManager.ConnectionStrings["EasyTestConnectionString"].ConnectionString; + } +#endif + ArgumentNullException.ThrowIfNull(connectionString); + var winApplication = ApplicationBuilder.BuildApplication(connectionString); + + if (ContainsArgument(args, "updateDatabase")) { + using var dbUpdater = new WinDBUpdater(() => winApplication); + return dbUpdater.Update( + forceUpdate: ContainsArgument(args, "forceUpdate"), + silent: ContainsArgument(args, "silent")); + } + + try { + winApplication.Setup(); + winApplication.Start(); + } + catch(Exception e) { + winApplication.StopSplash(); + winApplication.HandleException(e); + } + return 0; + } +} diff --git a/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/ReadMe.txt b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/ReadMe.txt new file mode 100644 index 0000000..cebe462 --- /dev/null +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/ReadMe.txt @@ -0,0 +1,33 @@ +Project Description + +This project implements a WinForms application. The root project folder +contains the WinApplication.cs file with the class that inherits WinApplication. +This class allows you to view and customize Module components: +referenced modules, Controllers and business classes. Additionally, the root folder +contains Application Model difference files (XAFML files) that keep application +settings specific for the current Module. Difference files can be customized in code +or in the Model Editor. + + +Relevant Documentation + +Application Solution Components +https://docs.devexpress.com/eXpressAppFramework/112569 + +XAF Community Extensions +https://www.devexpress.com/products/net/application_framework/#extensions + +Debugging, Unit and Functional Testing +https://docs.devexpress.com/eXpressAppFramework/112572 + +WinApplication Class +https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.Win.WinApplication + +XafApplication Class +https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.XafApplication + +Application Model +https://docs.devexpress.com/eXpressAppFramework/112579 + +Model Editor +https://docs.devexpress.com/eXpressAppFramework/112582 \ No newline at end of file diff --git a/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/Startup.cs b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/Startup.cs new file mode 100644 index 0000000..8648168 --- /dev/null +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/Startup.cs @@ -0,0 +1,47 @@ +using System.Configuration; +using DevExpress.ExpressApp; +using DevExpress.ExpressApp.ApplicationBuilder; +using DevExpress.ExpressApp.Win.ApplicationBuilder; +using DevExpress.ExpressApp.Security; +using DevExpress.ExpressApp.Win; +using DevExpress.Persistent.Base; +using Microsoft.EntityFrameworkCore; +using DevExpress.ExpressApp.EFCore; +using DevExpress.XtraEditors; +using DevExpress.ExpressApp.Design; + +namespace NonPersistentFilteringEF.Win; + +public class ApplicationBuilder : IDesignTimeApplicationFactory { + public static WinApplication BuildApplication(string connectionString) { + var builder = WinApplication.CreateBuilder(); + builder.UseApplication(); + builder.Modules + .Add() + .Add(); + builder.ObjectSpaceProviders + .AddEFCore().WithDbContext((application, options) => { + // Uncomment this code to use an in-memory database. This database is recreated each time the server starts. With the in-memory database, you don't need to make a migration when the data model is changed. + // Do not use this code in production environment to avoid data loss. + // We recommend that you refer to the following help topic before you use an in-memory database: https://docs.microsoft.com/en-us/ef/core/testing/in-memory + //options.UseInMemoryDatabase("InMemory"); + options.UseSqlServer(connectionString); + options.UseChangeTrackingProxies(); + options.UseObjectSpaceLinkProxies(); + }) + .AddNonPersistent(); + builder.AddBuildStep(application => { + application.ConnectionString = connectionString; +#if DEBUG + if(System.Diagnostics.Debugger.IsAttached && application.CheckCompatibilityType == CheckCompatibilityType.DatabaseSchema) { + application.DatabaseUpdateMode = DatabaseUpdateMode.UpdateDatabaseAlways; + } +#endif + }); + var winApplication = builder.Build(); + return winApplication; + } + + XafApplication IDesignTimeApplicationFactory.Create() + => BuildApplication(XafApplication.DesignTimeConnectionString); +} diff --git a/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/WinApplication.cs b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/WinApplication.cs new file mode 100644 index 0000000..ee10625 --- /dev/null +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/WinApplication.cs @@ -0,0 +1,54 @@ +using System.ComponentModel; +using DevExpress.ExpressApp; +using DevExpress.ExpressApp.ApplicationBuilder; +using DevExpress.ExpressApp.Win; +using DevExpress.ExpressApp.Updating; +using DevExpress.ExpressApp.Win.Utils; +using Microsoft.EntityFrameworkCore; +using DevExpress.ExpressApp.EFCore; +using NonPersistentFilteringEF.Module; +using NonPersistentFilteringEF.Module.BusinessObjects; +using System.Data.Common; + +namespace NonPersistentFilteringEF.Win; + +// For more typical usage scenarios, be sure to check out https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.Win.WinApplication._members +public class NonPersistentFilteringEFWindowsFormsApplication : WinApplication { + public NonPersistentFilteringEFWindowsFormsApplication() { + SplashScreen = new DXSplashScreen(typeof(XafSplashScreen), new DefaultOverlayFormOptions()); + ApplicationName = "NonPersistentFilteringEF"; + CheckCompatibilityType = DevExpress.ExpressApp.CheckCompatibilityType.DatabaseSchema; + UseOldTemplates = false; + DatabaseVersionMismatch += NonPersistentFilteringEFWindowsFormsApplication_DatabaseVersionMismatch; + CustomizeLanguagesList += NonPersistentFilteringEFWindowsFormsApplication_CustomizeLanguagesList; + } + private void NonPersistentFilteringEFWindowsFormsApplication_CustomizeLanguagesList(object sender, CustomizeLanguagesListEventArgs e) { + string userLanguageName = System.Threading.Thread.CurrentThread.CurrentUICulture.Name; + if(userLanguageName != "en-US" && e.Languages.IndexOf(userLanguageName) == -1) { + e.Languages.Add(userLanguageName); + } + } + private void NonPersistentFilteringEFWindowsFormsApplication_DatabaseVersionMismatch(object sender, DevExpress.ExpressApp.DatabaseVersionMismatchEventArgs e) { +#if EASYTEST + e.Updater.Update(); + e.Handled = true; +#else + if(System.Diagnostics.Debugger.IsAttached) { + e.Updater.Update(); + e.Handled = true; + } + else { + string message = "The application cannot connect to the specified database, " + + "because the database doesn't exist, its version is older " + + "than that of the application or its schema does not match " + + "the ORM data model structure. To avoid this error, use one " + + "of the solutions from the https://www.devexpress.com/kb=T367835 KB Article."; + + if(e.CompatibilityError != null && e.CompatibilityError.Exception != null) { + message += "\r\n\r\nInner exception: " + e.CompatibilityError.Exception.Message; + } + throw new InvalidOperationException(message); + } +#endif + } +} diff --git a/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/WinModule.cs b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/WinModule.cs new file mode 100644 index 0000000..6642717 --- /dev/null +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/WinModule.cs @@ -0,0 +1,26 @@ +using System.ComponentModel; +using DevExpress.ExpressApp; +using DevExpress.ExpressApp.DC; +using DevExpress.ExpressApp.Model; +using DevExpress.ExpressApp.Editors; +using DevExpress.ExpressApp.Actions; +using DevExpress.ExpressApp.Updating; +using DevExpress.ExpressApp.Model.Core; +using DevExpress.ExpressApp.Model.DomainLogics; +using DevExpress.ExpressApp.Model.NodeGenerators; + +namespace NonPersistentFilteringEF.Win; + +[ToolboxItemFilter("Xaf.Platform.Win")] +// For more typical usage scenarios, be sure to check out https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.ModuleBase. +public sealed class NonPersistentFilteringEFWinModule : ModuleBase { + public NonPersistentFilteringEFWinModule() { + DevExpress.ExpressApp.Editors.FormattingProvider.UseMaskSettings = true; + } + public override IEnumerable GetModuleUpdaters(IObjectSpace objectSpace, Version versionFromDB) { + return ModuleUpdater.EmptyModuleUpdaters; + } + public override void Setup(XafApplication application) { + base.Setup(application); + } +} diff --git a/CS/NonPersistentObjectsDemo.Win/XafSplashScreen.Designer.cs b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/XafSplashScreen.Designer.cs similarity index 99% rename from CS/NonPersistentObjectsDemo.Win/XafSplashScreen.Designer.cs rename to CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/XafSplashScreen.Designer.cs index 6f969d7..590fd2e 100644 --- a/CS/NonPersistentObjectsDemo.Win/XafSplashScreen.Designer.cs +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/XafSplashScreen.Designer.cs @@ -1,4 +1,4 @@ -namespace NonPersistentObjectsDemo.Win { +namespace NonPersistentFilteringEF.Win { partial class XafSplashScreen { /// diff --git a/CS/NonPersistentObjectsDemo.Win/XafSplashScreen.cs b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/XafSplashScreen.cs similarity index 95% rename from CS/NonPersistentObjectsDemo.Win/XafSplashScreen.cs rename to CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/XafSplashScreen.cs index b5fe178..8312c65 100644 --- a/CS/NonPersistentObjectsDemo.Win/XafSplashScreen.cs +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/XafSplashScreen.cs @@ -8,7 +8,7 @@ using DevExpress.Utils.Svg; using DevExpress.XtraSplashScreen; -namespace NonPersistentObjectsDemo.Win { +namespace NonPersistentFilteringEF.Win { public partial class XafSplashScreen : SplashScreen { private void LoadBlankLogo() { Assembly assembly = Assembly.GetExecutingAssembly(); @@ -50,7 +50,5 @@ public override void ProcessCommand(Enum cmd, object arg) { #endregion - public enum SplashScreenCommand { - } } } \ No newline at end of file diff --git a/CS/NonPersistentObjectsDemo.Win/XafSplashScreen.resx b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/XafSplashScreen.resx similarity index 100% rename from CS/NonPersistentObjectsDemo.Win/XafSplashScreen.resx rename to CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Win/XafSplashScreen.resx diff --git a/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.sln b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.sln new file mode 100644 index 0000000..be12722 --- /dev/null +++ b/CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.sln @@ -0,0 +1,42 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.33424.131 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NonPersistentFilteringEF.Blazor.Server", "NonPersistentFilteringEF.Blazor.Server\NonPersistentFilteringEF.Blazor.Server.csproj", "{1EA5939B-0396-43BB-B9C8-4516F3EF00F9}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NonPersistentFilteringEF.Module", "NonPersistentFilteringEF.Module\NonPersistentFilteringEF.Module.csproj", "{CFD35739-63A1-4719-91BC-73DC68E37F0A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NonPersistentFilteringEF.Win", "NonPersistentFilteringEF.Win\NonPersistentFilteringEF.Win.csproj", "{840F30C1-8D4C-44CD-96BD-4149947B8AF8}" +EndProject + +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + EasyTest|Any CPU = EasyTest|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {CFD35739-63A1-4719-91BC-73DC68E37F0A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CFD35739-63A1-4719-91BC-73DC68E37F0A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CFD35739-63A1-4719-91BC-73DC68E37F0A}.EasyTest|Any CPU.ActiveCfg = EasyTest|Any CPU + {CFD35739-63A1-4719-91BC-73DC68E37F0A}.EasyTest|Any CPU.Build.0 = EasyTest|Any CPU + {CFD35739-63A1-4719-91BC-73DC68E37F0A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CFD35739-63A1-4719-91BC-73DC68E37F0A}.Release|Any CPU.Build.0 = Release|Any CPU + {840F30C1-8D4C-44CD-96BD-4149947B8AF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {840F30C1-8D4C-44CD-96BD-4149947B8AF8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {840F30C1-8D4C-44CD-96BD-4149947B8AF8}.EasyTest|Any CPU.ActiveCfg = EasyTest|Any CPU + {840F30C1-8D4C-44CD-96BD-4149947B8AF8}.EasyTest|Any CPU.Build.0 = EasyTest|Any CPU + {840F30C1-8D4C-44CD-96BD-4149947B8AF8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {840F30C1-8D4C-44CD-96BD-4149947B8AF8}.Release|Any CPU.Build.0 = Release|Any CPU + {1EA5939B-0396-43BB-B9C8-4516F3EF00F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1EA5939B-0396-43BB-B9C8-4516F3EF00F9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1EA5939B-0396-43BB-B9C8-4516F3EF00F9}.EasyTest|Any CPU.ActiveCfg = EasyTest|Any CPU + {1EA5939B-0396-43BB-B9C8-4516F3EF00F9}.EasyTest|Any CPU.Build.0 = EasyTest|Any CPU + {1EA5939B-0396-43BB-B9C8-4516F3EF00F9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1EA5939B-0396-43BB-B9C8-4516F3EF00F9}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/CS/NonPersistentObjectsDemo.Module.Web/Controllers/ReadMe.txt b/CS/NonPersistentObjectsDemo.Module.Web/Controllers/ReadMe.txt deleted file mode 100644 index 0ee4668..0000000 --- a/CS/NonPersistentObjectsDemo.Module.Web/Controllers/ReadMe.txt +++ /dev/null @@ -1,19 +0,0 @@ -Folder Description - -The "Controllers" project folder is intended for storing ASP.NET-specific Controller classes -that can change the default XAF application flow and add new features. - - -Relevant Documentation - -Controllers and Actions -https://docs.devexpress.com/eXpressAppFramework/112623 - -Controller Class -https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.Controller - -ViewController Class -https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.ViewController - -WindowController Class -https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.WindowController diff --git a/CS/NonPersistentObjectsDemo.Module.Web/Editors/ReadMe.txt b/CS/NonPersistentObjectsDemo.Module.Web/Editors/ReadMe.txt deleted file mode 100644 index 461813c..0000000 --- a/CS/NonPersistentObjectsDemo.Module.Web/Editors/ReadMe.txt +++ /dev/null @@ -1,31 +0,0 @@ -Folder Description - -This project folder is intended for storing custom ASP.NET List Editors, -Property Editors and View Items. - - -Relevant Documentation - -List Editors -https://docs.devexpress.com/eXpressAppFramework/113189 - -Implement Custom Property Editors -https://docs.devexpress.com/eXpressAppFramework/113097 - -View Items -https://docs.devexpress.com/eXpressAppFramework/112612 - -How to: Implement an ASP.NET Web List Editor Using a Custom Control -https://docs.devexpress.com/eXpressAppFramework/113126 - -How to: Implement a Property Editor (in ASP.NET Applications) -https://docs.devexpress.com/eXpressAppFramework/112678 - -How to: Implement a Property Editor for Specific Data Management (in ASP.NET Web Applications) -https://docs.devexpress.com/eXpressAppFramework/113116 - -How to: Customize a Built-in Web Property Editor -https://docs.devexpress.com/eXpressAppFramework/113114 - -How to: Implement a View Item -https://docs.devexpress.com/eXpressAppFramework/112641 \ No newline at end of file diff --git a/CS/NonPersistentObjectsDemo.Module.Web/Model.DesignedDiffs.xafml b/CS/NonPersistentObjectsDemo.Module.Web/Model.DesignedDiffs.xafml deleted file mode 100644 index b3b40cf..0000000 --- a/CS/NonPersistentObjectsDemo.Module.Web/Model.DesignedDiffs.xafml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/CS/NonPersistentObjectsDemo.Module.Web/NonPersistentObjectsDemo.Module.Web.csproj b/CS/NonPersistentObjectsDemo.Module.Web/NonPersistentObjectsDemo.Module.Web.csproj deleted file mode 100644 index 6b461c3..0000000 --- a/CS/NonPersistentObjectsDemo.Module.Web/NonPersistentObjectsDemo.Module.Web.csproj +++ /dev/null @@ -1,208 +0,0 @@ - - - - - Debug - AnyCPU - {EFD113F7-1ED0-472C-8EBE-B1A7CAFB6C2B} - Library - Properties - NonPersistentObjectsDemo.Module.Web - NonPersistentObjectsDemo.Module.Web - v4.5.2 - 512 - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - true - bin\EasyTest\ - TRACE;DEBUG;EASYTEST - full - AnyCPU - prompt - - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - - - Component - - - - WebModule.cs - - - - - - - - - - - - - - - - - - {57ACDBDB-006E-43D3-9308-97857F2FF75D} - NonPersistentObjectsDemo.Module - True - - - - - \ No newline at end of file diff --git a/CS/NonPersistentObjectsDemo.Module.Web/Properties/AssemblyInfo.cs b/CS/NonPersistentObjectsDemo.Module.Web/Properties/AssemblyInfo.cs deleted file mode 100644 index 5d5c9d6..0000000 --- a/CS/NonPersistentObjectsDemo.Module.Web/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("NonPersistentObjectsDemo.Module.Web")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("NonPersistentObjectsDemo.Module.Web")] -[assembly: AssemblyCopyright("Copyright © 2020")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("720e2161-0047-4cfe-a68c-433063a3ae53")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -[assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/CS/NonPersistentObjectsDemo.Module.Web/ReadMe.txt b/CS/NonPersistentObjectsDemo.Module.Web/ReadMe.txt deleted file mode 100644 index 853a0d9..0000000 --- a/CS/NonPersistentObjectsDemo.Module.Web/ReadMe.txt +++ /dev/null @@ -1,28 +0,0 @@ -Project Description - -This project implements an ASP.NET Module. Platform-specific application elements -can be implemented here (Controllers, Editors & View Items, etc.). The root project -folder contains the WebModule.cs(vb) file with the class that inherits ModuleBase. -This class can be designed with the Module Designer that allows you to view and -customize Module components: referenced modules, Controllers and business classes. -Additionally, the root folder contains Application Model difference files -(XAFML files) that keep application settings specific for the current Module. -Differences files can be designed with the Model Editor. - - -Relevant Documentation - -Application Solution Components -https://docs.devexpress.com/eXpressAppFramework/112569 - -ModuleBase Class -https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.ModuleBase - -Module Designer -https://docs.devexpress.com/eXpressAppFramework/112828 - -Application Model -https://docs.devexpress.com/eXpressAppFramework/112579 - -Model Editor -https://docs.devexpress.com/eXpressAppFramework/112582 \ No newline at end of file diff --git a/CS/NonPersistentObjectsDemo.Module.Web/WebModule.Designer.cs b/CS/NonPersistentObjectsDemo.Module.Web/WebModule.Designer.cs deleted file mode 100644 index 3c7c48d..0000000 --- a/CS/NonPersistentObjectsDemo.Module.Web/WebModule.Designer.cs +++ /dev/null @@ -1,41 +0,0 @@ -namespace NonPersistentObjectsDemo.Module.Web { - partial class NonPersistentObjectsDemoAspNetModule { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) { - if(disposing && (components != null)) { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Component Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() { - // - // NonPersistentObjectsDemoAspNetModule - // - this.RequiredModuleTypes.Add(typeof(NonPersistentObjectsDemo.Module.NonPersistentObjectsDemoModule)); - this.RequiredModuleTypes.Add(typeof(DevExpress.ExpressApp.Web.SystemModule.SystemAspNetModule)); - this.RequiredModuleTypes.Add(typeof(DevExpress.ExpressApp.FileAttachments.Web.FileAttachmentsAspNetModule)); - this.RequiredModuleTypes.Add(typeof(DevExpress.ExpressApp.ReportsV2.Web.ReportsAspNetModuleV2)); - this.RequiredModuleTypes.Add(typeof(DevExpress.ExpressApp.Scheduler.Web.SchedulerAspNetModule)); - this.RequiredModuleTypes.Add(typeof(DevExpress.ExpressApp.ScriptRecorder.Web.ScriptRecorderAspNetModule)); - this.RequiredModuleTypes.Add(typeof(DevExpress.ExpressApp.TreeListEditors.Web.TreeListEditorsAspNetModule)); - this.RequiredModuleTypes.Add(typeof(DevExpress.ExpressApp.Validation.Web.ValidationAspNetModule)); - } - - #endregion - } -} \ No newline at end of file diff --git a/CS/NonPersistentObjectsDemo.Module.Web/WebModule.cs b/CS/NonPersistentObjectsDemo.Module.Web/WebModule.cs deleted file mode 100644 index fe3e181..0000000 --- a/CS/NonPersistentObjectsDemo.Module.Web/WebModule.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using System.Linq; -using System.Text; -using System.ComponentModel; -using DevExpress.ExpressApp; -using DevExpress.ExpressApp.DC; -using System.Collections.Generic; -using DevExpress.ExpressApp.Model; -using DevExpress.ExpressApp.Editors; -using DevExpress.ExpressApp.Actions; -using DevExpress.ExpressApp.Updating; -using DevExpress.ExpressApp.Model.Core; -using DevExpress.ExpressApp.Model.DomainLogics; -using DevExpress.ExpressApp.Model.NodeGenerators; -using DevExpress.Persistent.BaseImpl; - -namespace NonPersistentObjectsDemo.Module.Web { - [ToolboxItemFilter("Xaf.Platform.Web")] - // For more typical usage scenarios, be sure to check out https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.ModuleBase. - public sealed partial class NonPersistentObjectsDemoAspNetModule : ModuleBase { - //private void Application_CreateCustomModelDifferenceStore(Object sender, CreateCustomModelDifferenceStoreEventArgs e) { - // e.Store = new ModelDifferenceDbStore((XafApplication)sender, typeof(ModelDifference), true, "Web"); - // e.Handled = true; - //} - private void Application_CreateCustomUserModelDifferenceStore(Object sender, CreateCustomModelDifferenceStoreEventArgs e) { - e.Store = new ModelDifferenceDbStore((XafApplication)sender, typeof(ModelDifference), false, "Web"); - e.Handled = true; - } - public NonPersistentObjectsDemoAspNetModule() { - InitializeComponent(); - } - public override IEnumerable GetModuleUpdaters(IObjectSpace objectSpace, Version versionFromDB) { - return ModuleUpdater.EmptyModuleUpdaters; - } - public override void Setup(XafApplication application) { - base.Setup(application); - //application.CreateCustomModelDifferenceStore += Application_CreateCustomModelDifferenceStore; - application.CreateCustomUserModelDifferenceStore += Application_CreateCustomUserModelDifferenceStore; - // Manage various aspects of the application UI and behavior at the module level. - } - } -} diff --git a/CS/NonPersistentObjectsDemo.Module.Win/Controllers/ReadMe.txt b/CS/NonPersistentObjectsDemo.Module.Win/Controllers/ReadMe.txt deleted file mode 100644 index b9c5dc3..0000000 --- a/CS/NonPersistentObjectsDemo.Module.Win/Controllers/ReadMe.txt +++ /dev/null @@ -1,19 +0,0 @@ -Folder Description - -The "Controllers" project folder is intended for storing platform-agnostic Controller classes -that can change the default XAF application flow and add new features. - - -Relevant Documentation - -Controllers and Actions -https://docs.devexpress.com/eXpressAppFramework/112623 - -Controller Class -https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.Controller - -ViewController Class -https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.ViewController - -WindowController Class -https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.WindowController diff --git a/CS/NonPersistentObjectsDemo.Module.Win/Model.DesignedDiffs.xafml b/CS/NonPersistentObjectsDemo.Module.Win/Model.DesignedDiffs.xafml deleted file mode 100644 index d5e5a36..0000000 --- a/CS/NonPersistentObjectsDemo.Module.Win/Model.DesignedDiffs.xafml +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/CS/NonPersistentObjectsDemo.Module.Win/NonPersistentObjectsDemo.Module.Win.csproj b/CS/NonPersistentObjectsDemo.Module.Win/NonPersistentObjectsDemo.Module.Win.csproj deleted file mode 100644 index 88b0e13..0000000 --- a/CS/NonPersistentObjectsDemo.Module.Win/NonPersistentObjectsDemo.Module.Win.csproj +++ /dev/null @@ -1,251 +0,0 @@ - - - - - Debug - AnyCPU - {72D644CD-C193-4572-B2E3-CA82819A1627} - Library - Properties - NonPersistentObjectsDemo.Module.Win - NonPersistentObjectsDemo.Module.Win - v4.5.2 - 512 - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - true - bin\EasyTest\ - TRACE;DEBUG;EASYTEST - full - AnyCPU - prompt - - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - System - False - - - False - - - System.Data - False - - - System.Drawing - False - - - System.Windows.Forms - False - - - System.XML - False - - - - - - Component - - - WinModule.cs - - - - - - - - - - - - - - - - - - - - - - - {57ACDBDB-006E-43D3-9308-97857F2FF75D} - NonPersistentObjectsDemo.Module - True - - - - - \ No newline at end of file diff --git a/CS/NonPersistentObjectsDemo.Module.Win/Properties/AssemblyInfo.cs b/CS/NonPersistentObjectsDemo.Module.Win/Properties/AssemblyInfo.cs deleted file mode 100644 index e91e305..0000000 --- a/CS/NonPersistentObjectsDemo.Module.Win/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("NonPersistentObjectsDemo.Module.Win")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("NonPersistentObjectsDemo.Module.Win")] -[assembly: AssemblyCopyright("Copyright © 2020")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("720e2161-0047-4cfe-a68c-433063a3ae53")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -[assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/CS/NonPersistentObjectsDemo.Module.Win/ReadMe.txt b/CS/NonPersistentObjectsDemo.Module.Win/ReadMe.txt deleted file mode 100644 index 17056ef..0000000 --- a/CS/NonPersistentObjectsDemo.Module.Win/ReadMe.txt +++ /dev/null @@ -1,29 +0,0 @@ -Project Description - -This project implements a WinForms Module. Platform-specific application -elements can be implemented here (Controllers, Editors & View Items, etc.). -The root project folder contains the WinModule.cs(vb) file with the class that -inherits ModuleBase. This class can be designed with the Module Designer that -allows you to view and customize Module components: referenced modules, -Controllers and business classes. Additionally, the root folder contains -Application Model difference files (XAFML files) that keep application -settings specific for the current Module. Differences files can be designed -with the Model Editor. - - -Relevant Documentation - -Application Solution Components -https://docs.devexpress.com/eXpressAppFramework/112569 - -ModuleBase Class -https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.ModuleBase - -Module Designer -https://docs.devexpress.com/eXpressAppFramework/112828 - -Application Model -https://docs.devexpress.com/eXpressAppFramework/112579 - -Model Editor -https://docs.devexpress.com/eXpressAppFramework/112582 diff --git a/CS/NonPersistentObjectsDemo.Module.Win/WinModule.Designer.cs b/CS/NonPersistentObjectsDemo.Module.Win/WinModule.Designer.cs deleted file mode 100644 index e407aed..0000000 --- a/CS/NonPersistentObjectsDemo.Module.Win/WinModule.Designer.cs +++ /dev/null @@ -1,41 +0,0 @@ -namespace NonPersistentObjectsDemo.Module.Win { - partial class NonPersistentObjectsDemoWindowsFormsModule { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) { - if(disposing && (components != null)) { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Component Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() { - // - // NonPersistentObjectsDemoWindowsFormsModule - // - this.RequiredModuleTypes.Add(typeof(NonPersistentObjectsDemo.Module.NonPersistentObjectsDemoModule)); - this.RequiredModuleTypes.Add(typeof(DevExpress.ExpressApp.Win.SystemModule.SystemWindowsFormsModule)); - this.RequiredModuleTypes.Add(typeof(DevExpress.ExpressApp.FileAttachments.Win.FileAttachmentsWindowsFormsModule)); - this.RequiredModuleTypes.Add(typeof(DevExpress.ExpressApp.ReportsV2.Win.ReportsWindowsFormsModuleV2)); - this.RequiredModuleTypes.Add(typeof(DevExpress.ExpressApp.Scheduler.Win.SchedulerWindowsFormsModule)); - this.RequiredModuleTypes.Add(typeof(DevExpress.ExpressApp.ScriptRecorder.Win.ScriptRecorderWindowsFormsModule)); - this.RequiredModuleTypes.Add(typeof(DevExpress.ExpressApp.TreeListEditors.Win.TreeListEditorsWindowsFormsModule)); - this.RequiredModuleTypes.Add(typeof(DevExpress.ExpressApp.Validation.Win.ValidationWindowsFormsModule)); - } - - #endregion - } -} \ No newline at end of file diff --git a/CS/NonPersistentObjectsDemo.Module.Win/WinModule.cs b/CS/NonPersistentObjectsDemo.Module.Win/WinModule.cs deleted file mode 100644 index e187371..0000000 --- a/CS/NonPersistentObjectsDemo.Module.Win/WinModule.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using System.Linq; -using System.Text; -using System.ComponentModel; -using DevExpress.ExpressApp; -using DevExpress.ExpressApp.DC; -using System.Collections.Generic; -using DevExpress.ExpressApp.Model; -using DevExpress.ExpressApp.Editors; -using DevExpress.ExpressApp.Actions; -using DevExpress.ExpressApp.Updating; -using DevExpress.ExpressApp.Model.Core; -using DevExpress.ExpressApp.Model.DomainLogics; -using DevExpress.ExpressApp.Model.NodeGenerators; -using DevExpress.Persistent.BaseImpl; - -namespace NonPersistentObjectsDemo.Module.Win { - [ToolboxItemFilter("Xaf.Platform.Win")] - // For more typical usage scenarios, be sure to check out https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.ModuleBase. - public sealed partial class NonPersistentObjectsDemoWindowsFormsModule : ModuleBase { - //private void Application_CreateCustomModelDifferenceStore(Object sender, CreateCustomModelDifferenceStoreEventArgs e) { - // e.Store = new ModelDifferenceDbStore((XafApplication)sender, typeof(ModelDifference), true, "Win"); - // e.Handled = true; - //} - private void Application_CreateCustomUserModelDifferenceStore(Object sender, CreateCustomModelDifferenceStoreEventArgs e) { - e.Store = new ModelDifferenceDbStore((XafApplication)sender, typeof(ModelDifference), false, "Win"); - e.Handled = true; - } - public NonPersistentObjectsDemoWindowsFormsModule() { - InitializeComponent(); - } - public override IEnumerable GetModuleUpdaters(IObjectSpace objectSpace, Version versionFromDB) { - return ModuleUpdater.EmptyModuleUpdaters; - } - public override void Setup(XafApplication application) { - base.Setup(application); - //application.CreateCustomModelDifferenceStore += Application_CreateCustomModelDifferenceStore; - application.CreateCustomUserModelDifferenceStore += Application_CreateCustomUserModelDifferenceStore; - // Manage various aspects of the application UI and behavior at the module level. - } - } -} diff --git a/CS/NonPersistentObjectsDemo.Module/BusinessObjects/ReadMe.txt b/CS/NonPersistentObjectsDemo.Module/BusinessObjects/ReadMe.txt deleted file mode 100644 index 09595b9..0000000 --- a/CS/NonPersistentObjectsDemo.Module/BusinessObjects/ReadMe.txt +++ /dev/null @@ -1,11 +0,0 @@ -Folder Description - -The "BusinessObjects" project folder is intended for storing the business objects -code. In XAF, a business object can be implemented as a base persistent class -descendant and as Domain Component interfaces. - -Relevant Documentation - -Business Model Design -https://docs.devexpress.com/eXpressAppFramework/112600 - diff --git a/CS/NonPersistentObjectsDemo.Module/Controllers/ReadMe.txt b/CS/NonPersistentObjectsDemo.Module/Controllers/ReadMe.txt deleted file mode 100644 index b9c5dc3..0000000 --- a/CS/NonPersistentObjectsDemo.Module/Controllers/ReadMe.txt +++ /dev/null @@ -1,19 +0,0 @@ -Folder Description - -The "Controllers" project folder is intended for storing platform-agnostic Controller classes -that can change the default XAF application flow and add new features. - - -Relevant Documentation - -Controllers and Actions -https://docs.devexpress.com/eXpressAppFramework/112623 - -Controller Class -https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.Controller - -ViewController Class -https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.ViewController - -WindowController Class -https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.WindowController diff --git a/CS/NonPersistentObjectsDemo.Module/DatabaseUpdate/Updater.cs b/CS/NonPersistentObjectsDemo.Module/DatabaseUpdate/Updater.cs deleted file mode 100644 index 1b13791..0000000 --- a/CS/NonPersistentObjectsDemo.Module/DatabaseUpdate/Updater.cs +++ /dev/null @@ -1,81 +0,0 @@ -using System; -using System.Linq; -using DevExpress.ExpressApp; -using DevExpress.Data.Filtering; -using DevExpress.Persistent.Base; -using DevExpress.ExpressApp.Updating; -using DevExpress.ExpressApp.Security; -using DevExpress.ExpressApp.SystemModule; -using DevExpress.ExpressApp.Security.Strategy; -using DevExpress.Xpo; -using DevExpress.ExpressApp.Xpo; -using DevExpress.Persistent.BaseImpl; -using DevExpress.Persistent.BaseImpl.PermissionPolicy; - -namespace NonPersistentObjectsDemo.Module.DatabaseUpdate { - // For more typical usage scenarios, be sure to check out https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.Updating.ModuleUpdater - public class Updater : ModuleUpdater { - public Updater(IObjectSpace objectSpace, Version currentDBVersion) : - base(objectSpace, currentDBVersion) { - } - public override void UpdateDatabaseAfterUpdateSchema() { - base.UpdateDatabaseAfterUpdateSchema(); - //CreateSecurityObjects(); - } - - #region Security - private void CreateSecurityObjects() { - PermissionPolicyUser sampleUser = ObjectSpace.FindObject(new BinaryOperator("UserName", "User")); - if(sampleUser == null) { - sampleUser = ObjectSpace.CreateObject(); - sampleUser.UserName = "User"; - sampleUser.SetPassword(""); - } - PermissionPolicyRole defaultRole = CreateDefaultRole(); - sampleUser.Roles.Add(defaultRole); - - PermissionPolicyUser userAdmin = ObjectSpace.FindObject(new BinaryOperator("UserName", "Admin")); - if(userAdmin == null) { - userAdmin = ObjectSpace.CreateObject(); - userAdmin.UserName = "Admin"; - // Set a password if the standard authentication type is used - userAdmin.SetPassword(""); - } - // If a role with the Administrators name doesn't exist in the database, create this role - PermissionPolicyRole adminRole = ObjectSpace.FindObject(new BinaryOperator("Name", "Administrators")); - if(adminRole == null) { - adminRole = ObjectSpace.CreateObject(); - adminRole.Name = "Administrators"; - } - adminRole.IsAdministrative = true; - userAdmin.Roles.Add(adminRole); - ObjectSpace.CommitChanges(); //This line persists created object(s). - } - #endregion - - public override void UpdateDatabaseBeforeUpdateSchema() { - base.UpdateDatabaseBeforeUpdateSchema(); - //if(CurrentDBVersion < new Version("1.1.0.0") && CurrentDBVersion > new Version("0.0.0.0")) { - // RenameColumn("DomainObject1Table", "OldColumnName", "NewColumnName"); - //} - } - private PermissionPolicyRole CreateDefaultRole() { - PermissionPolicyRole defaultRole = ObjectSpace.FindObject(new BinaryOperator("Name", "Default")); - if(defaultRole == null) { - defaultRole = ObjectSpace.CreateObject(); - defaultRole.Name = "Default"; - - defaultRole.AddObjectPermission(SecurityOperations.Read, "[Oid] = CurrentUserId()", SecurityPermissionState.Allow); - defaultRole.AddNavigationPermission(@"Application/NavigationItems/Items/Default/Items/MyDetails", SecurityPermissionState.Allow); - defaultRole.AddMemberPermission(SecurityOperations.Write, "ChangePasswordOnFirstLogon", "[Oid] = CurrentUserId()", SecurityPermissionState.Allow); - defaultRole.AddMemberPermission(SecurityOperations.Write, "StoredPassword", "[Oid] = CurrentUserId()", SecurityPermissionState.Allow); - defaultRole.AddTypePermissionsRecursively(SecurityOperations.Read, SecurityPermissionState.Deny); - defaultRole.AddTypePermissionsRecursively(SecurityOperations.ReadWriteAccess, SecurityPermissionState.Allow); - defaultRole.AddTypePermissionsRecursively(SecurityOperations.ReadWriteAccess, SecurityPermissionState.Allow); - defaultRole.AddTypePermissionsRecursively(SecurityOperations.Create, SecurityPermissionState.Allow); - defaultRole.AddTypePermissionsRecursively(SecurityOperations.Create, SecurityPermissionState.Allow); - } - return defaultRole; - } - } -} diff --git a/CS/NonPersistentObjectsDemo.Module/FunctionalTests/ReadMe.txt b/CS/NonPersistentObjectsDemo.Module/FunctionalTests/ReadMe.txt deleted file mode 100644 index fb0b599..0000000 --- a/CS/NonPersistentObjectsDemo.Module/FunctionalTests/ReadMe.txt +++ /dev/null @@ -1,10 +0,0 @@ -Folder Description - -The "FunctionalTests" project folder is intended for storing EasyTest -configuration file and scripts. - - -Relevant Documentation - -Functional Testing -https://docs.devexpress.com/eXpressAppFramework/113206 diff --git a/CS/NonPersistentObjectsDemo.Module/FunctionalTests/config.xml b/CS/NonPersistentObjectsDemo.Module/FunctionalTests/config.xml deleted file mode 100644 index 8fcf398..0000000 --- a/CS/NonPersistentObjectsDemo.Module/FunctionalTests/config.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/CS/NonPersistentObjectsDemo.Module/FunctionalTests/sample.ets b/CS/NonPersistentObjectsDemo.Module/FunctionalTests/sample.ets deleted file mode 100644 index ab78fc2..0000000 --- a/CS/NonPersistentObjectsDemo.Module/FunctionalTests/sample.ets +++ /dev/null @@ -1,20 +0,0 @@ -;#DropDB NonPersistentObjectsDemoEasyTest - -#Application NonPersistentObjectsDemoWin -#Application NonPersistentObjectsDemoWeb - -*FillForm - User Name = Admin -*Action Log In - -#IfDef NonPersistentObjectsDemoWin - -*Action About... - -*Action OK - -#EndIf - -#IfDef NonPersistentObjectsDemoWeb -*Action Navigation(My Details) -#EndIf diff --git a/CS/NonPersistentObjectsDemo.Module/Model.DesignedDiffs.xafml b/CS/NonPersistentObjectsDemo.Module/Model.DesignedDiffs.xafml deleted file mode 100644 index fbd248d..0000000 --- a/CS/NonPersistentObjectsDemo.Module/Model.DesignedDiffs.xafml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/CS/NonPersistentObjectsDemo.Module/Module.Designer.cs b/CS/NonPersistentObjectsDemo.Module/Module.Designer.cs deleted file mode 100644 index 4be439d..0000000 --- a/CS/NonPersistentObjectsDemo.Module/Module.Designer.cs +++ /dev/null @@ -1,50 +0,0 @@ -namespace NonPersistentObjectsDemo.Module { - partial class NonPersistentObjectsDemoModule { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) { - if(disposing && (components != null)) { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Component Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() { - // - // NonPersistentObjectsDemoModule - // - this.AdditionalExportedTypes.Add(typeof(DevExpress.Persistent.BaseImpl.ModelDifference)); - this.AdditionalExportedTypes.Add(typeof(DevExpress.Persistent.BaseImpl.ModelDifferenceAspect)); - this.AdditionalExportedTypes.Add(typeof(DevExpress.Persistent.BaseImpl.BaseObject)); - //this.AdditionalExportedTypes.Add(typeof(DevExpress.Persistent.BaseImpl.FileData)); - //this.AdditionalExportedTypes.Add(typeof(DevExpress.Persistent.BaseImpl.FileAttachmentBase)); - //this.AdditionalExportedTypes.Add(typeof(DevExpress.Persistent.BaseImpl.Event)); - //this.AdditionalExportedTypes.Add(typeof(DevExpress.Persistent.BaseImpl.Resource)); - //this.AdditionalExportedTypes.Add(typeof(DevExpress.Persistent.BaseImpl.HCategory)); - this.RequiredModuleTypes.Add(typeof(DevExpress.ExpressApp.SystemModule.SystemModule)); - this.RequiredModuleTypes.Add(typeof(DevExpress.ExpressApp.Objects.BusinessClassLibraryCustomizationModule)); - this.RequiredModuleTypes.Add(typeof(DevExpress.ExpressApp.CloneObject.CloneObjectModule)); - this.RequiredModuleTypes.Add(typeof(DevExpress.ExpressApp.ConditionalAppearance.ConditionalAppearanceModule)); - this.RequiredModuleTypes.Add(typeof(DevExpress.ExpressApp.ReportsV2.ReportsModuleV2)); - this.RequiredModuleTypes.Add(typeof(DevExpress.ExpressApp.Scheduler.SchedulerModuleBase)); - this.RequiredModuleTypes.Add(typeof(DevExpress.ExpressApp.ScriptRecorder.ScriptRecorderModuleBase)); - this.RequiredModuleTypes.Add(typeof(DevExpress.ExpressApp.TreeListEditors.TreeListEditorsModuleBase)); - this.RequiredModuleTypes.Add(typeof(DevExpress.ExpressApp.Validation.ValidationModule)); - } - - #endregion - } -} diff --git a/CS/NonPersistentObjectsDemo.Module/Module.cs b/CS/NonPersistentObjectsDemo.Module/Module.cs deleted file mode 100644 index 37f7721..0000000 --- a/CS/NonPersistentObjectsDemo.Module/Module.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System; -using System.Text; -using System.Linq; -using DevExpress.ExpressApp; -using System.ComponentModel; -using DevExpress.ExpressApp.DC; -using System.Collections.Generic; -using DevExpress.Persistent.Base; -using DevExpress.Persistent.BaseImpl; -using DevExpress.Persistent.BaseImpl.PermissionPolicy; -using DevExpress.ExpressApp.Model; -using DevExpress.ExpressApp.Actions; -using DevExpress.ExpressApp.Editors; -using DevExpress.ExpressApp.Updating; -using DevExpress.ExpressApp.Model.Core; -using DevExpress.ExpressApp.Model.DomainLogics; -using DevExpress.ExpressApp.Model.NodeGenerators; -using DevExpress.ExpressApp.Xpo; -using NonPersistentObjectsDemo.Module.BusinessObjects; - -namespace NonPersistentObjectsDemo.Module { - // For more typical usage scenarios, be sure to check out https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.ModuleBase. - public sealed partial class NonPersistentObjectsDemoModule : ModuleBase { - public NonPersistentObjectsDemoModule() { - InitializeComponent(); - BaseObject.OidInitializationMode = OidInitializationMode.AfterConstruction; - } - public override IEnumerable GetModuleUpdaters(IObjectSpace objectSpace, Version versionFromDB) { - ModuleUpdater updater = new DatabaseUpdate.Updater(objectSpace, versionFromDB); - return new ModuleUpdater[] { updater }; - } - public override void Setup(XafApplication application) { - base.Setup(application); - // Manage various aspects of the application UI and behavior at the module level. - application.SetupComplete += Application_SetupComplete; - } - private void Application_SetupComplete(object sender, EventArgs e) { - Application.ObjectSpaceCreated += Application_ObjectSpaceCreated; - } - private void Application_ObjectSpaceCreated(object sender, ObjectSpaceCreatedEventArgs e) { - var npos = e.ObjectSpace as NonPersistentObjectSpace; - if(npos != null) { - new ArticleAdapter(npos); - new ContactAdapter(npos); - } - } - public override void CustomizeTypesInfo(ITypesInfo typesInfo) { - base.CustomizeTypesInfo(typesInfo); - CalculatedPersistentAliasHelper.CustomizeTypesInfo(typesInfo); - } - } -} diff --git a/CS/NonPersistentObjectsDemo.Module/NonPersistentObjectsDemo.Module.csproj b/CS/NonPersistentObjectsDemo.Module/NonPersistentObjectsDemo.Module.csproj deleted file mode 100644 index 44fb8c2..0000000 --- a/CS/NonPersistentObjectsDemo.Module/NonPersistentObjectsDemo.Module.csproj +++ /dev/null @@ -1,173 +0,0 @@ - - - - - Debug - AnyCPU - {57ACDBDB-006E-43D3-9308-97857F2FF75D} - Library - Properties - NonPersistentObjectsDemo.Module - NonPersistentObjectsDemo.Module - v4.5.2 - 512 - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - true - bin\EasyTest\ - TRACE;DEBUG;EASYTEST - full - AnyCPU - prompt - - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - System - - - System.Data - - - - System.XML - - - - - - - - Component - - - - Component - - - Module.cs - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/CS/NonPersistentObjectsDemo.Module/Properties/AssemblyInfo.cs b/CS/NonPersistentObjectsDemo.Module/Properties/AssemblyInfo.cs deleted file mode 100644 index 87b67a8..0000000 --- a/CS/NonPersistentObjectsDemo.Module/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("NonPersistentObjectsDemo.Module")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("NonPersistentObjectsDemo.Module")] -[assembly: AssemblyCopyright("Copyright © 2020")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("720e2161-0047-4cfe-a68c-433063a3ae53")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -[assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/CS/NonPersistentObjectsDemo.Module/ReadMe.txt b/CS/NonPersistentObjectsDemo.Module/ReadMe.txt deleted file mode 100644 index a96fb7a..0000000 --- a/CS/NonPersistentObjectsDemo.Module/ReadMe.txt +++ /dev/null @@ -1,28 +0,0 @@ -Project Description - -This project implements a platform-agnostic Module. UI-independent application -elements can be implemented here (Business Objects, Controllers, etc.). The root -project folder contains the Module.cs(vb) file with the class that inherits -ModuleBase. This class can be designed with the Module Designer that allows -you to view and customize Module components: referenced modules, Controllers -and business classes. Additionally, the root folder contains Application Model -difference files (XAFML files) that keep application settings specific for the -current Module. Differences files can be designed with the Model Editor. - - -Relevant Documentation - -Application Solution Components -https://docs.devexpress.com/eXpressAppFramework/112569 - -ModuleBase Class -https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.ModuleBase - -Module Designer -https://docs.devexpress.com/eXpressAppFramework/112828 - -Application Model -https://docs.devexpress.com/eXpressAppFramework/112579 - -Model Editor -https://docs.devexpress.com/eXpressAppFramework/112582 diff --git a/CS/NonPersistentObjectsDemo.Module/Util.cs b/CS/NonPersistentObjectsDemo.Module/Util.cs deleted file mode 100644 index 3a6ac71..0000000 --- a/CS/NonPersistentObjectsDemo.Module/Util.cs +++ /dev/null @@ -1,101 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace NonPersistentObjectsDemo.Module { - - public class GenHelper { - private static Random srnd; - private static List words; - private static List fnames; - private static List lnames; - static GenHelper() { - srnd = new Random(); - words = CreateWords(12000); - fnames = CreateNames(200); - lnames = CreateNames(500); - } - private static List CreateWords(int number) { - var items = new HashSet(); - while(number > 0) { - if(items.Add(CreateWord())) { - number--; - } - } - return items.ToList(); - } - private static string MakeTosh(Random rnd, int length) { - var chars = new char[length]; - for(int i = 0; i < length; i++) { - chars[i] = (char)('a' + rnd.Next(26)); - } - return new String(chars); - } - private static string CreateWord() { - return MakeTosh(srnd, 1 + srnd.Next(13)); - } - private static List CreateNames(int number) { - var items = new HashSet(); - while(number > 0) { - if(items.Add(ToTitle(CreateWord()))) { - number--; - } - } - return items.ToList(); - } - public static string ToTitle(string s) { - if(string.IsNullOrEmpty(s)) - return s; - return string.Concat(s.Substring(0, 1).ToUpper(), s.Substring(1)); - } - - private Random rnd; - public GenHelper() { - rnd = new Random(); - } - public GenHelper(int seed) { - rnd = new Random(seed); - } - public int Next(int max) { - return rnd.Next(max); - } - public string MakeTosh(int length) { - return MakeTosh(rnd, length); - } - public string MakeBlah(int length) { - var sb = new StringBuilder(); - for(var i = 0; i <= length; i++) { - if(sb.Length > 0) { - sb.Append(" "); - } - sb.Append(GetWord()); - } - return sb.ToString(); - } - public string MakeBlahBlahBlah(int length, int plength) { - var sb = new StringBuilder(); - for(var i = 0; i <= length; i++) { - if(sb.Length > 0) { - sb.Append(" "); - } - var w = ToTitle(MakeBlah(3 + rnd.Next(plength))) + "."; - sb.Append(w); - } - return sb.ToString(); - } - public string GetFullName() { - return string.Concat(GetFName(), " ", GetLName()); - } - private string GetFName() { - return fnames[rnd.Next(fnames.Count)]; - } - private string GetLName() { - return lnames[rnd.Next(lnames.Count)]; - } - private string GetWord() { - return words[rnd.Next(words.Count)]; - } - } -} diff --git a/CS/NonPersistentObjectsDemo.Module/Welcome.html b/CS/NonPersistentObjectsDemo.Module/Welcome.html deleted file mode 100644 index d27bb12..0000000 --- a/CS/NonPersistentObjectsDemo.Module/Welcome.html +++ /dev/null @@ -1,185 +0,0 @@ - - - - - Your XAF application - - - - - - -
- - - - - -
-
-

The XAF Solution Wizard has successfully generated the solution according to your settings.

-
    -
  • The NonPersistentObjectsDemo.Module project keeps your platform-agnostic code. - Add persistent objects code to the Business Objects folder of this project and XAF will automatically create a UI to create, read, update and delete these persistent objects.
  • -
  • The NonPersistentObjectsDemo.Win project is a startup project for the desktop application.
  • -
  • The NonPersistentObjectsDemo.Web project is a startup project for the web application.
  • -
  • To specify the database used by your application, modify the ConnectionString attribute in the configuration file located in the startup project.
  • -
  • To login, enter the "Admin" user name with empty password.
  • -
-
-
- - - - - -
-
- - - \ No newline at end of file diff --git a/CS/NonPersistentObjectsDemo.Web/Default.aspx b/CS/NonPersistentObjectsDemo.Web/Default.aspx deleted file mode 100644 index 918be8f..0000000 --- a/CS/NonPersistentObjectsDemo.Web/Default.aspx +++ /dev/null @@ -1,19 +0,0 @@ -<%@ Page Language="C#" AutoEventWireup="true" Inherits="Default" EnableViewState="false" - ValidateRequest="false" CodeBehind="Default.aspx.cs" %> -<%@ Register Assembly="DevExpress.ExpressApp.Web.v20.1" - Namespace="DevExpress.ExpressApp.Web.Templates" TagPrefix="cc3" %> -<%@ Register Assembly="DevExpress.ExpressApp.Web.v20.1" - Namespace="DevExpress.ExpressApp.Web.Controls" TagPrefix="cc4" %> - - - - Main Page - - - -
- -
- - - \ No newline at end of file diff --git a/CS/NonPersistentObjectsDemo.Web/Default.aspx.cs b/CS/NonPersistentObjectsDemo.Web/Default.aspx.cs deleted file mode 100644 index ad151ab..0000000 --- a/CS/NonPersistentObjectsDemo.Web/Default.aspx.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Web.UI; -using DevExpress.ExpressApp.Templates; -using DevExpress.ExpressApp.Web; -using DevExpress.ExpressApp.Web.Templates; -using DevExpress.ExpressApp.Web.Templates.ActionContainers; - -public partial class Default : BaseXafPage { - protected override ContextActionsMenu CreateContextActionsMenu() { - return new ContextActionsMenu(this, "Edit", "RecordEdit", "ObjectsCreation", "ListView", "Reports"); - } - public override Control InnerContentPlaceHolder { - get { - return Content; - } - } -} \ No newline at end of file diff --git a/CS/NonPersistentObjectsDemo.Web/Default.aspx.designer.cs b/CS/NonPersistentObjectsDemo.Web/Default.aspx.designer.cs deleted file mode 100644 index 58a6e63..0000000 --- a/CS/NonPersistentObjectsDemo.Web/Default.aspx.designer.cs +++ /dev/null @@ -1,40 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - - - -public partial class Default { - - /// - /// form2 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.HtmlControls.HtmlForm form2; - - /// - /// ProgressControl control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::DevExpress.ExpressApp.Web.Controls.ASPxProgressControl ProgressControl; - - /// - /// Content control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.HtmlControls.HtmlGenericControl Content; -} diff --git a/CS/NonPersistentObjectsDemo.Web/Error.aspx b/CS/NonPersistentObjectsDemo.Web/Error.aspx deleted file mode 100644 index 5cd4348..0000000 --- a/CS/NonPersistentObjectsDemo.Web/Error.aspx +++ /dev/null @@ -1,147 +0,0 @@ -<%@ Page Language="c#" AutoEventWireup="false" Inherits="ErrorPage" EnableViewState="false" - ValidateRequest="false" CodeBehind="Error.aspx.cs" %> - - - - Error - - - - -
- - - - -
-
-
- - - - - -
-

- -

-
- -
- -
- - - - -
- - - -

-

- -

- - We are currently unable to serve your request.
- You could go back and - try again or - restart the application. -
-

- - - - Show Error details - - - - Report error
-
-

- This error has been logged. If you have additional information that you believe - may have caused this error please report the problem.

- - - - - - - -
- -
- -
-
-
-
-
-
-
-
-
-
-
- -
- - diff --git a/CS/NonPersistentObjectsDemo.Web/Error.aspx.cs b/CS/NonPersistentObjectsDemo.Web/Error.aspx.cs deleted file mode 100644 index 7928158..0000000 --- a/CS/NonPersistentObjectsDemo.Web/Error.aspx.cs +++ /dev/null @@ -1,75 +0,0 @@ -using System; -using System.Web.UI; -using DevExpress.ExpressApp.Web; -using DevExpress.ExpressApp.Web.SystemModule; -using DevExpress.ExpressApp.Web.Templates; -using DevExpress.ExpressApp.Web.TestScripts; - -public partial class ErrorPage : System.Web.UI.Page { - protected override void InitializeCulture() { - if(WebApplication.Instance != null) - WebApplication.Instance.InitializeCulture(); - } - protected override void OnPreInit(EventArgs e) { - base.OnPreInit(e); - BaseXafPage.SetupCurrentTheme(); - } - private void Page_Load(object sender, System.EventArgs e) { - if(TestScriptsManager.EasyTestEnabled) { - TestScriptsManager testScriptsManager = new TestScriptsManager(Page); - testScriptsManager.RegisterControl(JSLabelTestControl.ClassName, "FormCaption", TestControlType.Field, "FormCaption"); - testScriptsManager.RegisterControl(JSLabelTestControl.ClassName, "DescriptionTextBox", TestControlType.Field, "Description"); - testScriptsManager.RegisterControl(JSDefaultTestControl.ClassName, "ReportButton", TestControlType.Action, "Report"); - testScriptsManager.AllControlRegistered(); - ClientScript.RegisterStartupScript(GetType(), "EasyTest", testScriptsManager.GetScript(), true); - } - if(WebApplication.Instance != null) { - ApplicationTitle.Text = WebApplication.Instance.Title; - } - else { - ApplicationTitle.Text = "No application"; - } - Header.Title = "Application Error - " + ApplicationTitle.Text; - - ErrorInfo errorInfo = ErrorHandling.GetApplicationError(); - if(errorInfo != null) { - if(ErrorHandling.CanShowDetailedInformation) { - DetailsText.Text = errorInfo.GetTextualPresentation(true); - } - else { - Details.Visible = false; - } - ReportForm.Visible = ErrorHandling.CanSendAlertToAdmin; - } - else { - ErrorPanel.Visible = false; - } - } - #region Web Form Designer generated code - override protected void OnInit(EventArgs e) { - InitializeComponent(); - base.OnInit(e); - } - - private void InitializeComponent() { - this.Load += new System.EventHandler(this.Page_Load); - this.PreRender += new EventHandler(ErrorPage_PreRender); - } - - private void ErrorPage_PreRender(object sender, EventArgs e) { - RegisterThemeAssemblyController.RegisterThemeResources((Page)sender); - } - - - #endregion - protected void ReportButton_Click(object sender, EventArgs e) { - ErrorInfo errorInfo = ErrorHandling.GetApplicationError(); - if(errorInfo != null) { - ErrorHandling.SendAlertToAdmin(errorInfo.Id, DescriptionTextBox.Text, errorInfo.Exception.Message); - ClientScript.RegisterStartupScript(GetType(), "alert", "alert('Your report has been sent. Thank you.');", true); - } - } - protected void NavigateToStart_Click(object sender, EventArgs e) { - WebApplication.Instance.LogOff(); - } -} diff --git a/CS/NonPersistentObjectsDemo.Web/Error.aspx.designer.cs b/CS/NonPersistentObjectsDemo.Web/Error.aspx.designer.cs deleted file mode 100644 index 5427628..0000000 --- a/CS/NonPersistentObjectsDemo.Web/Error.aspx.designer.cs +++ /dev/null @@ -1,166 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - - - -public partial class ErrorPage { - - /// - /// Head1 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.HtmlControls.HtmlHead Head1; - - /// - /// form1 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.HtmlControls.HtmlForm form1; - - /// - /// ApplicationTitle control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Literal ApplicationTitle; - - /// - /// InfoMessagesPanel control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Literal InfoMessagesPanel; - - /// - /// Table1 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Table Table1; - - /// - /// TableRow2 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TableRow TableRow2; - - /// - /// ViewSite control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TableCell ViewSite; - - /// - /// ErrorTitleLiteral control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Literal ErrorTitleLiteral; - - /// - /// ErrorPanel control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Panel ErrorPanel; - - /// - /// ApologizeMessage control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.PlaceHolder ApologizeMessage; - - /// - /// HyperLink1 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.HyperLink HyperLink1; - - /// - /// NavigateToStart control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.LinkButton NavigateToStart; - - /// - /// Details control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Panel Details; - - /// - /// DetailsText control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Literal DetailsText; - - /// - /// ReportForm control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Panel ReportForm; - - /// - /// DescriptionTextBox control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox DescriptionTextBox; - - /// - /// ReportButton control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Button ReportButton; -} diff --git a/CS/NonPersistentObjectsDemo.Web/Global.asax b/CS/NonPersistentObjectsDemo.Web/Global.asax deleted file mode 100644 index 129093f..0000000 --- a/CS/NonPersistentObjectsDemo.Web/Global.asax +++ /dev/null @@ -1 +0,0 @@ -<%@ Application Language="C#" CodeBehind="Global.asax.cs" Inherits="NonPersistentObjectsDemo.Web.Global"%> diff --git a/CS/NonPersistentObjectsDemo.Web/Global.asax.cs b/CS/NonPersistentObjectsDemo.Web/Global.asax.cs deleted file mode 100644 index 1646c4f..0000000 --- a/CS/NonPersistentObjectsDemo.Web/Global.asax.cs +++ /dev/null @@ -1,75 +0,0 @@ -using System; -using System.Configuration; -using System.Web.Configuration; -using System.Web; -using System.Web.Routing; - -using DevExpress.ExpressApp; -using DevExpress.Persistent.Base; -using DevExpress.Persistent.BaseImpl; -using DevExpress.ExpressApp.Security; -using DevExpress.ExpressApp.Web; -using DevExpress.Web; - -namespace NonPersistentObjectsDemo.Web { - public class Global : System.Web.HttpApplication { - public Global() { - InitializeComponent(); - } - protected void Application_Start(Object sender, EventArgs e) { - RouteTable.Routes.RegisterXafRoutes(); - DevExpress.ExpressApp.BaseObjectSpace.ThrowExceptionForNotRegisteredEntityType = true; - ASPxWebControl.CallbackError += new EventHandler(Application_Error); -#if EASYTEST - DevExpress.ExpressApp.Web.TestScripts.TestScriptsManager.EasyTestEnabled = true; -#endif - } - protected void Session_Start(Object sender, EventArgs e) { - Tracing.Initialize(); - WebApplication.SetInstance(Session, new NonPersistentObjectsDemoAspNetApplication()); - //SecurityStrategy security = (SecurityStrategy)WebApplication.Instance.Security; - //security.RegisterXPOAdapterProviders(); - DevExpress.ExpressApp.Web.Templates.DefaultVerticalTemplateContentNew.ClearSizeLimit(); - WebApplication.Instance.SwitchToNewStyle(); - if(ConfigurationManager.ConnectionStrings["ConnectionString"] != null) { - WebApplication.Instance.ConnectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString; - } -#if EASYTEST - if(ConfigurationManager.ConnectionStrings["EasyTestConnectionString"] != null) { - WebApplication.Instance.ConnectionString = ConfigurationManager.ConnectionStrings["EasyTestConnectionString"].ConnectionString; - } -#endif - WebApplication.Instance.ConnectionString = DevExpress.ExpressApp.Xpo.InMemoryDataStoreProvider.ConnectionString; -#if DEBUG - if(System.Diagnostics.Debugger.IsAttached && WebApplication.Instance.CheckCompatibilityType == CheckCompatibilityType.DatabaseSchema) { - WebApplication.Instance.DatabaseUpdateMode = DatabaseUpdateMode.UpdateDatabaseAlways; - } -#endif - WebApplication.Instance.Setup(); - WebApplication.Instance.Start(); - } - protected void Application_BeginRequest(Object sender, EventArgs e) { - } - protected void Application_EndRequest(Object sender, EventArgs e) { - } - protected void Application_AuthenticateRequest(Object sender, EventArgs e) { - } - protected void Application_Error(Object sender, EventArgs e) { - ErrorHandling.Instance.ProcessApplicationError(); - } - protected void Session_End(Object sender, EventArgs e) { - WebApplication.LogOff(Session); - WebApplication.DisposeInstance(Session); - } - protected void Application_End(Object sender, EventArgs e) { - } - #region Web Form Designer generated code - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() { - } - #endregion - } -} diff --git a/CS/NonPersistentObjectsDemo.Web/Login.aspx b/CS/NonPersistentObjectsDemo.Web/Login.aspx deleted file mode 100644 index b610ff1..0000000 --- a/CS/NonPersistentObjectsDemo.Web/Login.aspx +++ /dev/null @@ -1,24 +0,0 @@ -<%@ Page Language="C#" AutoEventWireup="true" Inherits="LoginPage" EnableViewState="false" - ValidateRequest="false" CodeBehind="Login.aspx.cs" %> -<%@ Register Assembly="DevExpress.ExpressApp.Web.v20.1" - Namespace="DevExpress.ExpressApp.Web.Templates.ActionContainers" TagPrefix="cc2" %> -<%@ Register Assembly="DevExpress.ExpressApp.Web.v20.1" - Namespace="DevExpress.ExpressApp.Web.Templates.Controls" TagPrefix="tc" %> -<%@ Register Assembly="DevExpress.ExpressApp.Web.v20.1" - Namespace="DevExpress.ExpressApp.Web.Controls" TagPrefix="cc4" %> -<%@ Register Assembly="DevExpress.ExpressApp.Web.v20.1" - Namespace="DevExpress.ExpressApp.Web.Templates" TagPrefix="cc3" %> - - - - Logon - - -
-
- -
- -
- - diff --git a/CS/NonPersistentObjectsDemo.Web/Login.aspx.cs b/CS/NonPersistentObjectsDemo.Web/Login.aspx.cs deleted file mode 100644 index faecf7b..0000000 --- a/CS/NonPersistentObjectsDemo.Web/Login.aspx.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; - -using DevExpress.ExpressApp.Web; -using DevExpress.ExpressApp.Web.Templates; - -public partial class LoginPage : BaseXafPage { - public override System.Web.UI.Control InnerContentPlaceHolder { - get { - return Content; - } - } -} diff --git a/CS/NonPersistentObjectsDemo.Web/Login.aspx.designer.cs b/CS/NonPersistentObjectsDemo.Web/Login.aspx.designer.cs deleted file mode 100644 index 769ff3e..0000000 --- a/CS/NonPersistentObjectsDemo.Web/Login.aspx.designer.cs +++ /dev/null @@ -1,49 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - - - -public partial class LoginPage { - - /// - /// Head1 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.HtmlControls.HtmlHead Head1; - - /// - /// form1 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.HtmlControls.HtmlForm form1; - - /// - /// ProgressControl control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::DevExpress.ExpressApp.Web.Controls.ASPxProgressControl ProgressControl; - - /// - /// Content control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.HtmlControls.HtmlGenericControl Content; -} diff --git a/CS/NonPersistentObjectsDemo.Web/Model.Desktop.xafml b/CS/NonPersistentObjectsDemo.Web/Model.Desktop.xafml deleted file mode 100644 index ab80ccd..0000000 --- a/CS/NonPersistentObjectsDemo.Web/Model.Desktop.xafml +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/CS/NonPersistentObjectsDemo.Web/Model.Tablet.xafml b/CS/NonPersistentObjectsDemo.Web/Model.Tablet.xafml deleted file mode 100644 index ab80ccd..0000000 --- a/CS/NonPersistentObjectsDemo.Web/Model.Tablet.xafml +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/CS/NonPersistentObjectsDemo.Web/Model.xafml b/CS/NonPersistentObjectsDemo.Web/Model.xafml deleted file mode 100644 index ab80ccd..0000000 --- a/CS/NonPersistentObjectsDemo.Web/Model.xafml +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/CS/NonPersistentObjectsDemo.Web/NonPersistentObjectsDemo.Web.csproj b/CS/NonPersistentObjectsDemo.Web/NonPersistentObjectsDemo.Web.csproj deleted file mode 100644 index 4961be1..0000000 --- a/CS/NonPersistentObjectsDemo.Web/NonPersistentObjectsDemo.Web.csproj +++ /dev/null @@ -1,364 +0,0 @@ - - - - - Debug - AnyCPU - {8C3026D1-113C-4B88-9F91-236753790C60} - {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} - Library - Properties - NonPersistentObjectsDemo.Web - NonPersistentObjectsDemo.Web - v4.5.2 - 512 - false - 44300 - enabled - disabled - false - - - - - true - full - false - bin\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\ - TRACE - prompt - 4 - - - true - bin\ - TRACE;DEBUG;EASYTEST - full - AnyCPU - prompt - - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - False - - - False - False - - - False - False - - - False - False - - - False - False - - - False - False - - - False - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - - - - - - - - - - Default.aspx - - - Error.aspx - - - Global.asax - - - Login.aspx - - - Component - - - Default.aspx - ASPXCodeBehind - - - Error.aspx - ASPXCodeBehind - - - Login.aspx - ASPXCodeBehind - - - - - - Designer - - - - - - - - - - - {EFD113F7-1ED0-472C-8EBE-B1A7CAFB6C2B} - NonPersistentObjectsDemo.Module.Web - True - - - {57ACDBDB-006E-43D3-9308-97857F2FF75D} - NonPersistentObjectsDemo.Module - True - - - - 10.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - - - - - - - False - True - 2064 - / - - - False - False - - - False - - - - - \ No newline at end of file diff --git a/CS/NonPersistentObjectsDemo.Web/Properties/AssemblyInfo.cs b/CS/NonPersistentObjectsDemo.Web/Properties/AssemblyInfo.cs deleted file mode 100644 index 3ce642c..0000000 --- a/CS/NonPersistentObjectsDemo.Web/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("NonPersistentObjectsDemo.Web")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("NonPersistentObjectsDemo.Web")] -[assembly: AssemblyCopyright("Copyright © 2020")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("720e2161-0047-4cfe-a68c-433063a3ae53")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/CS/NonPersistentObjectsDemo.Web/ReadMe.txt b/CS/NonPersistentObjectsDemo.Web/ReadMe.txt deleted file mode 100644 index db74671..0000000 --- a/CS/NonPersistentObjectsDemo.Web/ReadMe.txt +++ /dev/null @@ -1,31 +0,0 @@ -Project Description - -This project implements an ASP.NET application. The ApplicationCode project -folder contains the WebApplication.cs(vb) file with the class that inherits -WebApplication. This class can be designed with the Application Designer that -allows you to view and customize application components: referenced modules, -security settings, data connection. Additionally, the root folder contains -Application Model difference files (XAFML files) that keep application settings -specific for the current application. Differences files can be designed with -the Model Editor. - - -Relevant Documentation - -Application Solution Components -https://docs.devexpress.com/eXpressAppFramework/112569 - -WebApplication Class -https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.Web.WebApplication - -XafApplication Class -https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.XafApplication - -Application Designer -https://docs.devexpress.com/eXpressAppFramework/112827 - -Application Model -https://docs.devexpress.com/eXpressAppFramework/112579 - -Model Editor -https://docs.devexpress.com/eXpressAppFramework/112582 diff --git a/CS/NonPersistentObjectsDemo.Web/Web.config b/CS/NonPersistentObjectsDemo.Web/Web.config deleted file mode 100644 index 5d1bace..0000000 --- a/CS/NonPersistentObjectsDemo.Web/Web.config +++ /dev/null @@ -1,184 +0,0 @@ - - - - - -
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/CS/NonPersistentObjectsDemo.Web/WebApplication.cs b/CS/NonPersistentObjectsDemo.Web/WebApplication.cs deleted file mode 100644 index 04853e7..0000000 --- a/CS/NonPersistentObjectsDemo.Web/WebApplication.cs +++ /dev/null @@ -1,175 +0,0 @@ -using System; -using DevExpress.ExpressApp; -using System.ComponentModel; -using DevExpress.ExpressApp.Web; -using System.Collections.Generic; -using DevExpress.ExpressApp.Xpo; -using DevExpress.ExpressApp.Security; -using DevExpress.ExpressApp.Security.ClientServer; - -namespace NonPersistentObjectsDemo.Web { - // For more typical usage scenarios, be sure to check out https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.Web.WebApplication - public partial class NonPersistentObjectsDemoAspNetApplication : WebApplication { - private DevExpress.ExpressApp.SystemModule.SystemModule module1; - private DevExpress.ExpressApp.Web.SystemModule.SystemAspNetModule module2; - private NonPersistentObjectsDemo.Module.NonPersistentObjectsDemoModule module3; - private NonPersistentObjectsDemo.Module.Web.NonPersistentObjectsDemoAspNetModule module4; - private DevExpress.ExpressApp.Security.SecurityModule securityModule1; - private DevExpress.ExpressApp.Security.SecurityStrategyComplex securityStrategyComplex1; - private DevExpress.ExpressApp.Security.AuthenticationStandard authenticationStandard1; - private DevExpress.ExpressApp.Objects.BusinessClassLibraryCustomizationModule objectsModule; - private DevExpress.ExpressApp.CloneObject.CloneObjectModule cloneObjectModule; - private DevExpress.ExpressApp.ConditionalAppearance.ConditionalAppearanceModule conditionalAppearanceModule; - private DevExpress.ExpressApp.FileAttachments.Web.FileAttachmentsAspNetModule fileAttachmentsAspNetModule; - private DevExpress.ExpressApp.ReportsV2.ReportsModuleV2 reportsModuleV2; - private DevExpress.ExpressApp.ReportsV2.Web.ReportsAspNetModuleV2 reportsAspNetModuleV2; - private DevExpress.ExpressApp.Scheduler.SchedulerModuleBase schedulerModuleBase; - private DevExpress.ExpressApp.Scheduler.Web.SchedulerAspNetModule schedulerAspNetModule; - private DevExpress.ExpressApp.ScriptRecorder.ScriptRecorderModuleBase scriptRecorderModuleBase; - private DevExpress.ExpressApp.ScriptRecorder.Web.ScriptRecorderAspNetModule scriptRecorderAspNetModule; - private DevExpress.ExpressApp.TreeListEditors.TreeListEditorsModuleBase treeListEditorsModuleBase; - private DevExpress.ExpressApp.TreeListEditors.Web.TreeListEditorsAspNetModule treeListEditorsAspNetModule; - private DevExpress.ExpressApp.Validation.ValidationModule validationModule; - private DevExpress.ExpressApp.Validation.Web.ValidationAspNetModule validationAspNetModule; - - #region Default XAF configuration options (https://www.devexpress.com/kb=T501418) - static NonPersistentObjectsDemoAspNetApplication() { - EnableMultipleBrowserTabsSupport = true; - DevExpress.ExpressApp.Web.Editors.ASPx.ASPxGridListEditor.AllowFilterControlHierarchy = true; - DevExpress.ExpressApp.Web.Editors.ASPx.ASPxGridListEditor.MaxFilterControlHierarchyDepth = 3; - DevExpress.ExpressApp.Web.Editors.ASPx.ASPxCriteriaPropertyEditor.AllowFilterControlHierarchyDefault = true; - DevExpress.ExpressApp.Web.Editors.ASPx.ASPxCriteriaPropertyEditor.MaxHierarchyDepthDefault = 3; - DevExpress.Persistent.Base.PasswordCryptographer.EnableRfc2898 = true; - DevExpress.Persistent.Base.PasswordCryptographer.SupportLegacySha512 = false; - } - private void InitializeDefaults() { - LinkNewObjectToParentImmediately = false; - OptimizedControllersCreation = true; - } - #endregion - public NonPersistentObjectsDemoAspNetApplication() { - InitializeComponent(); - InitializeDefaults(); - } - protected override IViewUrlManager CreateViewUrlManager() { - return new ViewUrlManager(); - } - protected override void CreateDefaultObjectSpaceProvider(CreateCustomObjectSpaceProviderEventArgs args) { - //args.ObjectSpaceProvider = new SecuredObjectSpaceProvider((SecurityStrategyComplex)Security, GetDataStoreProvider(args.ConnectionString, args.Connection), true); - args.ObjectSpaceProvider = new XPObjectSpaceProvider(GetDataStoreProvider(args.ConnectionString, args.Connection), true); - args.ObjectSpaceProviders.Add(new NonPersistentObjectSpaceProvider(TypesInfo, null)); - } - private IXpoDataStoreProvider GetDataStoreProvider(string connectionString, System.Data.IDbConnection connection) { - System.Web.HttpApplicationState application = (System.Web.HttpContext.Current != null) ? System.Web.HttpContext.Current.Application : null; - IXpoDataStoreProvider dataStoreProvider = null; - if(application != null && application["DataStoreProvider"] != null) { - dataStoreProvider = application["DataStoreProvider"] as IXpoDataStoreProvider; - } - else { - dataStoreProvider = XPObjectSpaceProvider.GetDataStoreProvider(connectionString, connection, true); - if(application != null) { - application["DataStoreProvider"] = dataStoreProvider; - } - } - return dataStoreProvider; - } - private void NonPersistentObjectsDemoAspNetApplication_DatabaseVersionMismatch(object sender, DevExpress.ExpressApp.DatabaseVersionMismatchEventArgs e) { -#if EASYTEST - e.Updater.Update(); - e.Handled = true; -#else - if(System.Diagnostics.Debugger.IsAttached) { - e.Updater.Update(); - e.Handled = true; - } - else { - string message = "The application cannot connect to the specified database, " + - "because the database doesn't exist, its version is older " + - "than that of the application or its schema does not match " + - "the ORM data model structure. To avoid this error, use one " + - "of the solutions from the https://www.devexpress.com/kb=T367835 KB Article."; - - if(e.CompatibilityError != null && e.CompatibilityError.Exception != null) { - message += "\r\n\r\nInner exception: " + e.CompatibilityError.Exception.Message; - } - throw new InvalidOperationException(message); - } -#endif - } - private void InitializeComponent() { - this.module1 = new DevExpress.ExpressApp.SystemModule.SystemModule(); - this.module2 = new DevExpress.ExpressApp.Web.SystemModule.SystemAspNetModule(); - this.module3 = new NonPersistentObjectsDemo.Module.NonPersistentObjectsDemoModule(); - this.module4 = new NonPersistentObjectsDemo.Module.Web.NonPersistentObjectsDemoAspNetModule(); - this.securityModule1 = new DevExpress.ExpressApp.Security.SecurityModule(); - this.securityStrategyComplex1 = new DevExpress.ExpressApp.Security.SecurityStrategyComplex(); - this.securityStrategyComplex1.SupportNavigationPermissionsForTypes = false; - this.authenticationStandard1 = new DevExpress.ExpressApp.Security.AuthenticationStandard(); - this.objectsModule = new DevExpress.ExpressApp.Objects.BusinessClassLibraryCustomizationModule(); - this.cloneObjectModule = new DevExpress.ExpressApp.CloneObject.CloneObjectModule(); - this.conditionalAppearanceModule = new DevExpress.ExpressApp.ConditionalAppearance.ConditionalAppearanceModule(); - this.fileAttachmentsAspNetModule = new DevExpress.ExpressApp.FileAttachments.Web.FileAttachmentsAspNetModule(); - this.reportsModuleV2 = new DevExpress.ExpressApp.ReportsV2.ReportsModuleV2(); - this.reportsAspNetModuleV2 = new DevExpress.ExpressApp.ReportsV2.Web.ReportsAspNetModuleV2(); - this.schedulerModuleBase = new DevExpress.ExpressApp.Scheduler.SchedulerModuleBase(); - this.schedulerAspNetModule = new DevExpress.ExpressApp.Scheduler.Web.SchedulerAspNetModule(); - this.scriptRecorderModuleBase = new DevExpress.ExpressApp.ScriptRecorder.ScriptRecorderModuleBase(); - this.scriptRecorderAspNetModule = new DevExpress.ExpressApp.ScriptRecorder.Web.ScriptRecorderAspNetModule(); - this.treeListEditorsModuleBase = new DevExpress.ExpressApp.TreeListEditors.TreeListEditorsModuleBase(); - this.treeListEditorsAspNetModule = new DevExpress.ExpressApp.TreeListEditors.Web.TreeListEditorsAspNetModule(); - this.validationModule = new DevExpress.ExpressApp.Validation.ValidationModule(); - this.validationAspNetModule = new DevExpress.ExpressApp.Validation.Web.ValidationAspNetModule(); - ((System.ComponentModel.ISupportInitialize)(this)).BeginInit(); - // - // securityStrategyComplex1 - // - this.securityStrategyComplex1.Authentication = this.authenticationStandard1; - this.securityStrategyComplex1.RoleType = typeof(DevExpress.Persistent.BaseImpl.PermissionPolicy.PermissionPolicyRole); - this.securityStrategyComplex1.UserType = typeof(DevExpress.Persistent.BaseImpl.PermissionPolicy.PermissionPolicyUser); - // - // securityModule1 - // - this.securityModule1.UserType = typeof(DevExpress.Persistent.BaseImpl.PermissionPolicy.PermissionPolicyUser); - // - // authenticationStandard1 - // - this.authenticationStandard1.LogonParametersType = typeof(DevExpress.ExpressApp.Security.AuthenticationStandardLogonParameters); - // - // reportsModuleV2 - // - this.reportsModuleV2.EnableInplaceReports = true; - this.reportsModuleV2.ReportDataType = typeof(DevExpress.Persistent.BaseImpl.ReportDataV2); - this.reportsModuleV2.ShowAdditionalNavigation = false; - this.reportsAspNetModuleV2.ReportViewerType = DevExpress.ExpressApp.ReportsV2.Web.ReportViewerTypes.HTML5; - this.reportsModuleV2.ReportStoreMode = DevExpress.ExpressApp.ReportsV2.ReportStoreModes.XML; - // - // NonPersistentObjectsDemoAspNetApplication - // - this.ApplicationName = "NonPersistentObjectsDemo"; - this.CheckCompatibilityType = DevExpress.ExpressApp.CheckCompatibilityType.DatabaseSchema; - this.Modules.Add(this.module1); - this.Modules.Add(this.module2); - this.Modules.Add(this.module3); - this.Modules.Add(this.module4); - this.Modules.Add(this.securityModule1); - //this.Security = this.securityStrategyComplex1; - this.Modules.Add(this.objectsModule); - this.Modules.Add(this.cloneObjectModule); - this.Modules.Add(this.conditionalAppearanceModule); - this.Modules.Add(this.fileAttachmentsAspNetModule); - this.Modules.Add(this.reportsModuleV2); - this.Modules.Add(this.reportsAspNetModuleV2); - this.Modules.Add(this.schedulerModuleBase); - this.Modules.Add(this.schedulerAspNetModule); - this.Modules.Add(this.scriptRecorderModuleBase); - this.Modules.Add(this.scriptRecorderAspNetModule); - this.Modules.Add(this.treeListEditorsModuleBase); - this.Modules.Add(this.treeListEditorsAspNetModule); - this.Modules.Add(this.validationModule); - this.Modules.Add(this.validationAspNetModule); - this.DatabaseVersionMismatch += new System.EventHandler(this.NonPersistentObjectsDemoAspNetApplication_DatabaseVersionMismatch); - ((System.ComponentModel.ISupportInitialize)(this)).EndInit(); - - } - } -} diff --git a/CS/NonPersistentObjectsDemo.Win/Model.xafml b/CS/NonPersistentObjectsDemo.Win/Model.xafml deleted file mode 100644 index d745362..0000000 --- a/CS/NonPersistentObjectsDemo.Win/Model.xafml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/CS/NonPersistentObjectsDemo.Win/NonPersistentObjectsDemo.Win.csproj b/CS/NonPersistentObjectsDemo.Win/NonPersistentObjectsDemo.Win.csproj deleted file mode 100644 index 79c64f2..0000000 --- a/CS/NonPersistentObjectsDemo.Win/NonPersistentObjectsDemo.Win.csproj +++ /dev/null @@ -1,337 +0,0 @@ - - - - - Debug - AnyCPU - {13E1ACF3-669C-4405-8260-E70BE603E197} - WinExe - Properties - NonPersistentObjectsDemo.Win - NonPersistentObjectsDemo.Win - v4.5.2 - ExpressApp.ico - 512 - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - true - bin\EasyTest\ - TRACE;DEBUG;EASYTEST - full - AnyCPU - prompt - - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - True - - - False - False - - - False - False - - - False - False - - - False - False - - - False - False - - - False - False - - - False - False - - - False - False - - - System - False - - - False - - - System.Data - False - - - System.Drawing - False - - - System.Windows.Forms - False - - - System.XML - False - - - - - - - - - - - - Always - - - - - - - Component - - - WinApplication.cs - - - Form - - - XafSplashScreen.cs - - - XafSplashScreen.cs - - - - - {72D644CD-C193-4572-B2E3-CA82819A1627} - NonPersistentObjectsDemo.Module.Win - True - - - {57ACDBDB-006E-43D3-9308-97857F2FF75D} - NonPersistentObjectsDemo.Module - True - - - - - \ No newline at end of file diff --git a/CS/NonPersistentObjectsDemo.Win/Program.cs b/CS/NonPersistentObjectsDemo.Win/Program.cs deleted file mode 100644 index cec351a..0000000 --- a/CS/NonPersistentObjectsDemo.Win/Program.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System; -using System.Configuration; -using System.Windows.Forms; - -using DevExpress.ExpressApp; -using DevExpress.ExpressApp.Security; -using DevExpress.ExpressApp.Win; -using DevExpress.Persistent.Base; -using DevExpress.Persistent.BaseImpl; -using DevExpress.XtraEditors; - -namespace NonPersistentObjectsDemo.Win { - static class Program { - /// - /// The main entry point for the application. - /// - [STAThread] - static void Main() { -#if EASYTEST - DevExpress.ExpressApp.Win.EasyTest.EasyTestRemotingRegistration.Register(); -#endif - WindowsFormsSettings.LoadApplicationSettings(); - Application.EnableVisualStyles(); - Application.SetCompatibleTextRenderingDefault(false); - DevExpress.Utils.ToolTipController.DefaultController.ToolTipType = DevExpress.Utils.ToolTipType.SuperTip; - DevExpress.ExpressApp.BaseObjectSpace.ThrowExceptionForNotRegisteredEntityType = true; - EditModelPermission.AlwaysGranted = System.Diagnostics.Debugger.IsAttached; - if(Tracing.GetFileLocationFromSettings() == DevExpress.Persistent.Base.FileLocation.CurrentUserApplicationDataFolder) { - Tracing.LocalUserAppDataPath = Application.LocalUserAppDataPath; - } - Tracing.Initialize(); - NonPersistentObjectsDemoWindowsFormsApplication winApplication = new NonPersistentObjectsDemoWindowsFormsApplication(); - //SecurityStrategy security = (SecurityStrategy)winApplication.Security; - //security.RegisterXPOAdapterProviders(); - if(ConfigurationManager.ConnectionStrings["ConnectionString"] != null) { - winApplication.ConnectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString; - } -#if EASYTEST - if(ConfigurationManager.ConnectionStrings["EasyTestConnectionString"] != null) { - winApplication.ConnectionString = ConfigurationManager.ConnectionStrings["EasyTestConnectionString"].ConnectionString; - } -#endif - winApplication.ConnectionString = DevExpress.ExpressApp.Xpo.InMemoryDataStoreProvider.ConnectionString; -#if DEBUG - if(System.Diagnostics.Debugger.IsAttached && winApplication.CheckCompatibilityType == CheckCompatibilityType.DatabaseSchema) { - winApplication.DatabaseUpdateMode = DatabaseUpdateMode.UpdateDatabaseAlways; - } -#endif - try { - winApplication.Setup(); - winApplication.Start(); - } - catch(Exception e) { - winApplication.StopSplash(); - winApplication.HandleException(e); - } - } - } -} diff --git a/CS/NonPersistentObjectsDemo.Win/Properties/AssemblyInfo.cs b/CS/NonPersistentObjectsDemo.Win/Properties/AssemblyInfo.cs deleted file mode 100644 index 80cdb20..0000000 --- a/CS/NonPersistentObjectsDemo.Win/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("NonPersistentObjectsDemo.Win")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("NonPersistentObjectsDemo.Win")] -[assembly: AssemblyCopyright("Copyright © 2020")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("720e2161-0047-4cfe-a68c-433063a3ae53")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -[assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/CS/NonPersistentObjectsDemo.Win/ReadMe.txt b/CS/NonPersistentObjectsDemo.Win/ReadMe.txt deleted file mode 100644 index fd287a6..0000000 --- a/CS/NonPersistentObjectsDemo.Win/ReadMe.txt +++ /dev/null @@ -1,31 +0,0 @@ -Project Description - -This project implements a WinForms application. The root project folder -contains the WinApplication.cs(vb) file with the class that inherits -WinApplication. This class can be designed with the Application Designer that -allows you to view and customize application components: referenced modules, -security settings, data connection. Additionally, the root folder contains -Application Model difference files (XAFML files) that keep application settings -specific for the current application. Differences files can be designed with -the Model Editor. - - -Relevant Documentation - -Application Solution Components -https://docs.devexpress.com/eXpressAppFramework/112569 - -WinApplication Class -https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.Win.WinApplication - -XafApplication Class -https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.XafApplication - -Application Designer -https://docs.devexpress.com/eXpressAppFramework/112827 - -Application Model -https://docs.devexpress.com/eXpressAppFramework/112579 - -Model Editor -https://docs.devexpress.com/eXpressAppFramework/112582 \ No newline at end of file diff --git a/CS/NonPersistentObjectsDemo.Win/WinApplication.Designer.cs b/CS/NonPersistentObjectsDemo.Win/WinApplication.Designer.cs deleted file mode 100644 index b1da85b..0000000 --- a/CS/NonPersistentObjectsDemo.Win/WinApplication.Designer.cs +++ /dev/null @@ -1,127 +0,0 @@ -namespace NonPersistentObjectsDemo.Win { - partial class NonPersistentObjectsDemoWindowsFormsApplication { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) { - if(disposing && (components != null)) { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Component Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() { - this.module1 = new DevExpress.ExpressApp.SystemModule.SystemModule(); - this.module2 = new DevExpress.ExpressApp.Win.SystemModule.SystemWindowsFormsModule(); - this.module3 = new NonPersistentObjectsDemo.Module.NonPersistentObjectsDemoModule(); - this.module4 = new NonPersistentObjectsDemo.Module.Win.NonPersistentObjectsDemoWindowsFormsModule(); - this.securityModule1 = new DevExpress.ExpressApp.Security.SecurityModule(); - this.securityStrategyComplex1 = new DevExpress.ExpressApp.Security.SecurityStrategyComplex(); - this.securityStrategyComplex1.SupportNavigationPermissionsForTypes = false; - this.objectsModule = new DevExpress.ExpressApp.Objects.BusinessClassLibraryCustomizationModule(); - this.cloneObjectModule = new DevExpress.ExpressApp.CloneObject.CloneObjectModule(); - this.conditionalAppearanceModule = new DevExpress.ExpressApp.ConditionalAppearance.ConditionalAppearanceModule(); - this.fileAttachmentsWindowsFormsModule = new DevExpress.ExpressApp.FileAttachments.Win.FileAttachmentsWindowsFormsModule(); - this.reportsModuleV2 = new DevExpress.ExpressApp.ReportsV2.ReportsModuleV2(); - this.reportsWindowsFormsModuleV2 = new DevExpress.ExpressApp.ReportsV2.Win.ReportsWindowsFormsModuleV2(); - this.schedulerModuleBase = new DevExpress.ExpressApp.Scheduler.SchedulerModuleBase(); - this.schedulerWindowsFormsModule = new DevExpress.ExpressApp.Scheduler.Win.SchedulerWindowsFormsModule(); - this.scriptRecorderModuleBase = new DevExpress.ExpressApp.ScriptRecorder.ScriptRecorderModuleBase(); - this.scriptRecorderWindowsFormsModule = new DevExpress.ExpressApp.ScriptRecorder.Win.ScriptRecorderWindowsFormsModule(); - this.treeListEditorsModuleBase = new DevExpress.ExpressApp.TreeListEditors.TreeListEditorsModuleBase(); - this.treeListEditorsWindowsFormsModule = new DevExpress.ExpressApp.TreeListEditors.Win.TreeListEditorsWindowsFormsModule(); - this.validationModule = new DevExpress.ExpressApp.Validation.ValidationModule(); - this.validationWindowsFormsModule = new DevExpress.ExpressApp.Validation.Win.ValidationWindowsFormsModule(); - this.authenticationStandard1 = new DevExpress.ExpressApp.Security.AuthenticationStandard(); - ((System.ComponentModel.ISupportInitialize)(this)).BeginInit(); - // - // securityStrategyComplex1 - // - this.securityStrategyComplex1.Authentication = this.authenticationStandard1; - this.securityStrategyComplex1.RoleType = typeof(DevExpress.Persistent.BaseImpl.PermissionPolicy.PermissionPolicyRole); - this.securityStrategyComplex1.UserType = typeof(DevExpress.Persistent.BaseImpl.PermissionPolicy.PermissionPolicyUser); - // - // securityModule1 - // - this.securityModule1.UserType = typeof(DevExpress.Persistent.BaseImpl.PermissionPolicy.PermissionPolicyUser); - // - // authenticationStandard1 - // - this.authenticationStandard1.LogonParametersType = typeof(DevExpress.ExpressApp.Security.AuthenticationStandardLogonParameters); - // - // reportsModuleV2 - // - this.reportsModuleV2.EnableInplaceReports = true; - this.reportsModuleV2.ReportDataType = typeof(DevExpress.Persistent.BaseImpl.ReportDataV2); - this.reportsModuleV2.ShowAdditionalNavigation = false; - this.reportsModuleV2.ReportStoreMode = DevExpress.ExpressApp.ReportsV2.ReportStoreModes.XML; - // - // NonPersistentObjectsDemoWindowsFormsApplication - // - this.ApplicationName = "NonPersistentObjectsDemo"; - this.CheckCompatibilityType = DevExpress.ExpressApp.CheckCompatibilityType.DatabaseSchema; - this.Modules.Add(this.module1); - this.Modules.Add(this.module2); - this.Modules.Add(this.module3); - this.Modules.Add(this.module4); - this.Modules.Add(this.securityModule1); - //this.Security = this.securityStrategyComplex1; - this.Modules.Add(this.objectsModule); - this.Modules.Add(this.cloneObjectModule); - this.Modules.Add(this.conditionalAppearanceModule); - this.Modules.Add(this.fileAttachmentsWindowsFormsModule); - this.Modules.Add(this.reportsModuleV2); - this.Modules.Add(this.reportsWindowsFormsModuleV2); - this.Modules.Add(this.schedulerModuleBase); - this.Modules.Add(this.schedulerWindowsFormsModule); - this.Modules.Add(this.scriptRecorderModuleBase); - this.Modules.Add(this.scriptRecorderWindowsFormsModule); - this.Modules.Add(this.treeListEditorsModuleBase); - this.Modules.Add(this.treeListEditorsWindowsFormsModule); - this.Modules.Add(this.validationModule); - this.Modules.Add(this.validationWindowsFormsModule); - this.UseOldTemplates = false; - this.DatabaseVersionMismatch += new System.EventHandler(this.NonPersistentObjectsDemoWindowsFormsApplication_DatabaseVersionMismatch); - this.CustomizeLanguagesList += new System.EventHandler(this.NonPersistentObjectsDemoWindowsFormsApplication_CustomizeLanguagesList); - - ((System.ComponentModel.ISupportInitialize)(this)).EndInit(); - - } - - #endregion - - private DevExpress.ExpressApp.SystemModule.SystemModule module1; - private DevExpress.ExpressApp.Win.SystemModule.SystemWindowsFormsModule module2; - private NonPersistentObjectsDemo.Module.NonPersistentObjectsDemoModule module3; - private NonPersistentObjectsDemo.Module.Win.NonPersistentObjectsDemoWindowsFormsModule module4; - private DevExpress.ExpressApp.Security.SecurityModule securityModule1; - private DevExpress.ExpressApp.Security.SecurityStrategyComplex securityStrategyComplex1; - private DevExpress.ExpressApp.Security.AuthenticationStandard authenticationStandard1; - private DevExpress.ExpressApp.Objects.BusinessClassLibraryCustomizationModule objectsModule; - private DevExpress.ExpressApp.CloneObject.CloneObjectModule cloneObjectModule; - private DevExpress.ExpressApp.ConditionalAppearance.ConditionalAppearanceModule conditionalAppearanceModule; - private DevExpress.ExpressApp.FileAttachments.Win.FileAttachmentsWindowsFormsModule fileAttachmentsWindowsFormsModule; - private DevExpress.ExpressApp.ReportsV2.ReportsModuleV2 reportsModuleV2; - private DevExpress.ExpressApp.ReportsV2.Win.ReportsWindowsFormsModuleV2 reportsWindowsFormsModuleV2; - private DevExpress.ExpressApp.Scheduler.SchedulerModuleBase schedulerModuleBase; - private DevExpress.ExpressApp.Scheduler.Win.SchedulerWindowsFormsModule schedulerWindowsFormsModule; - private DevExpress.ExpressApp.ScriptRecorder.ScriptRecorderModuleBase scriptRecorderModuleBase; - private DevExpress.ExpressApp.ScriptRecorder.Win.ScriptRecorderWindowsFormsModule scriptRecorderWindowsFormsModule; - private DevExpress.ExpressApp.TreeListEditors.TreeListEditorsModuleBase treeListEditorsModuleBase; - private DevExpress.ExpressApp.TreeListEditors.Win.TreeListEditorsWindowsFormsModule treeListEditorsWindowsFormsModule; - private DevExpress.ExpressApp.Validation.ValidationModule validationModule; - private DevExpress.ExpressApp.Validation.Win.ValidationWindowsFormsModule validationWindowsFormsModule; - } -} diff --git a/CS/NonPersistentObjectsDemo.Win/WinApplication.cs b/CS/NonPersistentObjectsDemo.Win/WinApplication.cs deleted file mode 100644 index 139bce5..0000000 --- a/CS/NonPersistentObjectsDemo.Win/WinApplication.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System; -using System.ComponentModel; -using DevExpress.ExpressApp; -using DevExpress.ExpressApp.Win; -using System.Collections.Generic; -using DevExpress.ExpressApp.Updating; -using DevExpress.ExpressApp.Win.Utils; -using DevExpress.ExpressApp.Xpo; -using DevExpress.ExpressApp.Security; -using DevExpress.ExpressApp.Security.ClientServer; - -namespace NonPersistentObjectsDemo.Win { - // For more typical usage scenarios, be sure to check out https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.Win.WinApplication._members - public partial class NonPersistentObjectsDemoWindowsFormsApplication : WinApplication { - #region Default XAF configuration options (https://www.devexpress.com/kb=T501418) - static NonPersistentObjectsDemoWindowsFormsApplication() { - DevExpress.Persistent.Base.PasswordCryptographer.EnableRfc2898 = true; - DevExpress.Persistent.Base.PasswordCryptographer.SupportLegacySha512 = false; - DevExpress.ExpressApp.Utils.ImageLoader.Instance.UseSvgImages = true; - } - private void InitializeDefaults() { - LinkNewObjectToParentImmediately = false; - OptimizedControllersCreation = true; - UseLightStyle = true; - SplashScreen = new DXSplashScreen(typeof(XafSplashScreen), new DefaultOverlayFormOptions()); - ExecuteStartupLogicBeforeClosingLogonWindow = true; - } - #endregion - public NonPersistentObjectsDemoWindowsFormsApplication() { - InitializeComponent(); - InitializeDefaults(); - } - protected override void CreateDefaultObjectSpaceProvider(CreateCustomObjectSpaceProviderEventArgs args) { - //args.ObjectSpaceProviders.Add(new SecuredObjectSpaceProvider((SecurityStrategyComplex)Security, XPObjectSpaceProvider.GetDataStoreProvider(args.ConnectionString, args.Connection, true), false)); - args.ObjectSpaceProviders.Add(new XPObjectSpaceProvider(XPObjectSpaceProvider.GetDataStoreProvider(args.ConnectionString, args.Connection, true), false)); - args.ObjectSpaceProviders.Add(new NonPersistentObjectSpaceProvider(TypesInfo, null)); - } - private void NonPersistentObjectsDemoWindowsFormsApplication_CustomizeLanguagesList(object sender, CustomizeLanguagesListEventArgs e) { - string userLanguageName = System.Threading.Thread.CurrentThread.CurrentUICulture.Name; - if(userLanguageName != "en-US" && e.Languages.IndexOf(userLanguageName) == -1) { - e.Languages.Add(userLanguageName); - } - } - private void NonPersistentObjectsDemoWindowsFormsApplication_DatabaseVersionMismatch(object sender, DevExpress.ExpressApp.DatabaseVersionMismatchEventArgs e) { -#if EASYTEST - e.Updater.Update(); - e.Handled = true; -#else - if(System.Diagnostics.Debugger.IsAttached) { - e.Updater.Update(); - e.Handled = true; - } - else { - string message = "The application cannot connect to the specified database, " + - "because the database doesn't exist, its version is older " + - "than that of the application or its schema does not match " + - "the ORM data model structure. To avoid this error, use one " + - "of the solutions from the https://www.devexpress.com/kb=T367835 KB Article."; - - if(e.CompatibilityError != null && e.CompatibilityError.Exception != null) { - message += "\r\n\r\nInner exception: " + e.CompatibilityError.Exception.Message; - } - throw new InvalidOperationException(message); - } -#endif - } - } -} diff --git a/CS/NonPersistentObjectsFilteringDemo.sln b/CS/NonPersistentObjectsFilteringDemo.sln deleted file mode 100644 index b6f8e99..0000000 --- a/CS/NonPersistentObjectsFilteringDemo.sln +++ /dev/null @@ -1,60 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.28307.1000 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NonPersistentObjectsDemo.Module", "NonPersistentObjectsDemo.Module\NonPersistentObjectsDemo.Module.csproj", "{57ACDBDB-006E-43D3-9308-97857F2FF75D}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NonPersistentObjectsDemo.Module.Web", "NonPersistentObjectsDemo.Module.Web\NonPersistentObjectsDemo.Module.Web.csproj", "{EFD113F7-1ED0-472C-8EBE-B1A7CAFB6C2B}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NonPersistentObjectsDemo.Web", "NonPersistentObjectsDemo.Web\NonPersistentObjectsDemo.Web.csproj", "{8C3026D1-113C-4B88-9F91-236753790C60}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NonPersistentObjectsDemo.Module.Win", "NonPersistentObjectsDemo.Module.Win\NonPersistentObjectsDemo.Module.Win.csproj", "{72D644CD-C193-4572-B2E3-CA82819A1627}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NonPersistentObjectsDemo.Win", "NonPersistentObjectsDemo.Win\NonPersistentObjectsDemo.Win.csproj", "{13E1ACF3-669C-4405-8260-E70BE603E197}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - EasyTest|Any CPU = EasyTest|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {57ACDBDB-006E-43D3-9308-97857F2FF75D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {57ACDBDB-006E-43D3-9308-97857F2FF75D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {57ACDBDB-006E-43D3-9308-97857F2FF75D}.EasyTest|Any CPU.ActiveCfg = EasyTest|Any CPU - {57ACDBDB-006E-43D3-9308-97857F2FF75D}.EasyTest|Any CPU.Build.0 = EasyTest|Any CPU - {57ACDBDB-006E-43D3-9308-97857F2FF75D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {57ACDBDB-006E-43D3-9308-97857F2FF75D}.Release|Any CPU.Build.0 = Release|Any CPU - {EFD113F7-1ED0-472C-8EBE-B1A7CAFB6C2B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EFD113F7-1ED0-472C-8EBE-B1A7CAFB6C2B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EFD113F7-1ED0-472C-8EBE-B1A7CAFB6C2B}.EasyTest|Any CPU.ActiveCfg = EasyTest|Any CPU - {EFD113F7-1ED0-472C-8EBE-B1A7CAFB6C2B}.EasyTest|Any CPU.Build.0 = EasyTest|Any CPU - {EFD113F7-1ED0-472C-8EBE-B1A7CAFB6C2B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EFD113F7-1ED0-472C-8EBE-B1A7CAFB6C2B}.Release|Any CPU.Build.0 = Release|Any CPU - {8C3026D1-113C-4B88-9F91-236753790C60}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8C3026D1-113C-4B88-9F91-236753790C60}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8C3026D1-113C-4B88-9F91-236753790C60}.EasyTest|Any CPU.ActiveCfg = EasyTest|Any CPU - {8C3026D1-113C-4B88-9F91-236753790C60}.EasyTest|Any CPU.Build.0 = EasyTest|Any CPU - {8C3026D1-113C-4B88-9F91-236753790C60}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8C3026D1-113C-4B88-9F91-236753790C60}.Release|Any CPU.Build.0 = Release|Any CPU - {72D644CD-C193-4572-B2E3-CA82819A1627}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {72D644CD-C193-4572-B2E3-CA82819A1627}.Debug|Any CPU.Build.0 = Debug|Any CPU - {72D644CD-C193-4572-B2E3-CA82819A1627}.EasyTest|Any CPU.ActiveCfg = EasyTest|Any CPU - {72D644CD-C193-4572-B2E3-CA82819A1627}.EasyTest|Any CPU.Build.0 = EasyTest|Any CPU - {72D644CD-C193-4572-B2E3-CA82819A1627}.Release|Any CPU.ActiveCfg = Release|Any CPU - {72D644CD-C193-4572-B2E3-CA82819A1627}.Release|Any CPU.Build.0 = Release|Any CPU - {13E1ACF3-669C-4405-8260-E70BE603E197}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {13E1ACF3-669C-4405-8260-E70BE603E197}.Debug|Any CPU.Build.0 = Debug|Any CPU - {13E1ACF3-669C-4405-8260-E70BE603E197}.EasyTest|Any CPU.ActiveCfg = EasyTest|Any CPU - {13E1ACF3-669C-4405-8260-E70BE603E197}.EasyTest|Any CPU.Build.0 = EasyTest|Any CPU - {13E1ACF3-669C-4405-8260-E70BE603E197}.Release|Any CPU.ActiveCfg = Release|Any CPU - {13E1ACF3-669C-4405-8260-E70BE603E197}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {BCF45AD8-3F2F-4887-832F-CBD5AE72BD68} - EndGlobalSection -EndGlobal diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/App.razor b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/App.razor new file mode 100644 index 0000000..3b8af49 --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/App.razor @@ -0,0 +1,11 @@ + + + + + + + Not found +

Sorry, there's nothing at this address.

+
+
+
diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/BlazorApplication.cs b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/BlazorApplication.cs new file mode 100644 index 0000000..a9d47b8 --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/BlazorApplication.cs @@ -0,0 +1,47 @@ +using DevExpress.ExpressApp; +using DevExpress.ExpressApp.ApplicationBuilder; +using DevExpress.ExpressApp.Blazor; +using DevExpress.ExpressApp.SystemModule; +using DevExpress.ExpressApp.Xpo; +using NonPersistentFiltering.Blazor.Server.Services; + +namespace NonPersistentFiltering.Blazor.Server; + +public class NonPersistentFilteringBlazorApplication : BlazorApplication { + public NonPersistentFilteringBlazorApplication() { + ApplicationName = "NonPersistentFiltering"; + CheckCompatibilityType = DevExpress.ExpressApp.CheckCompatibilityType.DatabaseSchema; + DatabaseVersionMismatch += NonPersistentFilteringBlazorApplication_DatabaseVersionMismatch; + } + protected override void OnSetupStarted() { + base.OnSetupStarted(); +#if DEBUG + if(System.Diagnostics.Debugger.IsAttached && CheckCompatibilityType == CheckCompatibilityType.DatabaseSchema) { + DatabaseUpdateMode = DatabaseUpdateMode.UpdateDatabaseAlways; + } +#endif + } + private void NonPersistentFilteringBlazorApplication_DatabaseVersionMismatch(object sender, DatabaseVersionMismatchEventArgs e) { +#if EASYTEST + e.Updater.Update(); + e.Handled = true; +#else + if(System.Diagnostics.Debugger.IsAttached) { + e.Updater.Update(); + e.Handled = true; + } + else { + string message = "The application cannot connect to the specified database, " + + "because the database doesn't exist, its version is older " + + "than that of the application or its schema does not match " + + "the ORM data model structure. To avoid this error, use one " + + "of the solutions from the https://www.devexpress.com/kb=T367835 KB Article."; + + if(e.CompatibilityError != null && e.CompatibilityError.Exception != null) { + message += "\r\n\r\nInner exception: " + e.CompatibilityError.Exception.Message; + } + throw new InvalidOperationException(message); + } +#endif + } +} diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/BlazorModule.cs b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/BlazorModule.cs new file mode 100644 index 0000000..e14c3e6 --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/BlazorModule.cs @@ -0,0 +1,26 @@ +using System.ComponentModel; +using DevExpress.ExpressApp; +using DevExpress.ExpressApp.DC; +using DevExpress.ExpressApp.Model; +using DevExpress.ExpressApp.Editors; +using DevExpress.ExpressApp.Actions; +using DevExpress.ExpressApp.Updating; +using DevExpress.ExpressApp.Model.Core; +using DevExpress.ExpressApp.Model.DomainLogics; +using DevExpress.ExpressApp.Model.NodeGenerators; +using DevExpress.Persistent.BaseImpl; + +namespace NonPersistentFiltering.Blazor.Server; + +[ToolboxItemFilter("Xaf.Platform.Blazor")] +// For more typical usage scenarios, be sure to check out https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.ModuleBase. +public sealed class NonPersistentFilteringBlazorModule : ModuleBase { + public NonPersistentFilteringBlazorModule() { + } + public override IEnumerable GetModuleUpdaters(IObjectSpace objectSpace, Version versionFromDB) { + return ModuleUpdater.EmptyModuleUpdaters; + } + public override void Setup(XafApplication application) { + base.Setup(application); + } +} diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/Controllers/ReadMe.txt b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/Controllers/ReadMe.txt new file mode 100644 index 0000000..42f3017 --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/Controllers/ReadMe.txt @@ -0,0 +1,25 @@ +Folder Description + +The "Controllers" project folder is intended for storing Blazor-specific Controller classes +that can change the default XAF application flow and add new features. + + +Relevant Documentation + +Controllers and Actions +https://docs.devexpress.com/eXpressAppFramework/112623 + +Implement Custom Controllers +https://docs.devexpress.com/eXpressAppFramework/112621 + +Define the Scope of Controllers and Actions +https://docs.devexpress.com/eXpressAppFramework/113103 + +Ways to Show a View +https://docs.devexpress.com/eXpressAppFramework/112803 + +Ways to Implement Business Logic +https://docs.devexpress.com/eXpressAppFramework/113710 + +Debugging, Unit and Functional Testing +https://docs.devexpress.com/eXpressAppFramework/112572 diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/Editors/ReadMe.txt b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/Editors/ReadMe.txt new file mode 100644 index 0000000..827fd95 --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/Editors/ReadMe.txt @@ -0,0 +1,25 @@ +Folder Description + +This project folder is intended for storing custom Blazor List Editors, +Property Editors and View Items. + + +Relevant Documentation + +Using a Custom Control that is not Integrated by Default +https://docs.devexpress.com/eXpressAppFramework/113610 + +Ways to Access UI Elements and Their Controls +https://docs.devexpress.com/eXpressAppFramework/120092 + +Views +https://docs.devexpress.com/eXpressAppFramework/112611 + +List Editors +https://docs.devexpress.com/eXpressAppFramework/113189 + +View Items +https://docs.devexpress.com/eXpressAppFramework/112612 + +Debugging, Unit and Functional Testing +https://docs.devexpress.com/eXpressAppFramework/112572 diff --git a/CS/NonPersistentObjectsDemo.Web/Images/ReadMe.txt b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/Images/ReadMe.txt similarity index 100% rename from CS/NonPersistentObjectsDemo.Web/Images/ReadMe.txt rename to CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/Images/ReadMe.txt diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/Model.xafml b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/Model.xafml new file mode 100644 index 0000000..2877e3b --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/Model.xafml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/NonPersistentFiltering.Blazor.Server.csproj b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/NonPersistentFiltering.Blazor.Server.csproj new file mode 100644 index 0000000..9bf7dd6 --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/NonPersistentFiltering.Blazor.Server.csproj @@ -0,0 +1,26 @@ + + + net6.0 + false + false + 1.0.* + 1.0.0.0 + Debug;Release;EasyTest + enable + + + + + + + Always + + + + + + + + + + diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/Pages/_Host.cshtml b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/Pages/_Host.cshtml new file mode 100644 index 0000000..f3994ab --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/Pages/_Host.cshtml @@ -0,0 +1,55 @@ +@page "/" +@namespace NonPersistentFiltering.Blazor.Server +@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers +@using DevExpress.ExpressApp.Blazor.Components + + + + + + + + + + NonPersistentFiltering + + + + + @{ + string userAgent = Request.Headers["User-Agent"]; + bool isIE = userAgent.Contains("MSIE") || userAgent.Contains("Trident"); + } + @if(isIE) { + +
+
+ +
+
Internet Explorer is not supported.
+

NonPersistentFiltering cannot be loaded in Internet Explorer.
Please use a different browser.

+
+
+
+ } + else { + + + + + + + + + + + + +
+ +
+ + + } + + diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/Program.cs b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/Program.cs new file mode 100644 index 0000000..253f3b7 --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/Program.cs @@ -0,0 +1,50 @@ +using System.Reflection; +using DevExpress.ExpressApp; +using DevExpress.ExpressApp.Blazor.DesignTime; +using DevExpress.ExpressApp.Blazor.Services; +using DevExpress.ExpressApp.Design; +using DevExpress.ExpressApp.Utils; + +namespace NonPersistentFiltering.Blazor.Server; + +public class Program : IDesignTimeApplicationFactory { + private static bool ContainsArgument(string[] args, string argument) { + return args.Any(arg => arg.TrimStart('/').TrimStart('-').ToLower() == argument.ToLower()); + } + public static int Main(string[] args) { + if(ContainsArgument(args, "help") || ContainsArgument(args, "h")) { + Console.WriteLine("Updates the database when its version does not match the application's version."); + Console.WriteLine(); + Console.WriteLine($" {Assembly.GetExecutingAssembly().GetName().Name}.exe --updateDatabase [--forceUpdate --silent]"); + Console.WriteLine(); + Console.WriteLine("--forceUpdate - Marks that the database must be updated whether its version matches the application's version or not."); + Console.WriteLine("--silent - Marks that database update proceeds automatically and does not require any interaction with the user."); + Console.WriteLine(); + Console.WriteLine($"Exit codes: 0 - {DBUpdaterStatus.UpdateCompleted}"); + Console.WriteLine($" 1 - {DBUpdaterStatus.UpdateError}"); + Console.WriteLine($" 2 - {DBUpdaterStatus.UpdateNotNeeded}"); + } + else { + DevExpress.ExpressApp.FrameworkSettings.DefaultSettingsCompatibilityMode = DevExpress.ExpressApp.FrameworkSettingsCompatibilityMode.Latest; + IHost host = CreateHostBuilder(args).Build(); + if(ContainsArgument(args, "updateDatabase")) { + using(var serviceScope = host.Services.CreateScope()) { + return serviceScope.ServiceProvider.GetRequiredService().Update(ContainsArgument(args, "forceUpdate"), ContainsArgument(args, "silent")); + } + } + else { + host.Run(); + } + } + return 0; + } + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => { + webBuilder.UseStartup(); + }); + XafApplication IDesignTimeApplicationFactory.Create() { + IHostBuilder hostBuilder = CreateHostBuilder(Array.Empty()); + return DesignTimeApplicationFactoryHelper.Create(hostBuilder); + } +} diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/Properties/launchSettings.json b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/Properties/launchSettings.json new file mode 100644 index 0000000..87a1107 --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:65201", + "sslPort": 44318 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "NonPersistentFiltering.Blazor.Server": { + "commandName": "Project", + "launchBrowser": true, + "applicationUrl": "https://localhost:5001;http://localhost:5000", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} \ No newline at end of file diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/ReadMe.txt b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/ReadMe.txt new file mode 100644 index 0000000..a229505 --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/ReadMe.txt @@ -0,0 +1,40 @@ +Project Description + +This project implements an ASP.NET Core Blazor Server application (https://docs.microsoft.com/en-us/aspnet/core/blazor/). +The root project folder contains the BlazorApplication.cs file with the class that inherits +BlazorApplication. This class allows you to view and customize application components: referenced modules, +security settings, data connection. Additionally, the root folder contains +Application Model difference files (XAFML files) that keep settings +specific to the current application. Difference files can be customized in code +or in the Model Editor. +The appsettings.json file contains database connection, logging, and theme settings (https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration). + + +Relevant Documentation + +Application Solution Components +https://docs.devexpress.com/eXpressAppFramework/112569 + +Debugging, Testing and Error Handling +https://docs.devexpress.com/eXpressAppFramework/112572 + +XafApplication Class +https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.XafApplication + +Application Model (UI Settings Storage) +https://docs.devexpress.com/eXpressAppFramework/112579 + +Model Editor +https://docs.devexpress.com/eXpressAppFramework/112582 + +ASP.NET Core Blazor UI +https://docs.devexpress.com/eXpressAppFramework/401675/overview/supported-ui-platforms#aspnet-core-blazor-ui + +Frequently Asked Questions - Blazor UI (FAQ) +https://docs.devexpress.com/eXpressAppFramework/403277/support-qa-troubleshooting/frequently-asked-questions-blazor-faq + +Backend WebApi Service +https://docs.devexpress.com/eXpressAppFramework/403394/backend-web-api-service + +XAF Community Extensions +https://www.devexpress.com/products/net/application_framework/#extensions \ No newline at end of file diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/Services/CircuitHandlerProxy.cs b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/Services/CircuitHandlerProxy.cs new file mode 100644 index 0000000..0440c50 --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/Services/CircuitHandlerProxy.cs @@ -0,0 +1,23 @@ +using DevExpress.ExpressApp.Blazor.Services; +using Microsoft.AspNetCore.Components.Server.Circuits; + +namespace NonPersistentFiltering.Blazor.Server.Services; + +internal class CircuitHandlerProxy : CircuitHandler { + private readonly IScopedCircuitHandler scopedCircuitHandler; + public CircuitHandlerProxy(IScopedCircuitHandler scopedCircuitHandler) { + this.scopedCircuitHandler = scopedCircuitHandler; + } + public override Task OnCircuitOpenedAsync(Circuit circuit, CancellationToken cancellationToken) { + return scopedCircuitHandler.OnCircuitOpenedAsync(cancellationToken); + } + public override Task OnConnectionUpAsync(Circuit circuit, CancellationToken cancellationToken) { + return scopedCircuitHandler.OnConnectionUpAsync(cancellationToken); + } + public override Task OnCircuitClosedAsync(Circuit circuit, CancellationToken cancellationToken) { + return scopedCircuitHandler.OnCircuitClosedAsync(cancellationToken); + } + public override Task OnConnectionDownAsync(Circuit circuit, CancellationToken cancellationToken) { + return scopedCircuitHandler.OnConnectionDownAsync(cancellationToken); + } +} diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/Services/ProxyHubConnectionHandler.cs b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/Services/ProxyHubConnectionHandler.cs new file mode 100644 index 0000000..708f209 --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/Services/ProxyHubConnectionHandler.cs @@ -0,0 +1,27 @@ +using DevExpress.ExpressApp.Blazor.Services; +using Microsoft.AspNetCore.Connections; +using Microsoft.AspNetCore.SignalR; +using Microsoft.Extensions.Options; + +namespace NonPersistentFiltering.Blazor.Server.Services; + +internal class ProxyHubConnectionHandler : HubConnectionHandler where THub : Hub { + private readonly IValueManagerStorageContainerInitializer storageContainerInitializer; + public ProxyHubConnectionHandler( + HubLifetimeManager lifetimeManager, + IHubProtocolResolver protocolResolver, + IOptions globalHubOptions, + IOptions> hubOptions, + ILoggerFactory loggerFactory, + IUserIdProvider userIdProvider, + IServiceScopeFactory serviceScopeFactory, + IValueManagerStorageContainerInitializer storageContainerAccessor) + : base(lifetimeManager, protocolResolver, globalHubOptions, hubOptions, loggerFactory, userIdProvider, serviceScopeFactory) { + this.storageContainerInitializer = storageContainerAccessor; + } + + public override Task OnConnectedAsync(ConnectionContext connection) { + storageContainerInitializer.Initialize(); + return base.OnConnectedAsync(connection); + } +} diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/Startup.cs b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/Startup.cs new file mode 100644 index 0000000..e7d48b6 --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/Startup.cs @@ -0,0 +1,76 @@ +using DevExpress.ExpressApp.ApplicationBuilder; +using DevExpress.ExpressApp.Blazor.ApplicationBuilder; +using DevExpress.ExpressApp.Blazor.Services; +using DevExpress.Persistent.Base; +using Microsoft.AspNetCore.Authentication.Cookies; +using Microsoft.AspNetCore.Components.Server.Circuits; +using DevExpress.ExpressApp.Xpo; +using NonPersistentFiltering.Blazor.Server.Services; +using DevExpress.ExpressApp.Core; + +namespace NonPersistentFiltering.Blazor.Server; + +public class Startup { + public Startup(IConfiguration configuration) { + Configuration = configuration; + } + + public IConfiguration Configuration { get; } + + // This method gets called by the runtime. Use this method to add services to the container. + // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 + public void ConfigureServices(IServiceCollection services) { + services.AddSingleton(typeof(Microsoft.AspNetCore.SignalR.HubConnectionHandler<>), typeof(ProxyHubConnectionHandler<>)); + + services.AddRazorPages(); + services.AddServerSideBlazor(); + services.AddHttpContextAccessor(); + services.AddScoped(); + services.AddXaf(Configuration, builder => { + builder.UseApplication(); + builder.Modules + .Add() + .Add(); + builder.ObjectSpaceProviders + .AddXpo((serviceProvider, options) => { + string connectionString = null; + if(Configuration.GetConnectionString("ConnectionString") != null) { + connectionString = Configuration.GetConnectionString("ConnectionString"); + } +#if EASYTEST + if(Configuration.GetConnectionString("EasyTestConnectionString") != null) { + connectionString = Configuration.GetConnectionString("EasyTestConnectionString"); + } +#endif + ArgumentNullException.ThrowIfNull(connectionString); + options.ConnectionString = connectionString; + options.ThreadSafe = true; + options.UseSharedDataStoreProvider = true; + }) + .AddNonPersistent(); + }); + } + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { + if(env.IsDevelopment()) { + app.UseDeveloperExceptionPage(); + } + else { + app.UseExceptionHandler("/Error"); + // The default HSTS value is 30 days. To change this for production scenarios, see: https://aka.ms/aspnetcore-hsts. + app.UseHsts(); + } + app.UseHttpsRedirection(); + app.UseRequestLocalization(); + app.UseStaticFiles(); + app.UseRouting(); + app.UseXaf(); + app.UseEndpoints(endpoints => { + endpoints.MapXafEndpoints(); + endpoints.MapBlazorHub(); + endpoints.MapFallbackToPage("/_Host"); + endpoints.MapControllers(); + }); + } +} diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/_Imports.razor b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/_Imports.razor new file mode 100644 index 0000000..3deb47f --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/_Imports.razor @@ -0,0 +1,11 @@ +@using System.Net.Http +@using Microsoft.AspNetCore.Authorization +@using Microsoft.AspNetCore.Components.Authorization +@using Microsoft.AspNetCore.Components.Forms +@using Microsoft.AspNetCore.Components.Routing +@using Microsoft.AspNetCore.Components.Web +@using Microsoft.AspNetCore.Components.Web.Virtualization +@using Microsoft.JSInterop +@using DevExpress.Blazor +@using DevExpress.ExpressApp.Blazor.Components +@using NonPersistentFiltering.Blazor.Server diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/appsettings.Development.json b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/appsettings.Development.json new file mode 100644 index 0000000..437008f --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/appsettings.Development.json @@ -0,0 +1,16 @@ +{ + "DetailedErrors": true, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information", + "DevExpress.ExpressApp": "Information" + } + }, + "DevExpress": { + "ExpressApp": { + "EnableDiagnosticActions": false + } + } +} \ No newline at end of file diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/appsettings.json b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/appsettings.json new file mode 100644 index 0000000..123076e --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/appsettings.json @@ -0,0 +1,52 @@ +{ + "ConnectionStrings": { + "ConnectionString": "Integrated Security=SSPI;Pooling=false;Data Source=(localdb)\\mssqllocaldb;Initial Catalog=NonPersistentFiltering", + "EasyTestConnectionString": "Integrated Security=SSPI;Pooling=false;Data Source=(localdb)\\mssqllocaldb;Initial Catalog=NonPersistentFilteringEasyTest" + }, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information", + "DevExpress.ExpressApp": "Information" + } + }, + "AllowedHosts": "*", + "DevExpress": { + "ExpressApp": { + "Languages": "en-US;", + "ShowLanguageSwitcher": false, + "ThemeSwitcher": { + "DefaultItemName": "Office White", + "ShowSizeModeSwitcher": true, + "Groups": [ + { + "Caption": "DevExpress Themes", + "Items": [ + { + "Caption": "Blazing Berry", + "Url": "_content/DevExpress.Blazor.Themes/blazing-berry.bs5.min.css", + "Color": "#5c2d91" + }, + { + "Caption": "Blazing Dark", + "Url": "_content/DevExpress.Blazor.Themes/blazing-dark.bs5.min.css", + "Color": "#46444a" + }, + { + "Caption": "Office White", + "Url": "_content/DevExpress.Blazor.Themes/office-white.bs5.min.css", + "Color": "#fe7109" + }, + { + "Caption": "Purple", + "Url": "_content/DevExpress.Blazor.Themes/purple.bs5.min.css", + "Color": "#7989ff" + } + ] + } + ] + } + } + } +} \ No newline at end of file diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/wwwroot/css/site.css b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/wwwroot/css/site.css new file mode 100644 index 0000000..2e1c9a0 --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/wwwroot/css/site.css @@ -0,0 +1,31 @@ +html, body { + height: 100%; +} + +app { + display: block; + height: 100%; +} + +.header-logo { + flex-shrink: 0; + background-color: currentColor; + -webkit-mask: url('../images/Logo.svg'); + mask: url('../images/Logo.svg'); + -webkit-mask-position: center; + mask-position: center; + -webkit-mask-repeat: no-repeat; + mask-repeat: no-repeat; + width: 180px; + height: 24px; +} + +#blazor-error-ui { + background: inherit; + bottom: 0; + display: none; + position: fixed; + width: 100%; + height: 100%; + z-index: 100001; +} \ No newline at end of file diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/wwwroot/favicon.ico b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/wwwroot/favicon.ico new file mode 100644 index 0000000..91de870 Binary files /dev/null and b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/wwwroot/favicon.ico differ diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/wwwroot/images/Logo.svg b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/wwwroot/images/Logo.svg new file mode 100644 index 0000000..d0aa175 --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/wwwroot/images/Logo.svg @@ -0,0 +1,43 @@ + + + + + + diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/wwwroot/images/SplashScreen.svg b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/wwwroot/images/SplashScreen.svg new file mode 100644 index 0000000..d68f0e7 --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Blazor.Server/wwwroot/images/SplashScreen.svg @@ -0,0 +1,13 @@ + + + + + + + diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Module/BusinessObjects/Article.cs b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Module/BusinessObjects/Article.cs new file mode 100644 index 0000000..72ad8af --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Module/BusinessObjects/Article.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using DevExpress.ExpressApp; +using DevExpress.ExpressApp.DC; +using DevExpress.Persistent.Base; + +namespace NonPersistentObjectsDemo.Module.BusinessObjects { + + [DefaultClassOptions] + [DefaultProperty(nameof(Article.Title))] + [DevExpress.ExpressApp.ConditionalAppearance.Appearance("", Enabled = false, TargetItems = "*")] + [DevExpress.ExpressApp.DC.DomainComponent] + public class Article : NonPersistentObjectBase { + internal Article() { } + private int _ID; + [Browsable(false)] + [DevExpress.ExpressApp.Data.Key] + public int ID { + get { return _ID; } + set { _ID = value; } + } + private Contact _Author; + public Contact Author { + get { return _Author; } + set { SetPropertyValue(nameof(Author), ref _Author, value); } + } + private string _Title; + public string Title { + get { return _Title; } + set { SetPropertyValue(nameof(Title), ref _Title, value); } + } + private string _Content; + [FieldSize(-1)] + public string Content { + get { return _Content; } + set { SetPropertyValue(nameof(Content), ref _Content, value); } + } + } + + class ArticleAdapter { + private NonPersistentObjectSpace objectSpace; + private static List
articles; + + public ArticleAdapter(NonPersistentObjectSpace npos) { + this.objectSpace = npos; + objectSpace.ObjectsGetting += ObjectSpace_ObjectsGetting; + } + private void ObjectSpace_ObjectsGetting(object sender, ObjectsGettingEventArgs e) { + if(e.ObjectType == typeof(Article)) { + var collection = new DynamicCollection(objectSpace, e.ObjectType, e.Criteria, e.Sorting, e.InTransaction); + collection.FetchObjects += DynamicCollection_FetchObjects; + e.Objects = collection; + } + } + private void DynamicCollection_FetchObjects(object sender, FetchObjectsEventArgs e) { + if(e.ObjectType == typeof(Article)) { + e.Objects = articles; + e.ShapeData = true; + } + } + + static ArticleAdapter() { + articles = new List
(); + CreateDemoData(); + } + + #region DemoData + static void CreateDemoData() { + // var gen = new GenHelper(); + var contacts = ContactAdapter.GetAllContacts(); + + for (int i = 0; i < 70; i++) { + var cntIndex = new Random(i).Next(0, contacts.Count); + articles.Add(new Article() { + ID = i, + Title = "Title" + i, + Content = "Content" + i, + Author = contacts[cntIndex] + }) ; + } + } + #endregion + } +} diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Module/BusinessObjects/Contact.cs b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Module/BusinessObjects/Contact.cs new file mode 100644 index 0000000..87ca349 --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Module/BusinessObjects/Contact.cs @@ -0,0 +1,124 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using DevExpress.Data.Filtering; +using DevExpress.ExpressApp; +using DevExpress.Persistent.Base; +using DevExpress.Xpo; + +namespace NonPersistentObjectsDemo.Module.BusinessObjects { + + [DefaultClassOptions] + [DefaultProperty(nameof(Contact.FullName))] + [DevExpress.ExpressApp.ConditionalAppearance.Appearance("", Enabled = false, TargetItems = "*")] + [DevExpress.ExpressApp.DC.DomainComponent] + public class Contact : NonPersistentObjectBase { + internal Contact() { } + private string _UserName; + [DevExpress.ExpressApp.Data.Key] + public string UserName { + get { return _UserName; } + set { _UserName = value; } + } + private string _FullName; + public string FullName { + get { return _FullName; } + set { SetPropertyValue(nameof(FullName), ref _FullName, value); } + } + private int _Age; + public int Age { + get { return _Age; } + set { SetPropertyValue(nameof(Age), ref _Age, value); } + } + private float _Rating; + public float Rating { + get { return _Rating; } + set { SetPropertyValue(nameof(Rating), ref _Rating, value); } + } + } + + class ContactAdapter { + private NonPersistentObjectSpace objectSpace; + + public ContactAdapter(NonPersistentObjectSpace npos) { + this.objectSpace = npos; + objectSpace.ObjectsGetting += ObjectSpace_ObjectsGetting; + } + private void ObjectSpace_ObjectsGetting(object sender, ObjectsGettingEventArgs e) { + if(e.ObjectType == typeof(Contact)) { + var collection = new DynamicCollection(objectSpace, e.ObjectType, e.Criteria, e.Sorting, e.InTransaction); + collection.FetchObjects += DynamicCollection_FetchObjects; + e.Objects = collection; + } + } + private void DynamicCollection_FetchObjects(object sender, FetchObjectsEventArgs e) { + if(e.ObjectType == typeof(Contact)) { + var rows = contactsStorage.GetContactRows(e.Criteria, e.Sorting); + e.Objects = rows.Select(row => GetContact(row)); + } + } + private static Contact GetContact(DataRow row) { + Contact obj; + var key = row["UserName"] as string; + if(!contactsCache.TryGetValue(key, out obj)) { + obj = new Contact() { + UserName = key, + FullName = (string)row["FullName"], + Age = (int)row["Age"], + Rating = (float)row["Rating"] + }; + contactsCache.Add(key, obj); + } + return obj; + } + + private static ContactStorage contactsStorage; + private static Dictionary contactsCache; + internal static IList GetAllContacts() { + return contactsStorage.GetContactRows(null, null).Select(row => GetContact(row)).ToList(); + } + static ContactAdapter() { + contactsStorage = new ContactStorage(); + contactsStorage.LoadDemoData(); + contactsCache = new Dictionary(); + } + } + + class ContactStorage { + private DataSet dataSet; + public IList GetContactRows(CriteriaOperator criteria, IList sorting) { + var filter = CriteriaToWhereClauseHelper.GetDataSetWhere(criteria); + string sort = null; + if(sorting!= null&& sorting.Count == 1 && sorting[0].Property is OperandProperty) { + sort = string.Format("{0} {1}", sorting[0].PropertyName, sorting[0].Direction == DevExpress.Xpo.DB.SortingDirection.Ascending ? "ASC" : "DESC"); + } + return dataSet.Tables["Contacts"].Select(filter, sort); + } + public ContactStorage() { + dataSet = new DataSet(); + { + var dt = dataSet.Tables.Add("Contacts"); + var colID = dt.Columns.Add("UserName", typeof(string)); + dt.Columns.Add("FullName", typeof(string)); + dt.Columns.Add("Age", typeof(int)); + dt.Columns.Add("Rating", typeof(float)); + dt.PrimaryKey = new DataColumn[] { colID }; + } + LoadDemoData(); + } + public void LoadDemoData() { + var dt = dataSet.Tables["Contacts"]; + for(int i = 0; i < 50; i++) { + var id = i; + var fullName = "FullName"+i; + var age = 16 + i; + var rating = new Random(i).Next(10,90); + dt.LoadDataRow(new object[] { id, fullName, age, rating }, LoadOption.OverwriteChanges); + } + } + } +} diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Module/BusinessObjects/NonPersistentObjectBase.cs b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Module/BusinessObjects/NonPersistentObjectBase.cs new file mode 100644 index 0000000..b712117 --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Module/BusinessObjects/NonPersistentObjectBase.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using DevExpress.ExpressApp; +using DevExpress.ExpressApp.DC; +using DevExpress.Persistent.Base; + +namespace NonPersistentObjectsDemo.Module.BusinessObjects { + + public abstract class BoundNonPersistentObjectBase : NonPersistentObjectBase, IObjectSpaceLink { + private IObjectSpace _ObjectSpace; + protected IObjectSpace ObjectSpace { get { return _ObjectSpace; } } + IObjectSpace IObjectSpaceLink.ObjectSpace { + get { return _ObjectSpace; } + set { + if(_ObjectSpace != value) { + OnObjectSpaceChanging(); + _ObjectSpace = value; + OnObjectSpaceChanged(); + } + } + } + protected virtual void OnObjectSpaceChanging() { } + protected virtual void OnObjectSpaceChanged() { } + protected IObjectSpace FindPersistentObjectSpace(Type type) { + return ((NonPersistentObjectSpace)ObjectSpace).AdditionalObjectSpaces.FirstOrDefault(os => os.IsKnownType(type)); + } + } + + public abstract class NonPersistentObjectBase : INotifyPropertyChanged { + public event PropertyChangedEventHandler PropertyChanged; + protected void OnPropertyChanged(string propertyName) { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + protected void SetPropertyValue(string name, ref T field, T value) { + if(!Equals(field, value)) { + field = value; + OnPropertyChanged(name); + } + } + [Browsable(false)] + public object This { get { return this; } } + } +} diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Module/BusinessObjects/ReadMe.txt b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Module/BusinessObjects/ReadMe.txt new file mode 100644 index 0000000..a958910 --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Module/BusinessObjects/ReadMe.txt @@ -0,0 +1,26 @@ +Folder Description + +The "BusinessObjects" project folder is intended for storing code of your data model. +In XAF, a business object can be implemented as an ORM-based persistent class +or a non-persistent POCO. + + +Relevant Documentation + +Business Model Design +https://docs.devexpress.com/eXpressAppFramework/113461 + +Non-Persistent Objects +https://docs.devexpress.com/eXpressAppFramework/116516 + +Data Types Supported by built-in Editors +https://docs.devexpress.com/eXpressAppFramework/113014 + +Ways to Add a Business Class (XPO) +https://docs.devexpress.com/eXpressAppFramework/112847 + +Ways to Implement Business Logic +https://docs.devexpress.com/eXpressAppFramework/113710 + +Debugging, Unit and Functional Testing +https://docs.devexpress.com/eXpressAppFramework/112572 diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Module/Controllers/FindArticlesController.cs b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Module/Controllers/FindArticlesController.cs new file mode 100644 index 0000000..7d75671 --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Module/Controllers/FindArticlesController.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using DevExpress.Data.Filtering; +using DevExpress.ExpressApp; +using DevExpress.ExpressApp.Actions; +using DevExpress.ExpressApp.ConditionalAppearance; +using DevExpress.ExpressApp.DC; +using DevExpress.Persistent.Base; +using NonPersistentObjectsDemo.Module.BusinessObjects; + +namespace NonPersistentObjectsDemo.Module.Controllers { + + public class FindArticlesController : ViewController { + private PopupWindowShowAction action; + public FindArticlesController() { + action = new PopupWindowShowAction(this, "FindArticles", PredefinedCategory.View); + action.CustomizePopupWindowParams += Action_CustomizePopupWindowParams; + action.Execute += Action_Execute; + } + private void Action_CustomizePopupWindowParams(object sender, CustomizePopupWindowParamsEventArgs e) { + var objectSpace = Application.CreateObjectSpace(typeof(FindArticlesDialog)); + var obj = new FindArticlesDialog(); + var detailView = Application.CreateDetailView(objectSpace, obj); + detailView.ViewEditMode = DevExpress.ExpressApp.Editors.ViewEditMode.Edit; + e.View = detailView; + } + private void Action_Execute(object sender, PopupWindowShowActionExecuteEventArgs e) { + } + } + + [DomainComponent] + public class FindArticlesDialog : BoundNonPersistentObjectBase { + private Contact _Author; + [ImmediatePostData] + public Contact Author { + get { return _Author; } + set { SetPropertyValue(nameof(Author), ref _Author, value); } + } + private float _AuthorMinRating; + [Appearance("", Enabled = false, Criteria = "Author is not null")] + public float AuthorMinRating { + get { return _AuthorMinRating; } + set { SetPropertyValue(nameof(AuthorMinRating), ref _AuthorMinRating, value); } + } + private BindingList
_Articles; + public BindingList
Articles { + get { + if(_Articles == null) { + _Articles = new BindingList
(); + } + return _Articles; + } + } + private void UpdateArticles() { + if(_Articles != null) { + var filter = GetCriteria(); + _Articles.RaiseListChangedEvents = false; + _Articles.Clear(); + foreach(var obj in ObjectSpace.GetObjects
(filter)) { + _Articles.Add(obj); + } + _Articles.RaiseListChangedEvents = true; + _Articles.ResetBindings(); + OnPropertyChanged(nameof(Articles)); + } + } + private CriteriaOperator GetCriteria() { + if(Author != null) { + return new BinaryOperator("Author.UserName", Author.UserName); + } + else { + return CriteriaOperator.Parse("Author.Rating >= ?", AuthorMinRating); + } + } + [Action(PredefinedCategory.PopupActions)] + public void Find() { + UpdateArticles(); + } + } +} diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Module/Controllers/ReadMe.txt b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Module/Controllers/ReadMe.txt new file mode 100644 index 0000000..9389414 --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Module/Controllers/ReadMe.txt @@ -0,0 +1,25 @@ +Folder Description + +The "Controllers" project folder is intended for storing platform-agnostic Controller classes +that can change the default XAF application flow and add new features. + + +Relevant Documentation + +Controllers and Actions +https://docs.devexpress.com/eXpressAppFramework/112623 + +Implement Custom Controllers +https://docs.devexpress.com/eXpressAppFramework/112621 + +Define the Scope of Controllers and Actions +https://docs.devexpress.com/eXpressAppFramework/113103 + +Ways to Show a View +https://docs.devexpress.com/eXpressAppFramework/112803 + +Ways to Implement Business Logic +https://docs.devexpress.com/eXpressAppFramework/113710 + +Debugging, Unit and Functional Testing +https://docs.devexpress.com/eXpressAppFramework/112572 diff --git a/CS/NonPersistentObjectsDemo.Module/DatabaseUpdate/ReadMe.txt b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Module/DatabaseUpdate/ReadMe.txt similarity index 64% rename from CS/NonPersistentObjectsDemo.Module/DatabaseUpdate/ReadMe.txt rename to CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Module/DatabaseUpdate/ReadMe.txt index 31da2b7..436b186 100644 --- a/CS/NonPersistentObjectsDemo.Module/DatabaseUpdate/ReadMe.txt +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Module/DatabaseUpdate/ReadMe.txt @@ -1,17 +1,23 @@ Folder Description -The "DatabaseUpdate" project folder is intended for storing code that supplies -initial data (default User objects, etc) and handles a database update when the +The "DatabaseUpdate" project folder is intended for storing code that supplies +initial data (default User objects, etc) and handles a database update when the application version changes. Relevant Documentation -Supply Initial Data +Supply Initial Data (XPO) https://docs.devexpress.com/eXpressAppFramework/112788 -How to: Update the Database Structure after the Persistent Class or Property Was Renamed or Removed -https://docs.devexpress.com/eXpressAppFramework/113254 - ModuleUpdater Class https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.Updating.ModuleUpdater + +Application Update +https://docs.devexpress.com/eXpressAppFramework/113239 + +How to: Update the Database Structure after the Persistent Class or Property Was Renamed or Removed (XPO) +https://docs.devexpress.com/eXpressAppFramework/113254 + +Debugging, Unit and Functional Testing +https://docs.devexpress.com/eXpressAppFramework/112572 diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Module/DatabaseUpdate/Updater.cs b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Module/DatabaseUpdate/Updater.cs new file mode 100644 index 0000000..895f2ff --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Module/DatabaseUpdate/Updater.cs @@ -0,0 +1,33 @@ +using DevExpress.ExpressApp; +using DevExpress.Data.Filtering; +using DevExpress.Persistent.Base; +using DevExpress.ExpressApp.Updating; +using DevExpress.Xpo; +using DevExpress.ExpressApp.Xpo; +using DevExpress.Persistent.BaseImpl; + +namespace NonPersistentFiltering.Module.DatabaseUpdate; + +// For more typical usage scenarios, be sure to check out https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.Updating.ModuleUpdater +public class Updater : ModuleUpdater { + public Updater(IObjectSpace objectSpace, Version currentDBVersion) : + base(objectSpace, currentDBVersion) { + } + public override void UpdateDatabaseAfterUpdateSchema() { + base.UpdateDatabaseAfterUpdateSchema(); + //string name = "MyName"; + //DomainObject1 theObject = ObjectSpace.FirstOrDefault(u => u.Name == name); + //if(theObject == null) { + // theObject = ObjectSpace.CreateObject(); + // theObject.Name = name; + //} + + //ObjectSpace.CommitChanges(); //Uncomment this line to persist created object(s). + } + public override void UpdateDatabaseBeforeUpdateSchema() { + base.UpdateDatabaseBeforeUpdateSchema(); + //if(CurrentDBVersion < new Version("1.1.0.0") && CurrentDBVersion > new Version("0.0.0.0")) { + // RenameColumn("DomainObject1Table", "OldColumnName", "NewColumnName"); + //} + } +} diff --git a/CS/NonPersistentObjectsDemo.Win/Images/ReadMe.txt b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Module/Images/ReadMe.txt similarity index 100% rename from CS/NonPersistentObjectsDemo.Win/Images/ReadMe.txt rename to CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Module/Images/ReadMe.txt diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Module/Model.DesignedDiffs.xafml b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Module/Model.DesignedDiffs.xafml new file mode 100644 index 0000000..7cc37e2 --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Module/Model.DesignedDiffs.xafml @@ -0,0 +1,5 @@ + + + + + diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Module/Module.cs b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Module/Module.cs new file mode 100644 index 0000000..8d24c39 --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Module/Module.cs @@ -0,0 +1,51 @@ +using System.ComponentModel; +using DevExpress.ExpressApp; +using DevExpress.ExpressApp.DC; +using DevExpress.Persistent.Base; +using DevExpress.Persistent.BaseImpl; +using DevExpress.ExpressApp.Model; +using DevExpress.ExpressApp.Actions; +using DevExpress.ExpressApp.Editors; +using DevExpress.ExpressApp.Updating; +using DevExpress.ExpressApp.Model.Core; +using DevExpress.ExpressApp.Model.DomainLogics; +using DevExpress.ExpressApp.Model.NodeGenerators; +using DevExpress.Xpo; +using DevExpress.ExpressApp.Xpo; +using NonPersistentObjectsDemo.Module.BusinessObjects; + +namespace NonPersistentFiltering.Module; + +// For more typical usage scenarios, be sure to check out https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.ModuleBase. +public sealed class NonPersistentFilteringModule : ModuleBase { + public NonPersistentFilteringModule() { + // + // NonPersistentFilteringModule + // + RequiredModuleTypes.Add(typeof(DevExpress.ExpressApp.SystemModule.SystemModule)); + RequiredModuleTypes.Add(typeof(DevExpress.ExpressApp.Objects.BusinessClassLibraryCustomizationModule)); + } + public override IEnumerable GetModuleUpdaters(IObjectSpace objectSpace, Version versionFromDB) { + ModuleUpdater updater = new DatabaseUpdate.Updater(objectSpace, versionFromDB); + return new ModuleUpdater[] { updater }; + } + public override void Setup(XafApplication application) { + base.Setup(application); + // Manage various aspects of the application UI and behavior at the module level. + application.SetupComplete += Application_SetupComplete; + } + private void Application_SetupComplete(object sender, EventArgs e) { + Application.ObjectSpaceCreated += Application_ObjectSpaceCreated; + } + private void Application_ObjectSpaceCreated(object sender, ObjectSpaceCreatedEventArgs e) { + var npos = e.ObjectSpace as NonPersistentObjectSpace; + if (npos != null) { + new ArticleAdapter(npos); + new ContactAdapter(npos); + } + } + public override void CustomizeTypesInfo(ITypesInfo typesInfo) { + base.CustomizeTypesInfo(typesInfo); + CalculatedPersistentAliasHelper.CustomizeTypesInfo(typesInfo); + } +} diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Module/NonPersistentFiltering.Module.csproj b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Module/NonPersistentFiltering.Module.csproj new file mode 100644 index 0000000..cd4dd1e --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Module/NonPersistentFiltering.Module.csproj @@ -0,0 +1,25 @@ + + + net6.0 + false + false + 1.0.* + 1.0.0.0 + Debug;Release;EasyTest + enable + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Module/ReadMe.txt b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Module/ReadMe.txt new file mode 100644 index 0000000..087d288 --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Module/ReadMe.txt @@ -0,0 +1,32 @@ +Project Description + +This project implements a platform-agnostic Module. UI-independent application +elements can be implemented here (Business Objects, Controllers, etc.). The root project +folder contains the Module.cs(vb) file with the class that inherits ModuleBase. +This class allows you to view and customize Module components: +referenced modules, Controllers and business classes. Additionally, the root folder +contains Application Model difference files (XAFML files) that keep application +settings specific for the current Module. Difference files can be customized in code +or in the Model Editor. + + +Relevant Documentation + +Application Solution Components +https://docs.devexpress.com/eXpressAppFramework/112569 + +XAF Community Extensions +https://www.devexpress.com/products/net/application_framework/#extensions + +Debugging, Unit and Functional Testing +https://docs.devexpress.com/eXpressAppFramework/112572 + +ModuleBase Class +https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.ModuleBase + + +Application Model +https://docs.devexpress.com/eXpressAppFramework/112579 + +Model Editor +https://docs.devexpress.com/eXpressAppFramework/112582 \ No newline at end of file diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Module/Welcome.html b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Module/Welcome.html new file mode 100644 index 0000000..dde5abf --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Module/Welcome.html @@ -0,0 +1,191 @@ + + + + + Your XAF application + + + + +
+ + + + + +
+
+

The XAF Solution Wizard has successfully generated the solution according to your settings.

+
    +
  • The NonPersistentFiltering.Module project keeps your platform-agnostic code. + Add persistent objects code to the Business Objects folder of this project and XAF will automatically create a UI to create, read, update and delete these persistent objects.
  • +
  • The NonPersistentFiltering.Win project is a startup project for the desktop application.
  • +
  • To specify the database used by your application, modify the ConnectionString attribute in the configuration file located in the startup project.
  • +
+
+
+ + + + + +
+
+ + + diff --git a/CS/NonPersistentObjectsDemo.Win/App.config b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/App.config similarity index 74% rename from CS/NonPersistentObjectsDemo.Win/App.config rename to CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/App.config index 7c38ed8..bf4274b 100644 --- a/CS/NonPersistentObjectsDemo.Win/App.config +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/App.config @@ -20,27 +20,17 @@ Use the one of predefined values: None, ApplicationFolder, CurrentUserApplicationDataFolder. The default value is ApplicationFolder. - + --> + + - - + + - - - - - - - - - - diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/Controllers/ReadMe.txt b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/Controllers/ReadMe.txt new file mode 100644 index 0000000..a2c3f7a --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/Controllers/ReadMe.txt @@ -0,0 +1,25 @@ +Folder Description + +The "Controllers" project folder is intended for storing WinForms-specific Controller classes +that can change the default XAF application flow and add new features. + + +Relevant Documentation + +Controllers and Actions +https://docs.devexpress.com/eXpressAppFramework/112623 + +Implement Custom Controllers +https://docs.devexpress.com/eXpressAppFramework/112621 + +Define the Scope of Controllers and Actions +https://docs.devexpress.com/eXpressAppFramework/113103 + +Ways to Show a View +https://docs.devexpress.com/eXpressAppFramework/112803 + +Ways to Implement Business Logic +https://docs.devexpress.com/eXpressAppFramework/113710 + +Debugging, Unit and Functional Testing +https://docs.devexpress.com/eXpressAppFramework/112572 diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/Editors/ReadMe.txt b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/Editors/ReadMe.txt new file mode 100644 index 0000000..00ff025 --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/Editors/ReadMe.txt @@ -0,0 +1,46 @@ +Folder Description + +This project folder is intended for storing custom WinForms List Editors, +Property Editors and View Items. + + +Relevant Documentation + +Using a Custom Control that is not Integrated by Default +https://docs.devexpress.com/eXpressAppFramework/113610 + +Ways to Access UI Elements and Their Controls +https://docs.devexpress.com/eXpressAppFramework/120092 + +Views +https://docs.devexpress.com/eXpressAppFramework/112611 + +List Editors +https://docs.devexpress.com/eXpressAppFramework/113189 + +Implement Custom Property Editors +https://docs.devexpress.com/eXpressAppFramework/113097 + +View Items +https://docs.devexpress.com/eXpressAppFramework/112612 + +How to: Implement a Custom WinForms List Editor +https://docs.devexpress.com/eXpressAppFramework/112659 + +How to: Support a Context Menu for a Custom WinForms List Editor +https://docs.devexpress.com/eXpressAppFramework/112660 + +How to: Implement a Property Editor (in WinForms Applications) +https://docs.devexpress.com/eXpressAppFramework/112679 + +How to: Implement a Property Editor for Specific Data Management (in WinForms Applications) +https://docs.devexpress.com/eXpressAppFramework/113101 + +How to: Extend Built-in Property Editor's Functionality +https://docs.devexpress.com/eXpressAppFramework/113104 + +How to: Implement a View Item +https://docs.devexpress.com/eXpressAppFramework/112641 + +Debugging, Unit and Functional Testing +https://docs.devexpress.com/eXpressAppFramework/112572 diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/ExpressApp.ico b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/ExpressApp.ico new file mode 100644 index 0000000..e6810fc Binary files /dev/null and b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/ExpressApp.ico differ diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/Images/ExpressAppLogo.png b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/Images/ExpressAppLogo.png new file mode 100644 index 0000000..3a6eaad Binary files /dev/null and b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/Images/ExpressAppLogo.png differ diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/Images/Logo.svg b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/Images/Logo.svg new file mode 100644 index 0000000..68d56ca --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/Images/Logo.svg @@ -0,0 +1,18 @@ + + + + + + diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/Images/ReadMe.txt b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/Images/ReadMe.txt new file mode 100644 index 0000000..230befc --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/Images/ReadMe.txt @@ -0,0 +1,12 @@ +Folder Description + +The "Images" project folder is intended for storing custom image files. + + +Relevant Documentation + +Add and Override Images +https://docs.devexpress.com/eXpressAppFramework/112792 + +Assign a Custom Image +https://docs.devexpress.com/eXpressAppFramework/112744 diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/Model.xafml b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/Model.xafml new file mode 100644 index 0000000..594847b --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/Model.xafml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/NonPersistentFiltering.Win.csproj b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/NonPersistentFiltering.Win.csproj new file mode 100644 index 0000000..0190961 --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/NonPersistentFiltering.Win.csproj @@ -0,0 +1,43 @@ + + + WinExe + net6.0-windows + false + true + ExpressApp.ico + false + 1.0.* + 1.0.0.0 + Debug;Release;EasyTest + enable + + + + + + + + + + + Always + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/Program.cs b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/Program.cs new file mode 100644 index 0000000..db2a62f --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/Program.cs @@ -0,0 +1,80 @@ +using System.Configuration; +using DevExpress.ExpressApp; +using DevExpress.ExpressApp.ApplicationBuilder; +using DevExpress.ExpressApp.Win.ApplicationBuilder; +using DevExpress.ExpressApp.Security; +using DevExpress.ExpressApp.Win; +using DevExpress.Persistent.Base; +using DevExpress.Persistent.BaseImpl; +using DevExpress.XtraEditors; +using DevExpress.ExpressApp.Utils; +using DevExpress.ExpressApp.Win.Utils; +using System.Reflection; + +namespace NonPersistentFiltering.Win; + +static class Program { + private static bool ContainsArgument(string[] args, string argument) { + return args.Any(arg => arg.TrimStart('/').TrimStart('-').ToLower() == argument.ToLower()); + } + /// + /// The main entry point for the application. + /// + [STAThread] + public static int Main(string[] args) { + if(ContainsArgument(args, "help") || ContainsArgument(args, "h")) { + Console.WriteLine("Updates the database when its version does not match the application's version."); + Console.WriteLine(); + Console.WriteLine($" {Assembly.GetExecutingAssembly().GetName().Name}.exe --updateDatabase [--forceUpdate --silent]"); + Console.WriteLine(); + Console.WriteLine("--forceUpdate - Marks that the database must be updated whether its version matches the application's version or not."); + Console.WriteLine("--silent - Marks that database update proceeds automatically and does not require any interaction with the user."); + Console.WriteLine(); + Console.WriteLine($"Exit codes: 0 - {DBUpdaterStatus.UpdateCompleted}"); + Console.WriteLine($" 1 - {DBUpdaterStatus.UpdateError}"); + Console.WriteLine($" 2 - {DBUpdaterStatus.UpdateNotNeeded}"); + return 0; + } + DevExpress.ExpressApp.FrameworkSettings.DefaultSettingsCompatibilityMode = DevExpress.ExpressApp.FrameworkSettingsCompatibilityMode.Latest; +#if EASYTEST + DevExpress.ExpressApp.Win.EasyTest.EasyTestRemotingRegistration.Register(); +#endif + WindowsFormsSettings.LoadApplicationSettings(); + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + DevExpress.Utils.ToolTipController.DefaultController.ToolTipType = DevExpress.Utils.ToolTipType.SuperTip; + if(Tracing.GetFileLocationFromSettings() == DevExpress.Persistent.Base.FileLocation.CurrentUserApplicationDataFolder) { + Tracing.LocalUserAppDataPath = Application.LocalUserAppDataPath; + } + Tracing.Initialize(); + + string connectionString = null; + if(ConfigurationManager.ConnectionStrings["ConnectionString"] != null) { + connectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString; + } +#if EASYTEST + if(ConfigurationManager.ConnectionStrings["EasyTestConnectionString"] != null) { + connectionString = ConfigurationManager.ConnectionStrings["EasyTestConnectionString"].ConnectionString; + } +#endif + ArgumentNullException.ThrowIfNull(connectionString); + var winApplication = ApplicationBuilder.BuildApplication(connectionString); + + if (ContainsArgument(args, "updateDatabase")) { + using var dbUpdater = new WinDBUpdater(() => winApplication); + return dbUpdater.Update( + forceUpdate: ContainsArgument(args, "forceUpdate"), + silent: ContainsArgument(args, "silent")); + } + + try { + winApplication.Setup(); + winApplication.Start(); + } + catch(Exception e) { + winApplication.StopSplash(); + winApplication.HandleException(e); + } + return 0; + } +} diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/ReadMe.txt b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/ReadMe.txt new file mode 100644 index 0000000..cebe462 --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/ReadMe.txt @@ -0,0 +1,33 @@ +Project Description + +This project implements a WinForms application. The root project folder +contains the WinApplication.cs file with the class that inherits WinApplication. +This class allows you to view and customize Module components: +referenced modules, Controllers and business classes. Additionally, the root folder +contains Application Model difference files (XAFML files) that keep application +settings specific for the current Module. Difference files can be customized in code +or in the Model Editor. + + +Relevant Documentation + +Application Solution Components +https://docs.devexpress.com/eXpressAppFramework/112569 + +XAF Community Extensions +https://www.devexpress.com/products/net/application_framework/#extensions + +Debugging, Unit and Functional Testing +https://docs.devexpress.com/eXpressAppFramework/112572 + +WinApplication Class +https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.Win.WinApplication + +XafApplication Class +https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.XafApplication + +Application Model +https://docs.devexpress.com/eXpressAppFramework/112579 + +Model Editor +https://docs.devexpress.com/eXpressAppFramework/112582 \ No newline at end of file diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/Startup.cs b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/Startup.cs new file mode 100644 index 0000000..e52a264 --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/Startup.cs @@ -0,0 +1,40 @@ +using System.Configuration; +using DevExpress.ExpressApp; +using DevExpress.ExpressApp.ApplicationBuilder; +using DevExpress.ExpressApp.Win.ApplicationBuilder; +using DevExpress.ExpressApp.Security; +using DevExpress.ExpressApp.Win; +using DevExpress.Persistent.Base; +using DevExpress.Persistent.BaseImpl; +using DevExpress.XtraEditors; +using DevExpress.ExpressApp.Design; + +namespace NonPersistentFiltering.Win; + +public class ApplicationBuilder : IDesignTimeApplicationFactory { + public static WinApplication BuildApplication(string connectionString) { + var builder = WinApplication.CreateBuilder(); + builder.UseApplication(); + builder.Modules + .Add() + .Add(); + builder.ObjectSpaceProviders + .AddXpo((application, options) => { + options.ConnectionString = connectionString; + }) + .AddNonPersistent(); + builder.AddBuildStep(application => { + application.ConnectionString = connectionString; +#if DEBUG + if(System.Diagnostics.Debugger.IsAttached && application.CheckCompatibilityType == CheckCompatibilityType.DatabaseSchema) { + application.DatabaseUpdateMode = DatabaseUpdateMode.UpdateDatabaseAlways; + } +#endif + }); + var winApplication = builder.Build(); + return winApplication; + } + + XafApplication IDesignTimeApplicationFactory.Create() + => BuildApplication(XafApplication.DesignTimeConnectionString); +} diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/WinApplication.cs b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/WinApplication.cs new file mode 100644 index 0000000..c3e6775 --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/WinApplication.cs @@ -0,0 +1,50 @@ +using System.ComponentModel; +using DevExpress.ExpressApp; +using DevExpress.ExpressApp.ApplicationBuilder; +using DevExpress.ExpressApp.Win; +using DevExpress.ExpressApp.Updating; +using DevExpress.ExpressApp.Win.Utils; +using DevExpress.ExpressApp.Xpo; + +namespace NonPersistentFiltering.Win; + +// For more typical usage scenarios, be sure to check out https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.Win.WinApplication._members +public class NonPersistentFilteringWindowsFormsApplication : WinApplication { + public NonPersistentFilteringWindowsFormsApplication() { + SplashScreen = new DXSplashScreen(typeof(XafSplashScreen), new DefaultOverlayFormOptions()); + ApplicationName = "NonPersistentFiltering"; + CheckCompatibilityType = DevExpress.ExpressApp.CheckCompatibilityType.DatabaseSchema; + UseOldTemplates = false; + DatabaseVersionMismatch += NonPersistentFilteringWindowsFormsApplication_DatabaseVersionMismatch; + CustomizeLanguagesList += NonPersistentFilteringWindowsFormsApplication_CustomizeLanguagesList; + } + private void NonPersistentFilteringWindowsFormsApplication_CustomizeLanguagesList(object sender, CustomizeLanguagesListEventArgs e) { + string userLanguageName = System.Threading.Thread.CurrentThread.CurrentUICulture.Name; + if(userLanguageName != "en-US" && e.Languages.IndexOf(userLanguageName) == -1) { + e.Languages.Add(userLanguageName); + } + } + private void NonPersistentFilteringWindowsFormsApplication_DatabaseVersionMismatch(object sender, DevExpress.ExpressApp.DatabaseVersionMismatchEventArgs e) { +#if EASYTEST + e.Updater.Update(); + e.Handled = true; +#else + if(System.Diagnostics.Debugger.IsAttached) { + e.Updater.Update(); + e.Handled = true; + } + else { + string message = "The application cannot connect to the specified database, " + + "because the database doesn't exist, its version is older " + + "than that of the application or its schema does not match " + + "the ORM data model structure. To avoid this error, use one " + + "of the solutions from the https://www.devexpress.com/kb=T367835 KB Article."; + + if(e.CompatibilityError != null && e.CompatibilityError.Exception != null) { + message += "\r\n\r\nInner exception: " + e.CompatibilityError.Exception.Message; + } + throw new InvalidOperationException(message); + } +#endif + } +} diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/WinModule.cs b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/WinModule.cs new file mode 100644 index 0000000..57a3ab5 --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/WinModule.cs @@ -0,0 +1,26 @@ +using System.ComponentModel; +using DevExpress.ExpressApp; +using DevExpress.ExpressApp.DC; +using DevExpress.ExpressApp.Model; +using DevExpress.ExpressApp.Editors; +using DevExpress.ExpressApp.Actions; +using DevExpress.ExpressApp.Updating; +using DevExpress.ExpressApp.Model.Core; +using DevExpress.ExpressApp.Model.DomainLogics; +using DevExpress.ExpressApp.Model.NodeGenerators; + +namespace NonPersistentFiltering.Win; + +[ToolboxItemFilter("Xaf.Platform.Win")] +// For more typical usage scenarios, be sure to check out https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.ModuleBase. +public sealed class NonPersistentFilteringWinModule : ModuleBase { + public NonPersistentFilteringWinModule() { + DevExpress.ExpressApp.Editors.FormattingProvider.UseMaskSettings = true; + } + public override IEnumerable GetModuleUpdaters(IObjectSpace objectSpace, Version versionFromDB) { + return ModuleUpdater.EmptyModuleUpdaters; + } + public override void Setup(XafApplication application) { + base.Setup(application); + } +} diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/XafSplashScreen.Designer.cs b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/XafSplashScreen.Designer.cs new file mode 100644 index 0000000..42d1990 --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/XafSplashScreen.Designer.cs @@ -0,0 +1,181 @@ +namespace NonPersistentFiltering.Win { + partial class XafSplashScreen + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(XafSplashScreen)); + this.progressBarControl = new DevExpress.XtraEditors.MarqueeProgressBarControl(); + this.labelCopyright = new DevExpress.XtraEditors.LabelControl(); + this.labelStatus = new DevExpress.XtraEditors.LabelControl(); + this.peImage = new DevExpress.XtraEditors.PictureEdit(); + this.peLogo = new DevExpress.XtraEditors.PictureEdit(); + this.pcApplicationName = new DevExpress.XtraEditors.PanelControl(); + this.labelSubtitle = new DevExpress.XtraEditors.LabelControl(); + this.labelApplicationName = new DevExpress.XtraEditors.LabelControl(); + ((System.ComponentModel.ISupportInitialize)(this.progressBarControl.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.peImage.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.peLogo.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.pcApplicationName)).BeginInit(); + this.pcApplicationName.SuspendLayout(); + this.SuspendLayout(); + // + // progressBarControl + // + this.progressBarControl.EditValue = 0; + this.progressBarControl.Location = new System.Drawing.Point(74, 271); + this.progressBarControl.Name = "progressBarControl"; + this.progressBarControl.Properties.Appearance.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(195)))), ((int)(((byte)(194)))), ((int)(((byte)(194))))); + this.progressBarControl.Properties.BorderStyle = DevExpress.XtraEditors.Controls.BorderStyles.Simple; + this.progressBarControl.Properties.EndColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(114)))), ((int)(((byte)(0))))); + this.progressBarControl.Properties.LookAndFeel.SkinName = "Visual Studio 2013 Blue"; + this.progressBarControl.Properties.LookAndFeel.Style = DevExpress.LookAndFeel.LookAndFeelStyle.UltraFlat; + this.progressBarControl.Properties.LookAndFeel.UseDefaultLookAndFeel = false; + this.progressBarControl.Properties.ProgressViewStyle = DevExpress.XtraEditors.Controls.ProgressViewStyle.Solid; + this.progressBarControl.Properties.StartColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(144)))), ((int)(((byte)(0))))); + this.progressBarControl.Size = new System.Drawing.Size(350, 16); + this.progressBarControl.TabIndex = 5; + // + // labelCopyright + // + this.labelCopyright.BorderStyle = DevExpress.XtraEditors.Controls.BorderStyles.NoBorder; + this.labelCopyright.Location = new System.Drawing.Point(24, 324); + this.labelCopyright.Name = "labelCopyright"; + this.labelCopyright.Size = new System.Drawing.Size(47, 13); + this.labelCopyright.TabIndex = 6; + this.labelCopyright.Text = "Copyright"; + // + // labelStatus + // + this.labelStatus.Location = new System.Drawing.Point(75, 253); + this.labelStatus.Name = "labelStatus"; + this.labelStatus.Size = new System.Drawing.Size(50, 13); + this.labelStatus.TabIndex = 7; + this.labelStatus.Text = "Starting..."; + // + // peImage + // + this.peImage.EditValue = ((object)(resources.GetObject("peImage.EditValue"))); + this.peImage.Location = new System.Drawing.Point(12, 12); + this.peImage.Name = "peImage"; + this.peImage.Properties.AllowFocused = false; + this.peImage.Properties.Appearance.BackColor = System.Drawing.Color.Transparent; + this.peImage.Properties.Appearance.Options.UseBackColor = true; + this.peImage.Properties.BorderStyle = DevExpress.XtraEditors.Controls.BorderStyles.NoBorder; + this.peImage.Properties.ShowMenu = false; + this.peImage.Size = new System.Drawing.Size(426, 180); + this.peImage.TabIndex = 9; + this.peImage.Visible = false; + // + // peLogo + // + this.peLogo.EditValue = ((object)(resources.GetObject("peLogo.EditValue"))); + this.peLogo.Location = new System.Drawing.Point(400, 328); + this.peLogo.Name = "peLogo"; + this.peLogo.Properties.AllowFocused = false; + this.peLogo.Properties.Appearance.BackColor = System.Drawing.Color.Transparent; + this.peLogo.Properties.Appearance.Options.UseBackColor = true; + this.peLogo.Properties.BorderStyle = DevExpress.XtraEditors.Controls.BorderStyles.NoBorder; + this.peLogo.Properties.ShowMenu = false; + this.peLogo.Size = new System.Drawing.Size(70, 20); + this.peLogo.TabIndex = 8; + // + // pcApplicationName + // + this.pcApplicationName.Appearance.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(114)))), ((int)(((byte)(0))))); + this.pcApplicationName.Appearance.Options.UseBackColor = true; + this.pcApplicationName.BorderStyle = DevExpress.XtraEditors.Controls.BorderStyles.NoBorder; + this.pcApplicationName.Controls.Add(this.labelSubtitle); + this.pcApplicationName.Controls.Add(this.labelApplicationName); + this.pcApplicationName.Dock = System.Windows.Forms.DockStyle.Top; + this.pcApplicationName.Location = new System.Drawing.Point(1, 1); + this.pcApplicationName.LookAndFeel.UseDefaultLookAndFeel = false; + this.pcApplicationName.Name = "pcApplicationName"; + this.pcApplicationName.Size = new System.Drawing.Size(494, 220); + this.pcApplicationName.TabIndex = 10; + // + // labelSubtitle + // + this.labelSubtitle.Appearance.Font = new System.Drawing.Font("Segoe UI", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.labelSubtitle.Appearance.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(216)))), ((int)(((byte)(188))))); + this.labelSubtitle.Appearance.Options.UseFont = true; + this.labelSubtitle.Appearance.Options.UseForeColor = true; + this.labelSubtitle.Location = new System.Drawing.Point(222, 131); + this.labelSubtitle.Name = "labelSubtitle"; + this.labelSubtitle.Size = new System.Drawing.Size(64, 25); + this.labelSubtitle.TabIndex = 1; + this.labelSubtitle.Text = "Subtitle"; + // + // labelApplicationName + // + this.labelApplicationName.Appearance.Font = new System.Drawing.Font("Segoe UI", 26.25F); + this.labelApplicationName.Appearance.ForeColor = System.Drawing.SystemColors.Window; + this.labelApplicationName.Appearance.Options.UseFont = true; + this.labelApplicationName.Appearance.Options.UseForeColor = true; + this.labelApplicationName.Location = new System.Drawing.Point(123, 84); + this.labelApplicationName.Name = "labelApplicationName"; + this.labelApplicationName.Size = new System.Drawing.Size(278, 47); + this.labelApplicationName.TabIndex = 0; + this.labelApplicationName.Text = "Application Name"; + // + // XafSplashScreen + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.BackColor = System.Drawing.Color.White; + this.ClientSize = new System.Drawing.Size(496, 370); + this.Controls.Add(this.pcApplicationName); + this.Controls.Add(this.peImage); + this.Controls.Add(this.peLogo); + this.Controls.Add(this.labelStatus); + this.Controls.Add(this.labelCopyright); + this.Controls.Add(this.progressBarControl); + this.Name = "XafSplashScreen"; + this.Padding = new System.Windows.Forms.Padding(1); + this.Text = "Form1"; + ((System.ComponentModel.ISupportInitialize)(this.progressBarControl.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.peImage.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.peLogo.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.pcApplicationName)).EndInit(); + this.pcApplicationName.ResumeLayout(false); + this.pcApplicationName.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private DevExpress.XtraEditors.MarqueeProgressBarControl progressBarControl; + private DevExpress.XtraEditors.LabelControl labelCopyright; + private DevExpress.XtraEditors.LabelControl labelStatus; + private DevExpress.XtraEditors.PictureEdit peLogo; + private DevExpress.XtraEditors.PictureEdit peImage; + private DevExpress.XtraEditors.PanelControl pcApplicationName; + private DevExpress.XtraEditors.LabelControl labelSubtitle; + private DevExpress.XtraEditors.LabelControl labelApplicationName; + } +} diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/XafSplashScreen.cs b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/XafSplashScreen.cs new file mode 100644 index 0000000..ad9eaa1 --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/XafSplashScreen.cs @@ -0,0 +1,54 @@ +using System; +using System.Drawing; +using System.IO; +using System.Reflection; +using DevExpress.ExpressApp.Win.Utils; +using DevExpress.Skins; +using DevExpress.Utils.Drawing; +using DevExpress.Utils.Svg; +using DevExpress.XtraSplashScreen; + +namespace NonPersistentFiltering.Win { + public partial class XafSplashScreen : SplashScreen { + private void LoadBlankLogo() { + Assembly assembly = Assembly.GetExecutingAssembly(); + string blankLogoResourceName = assembly.GetName().Name + ".Images.Logo.svg"; + Stream svgStream = assembly.GetManifestResourceStream(blankLogoResourceName); + if(svgStream != null) { + svgStream.Position = 0; + peLogo.SvgImage = SvgImage.FromStream(svgStream); + } + } + protected override void DrawContent(GraphicsCache graphicsCache, Skin skin) { + Rectangle bounds = ClientRectangle; + bounds.Width--; bounds.Height--; + graphicsCache.Graphics.DrawRectangle(graphicsCache.GetPen(Color.FromArgb(255, 87, 87, 87), 1), bounds); + } + protected void UpdateLabelsPosition() { + labelApplicationName.CalcBestSize(); + int newLeft = (Width - labelApplicationName.Width) / 2; + labelApplicationName.Location = new Point(newLeft, labelApplicationName.Top); + labelSubtitle.CalcBestSize(); + newLeft = (Width - labelSubtitle.Width) / 2; + labelSubtitle.Location = new Point(newLeft, labelSubtitle.Top); + } + public XafSplashScreen() { + InitializeComponent(); + LoadBlankLogo(); + this.labelCopyright.Text = "Copyright © " + DateTime.Now.Year.ToString() + " Company Name" + System.Environment.NewLine + "All rights reserved."; + UpdateLabelsPosition(); + } + + #region Overrides + + public override void ProcessCommand(Enum cmd, object arg) { + base.ProcessCommand(cmd, arg); + if((UpdateSplashCommand)cmd == UpdateSplashCommand.Description) { + labelStatus.Text = (string)arg; + } + } + + #endregion + + } +} \ No newline at end of file diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/XafSplashScreen.resx b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/XafSplashScreen.resx new file mode 100644 index 0000000..18fc5b4 --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.Win/XafSplashScreen.resx @@ -0,0 +1,638 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + 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 + YII= + + + \ No newline at end of file diff --git a/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.sln b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.sln new file mode 100644 index 0000000..a415fac --- /dev/null +++ b/CS/XPO/NonPersistentFiltering/NonPersistentFiltering.sln @@ -0,0 +1,42 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.33424.131 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NonPersistentFiltering.Blazor.Server", "NonPersistentFiltering.Blazor.Server\NonPersistentFiltering.Blazor.Server.csproj", "{787C7A8E-80C0-47F4-810B-1B41B4E3DA54}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NonPersistentFiltering.Module", "NonPersistentFiltering.Module\NonPersistentFiltering.Module.csproj", "{683BB2A8-F56B-4F37-9DCF-DE906FCAD530}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NonPersistentFiltering.Win", "NonPersistentFiltering.Win\NonPersistentFiltering.Win.csproj", "{4035990A-11F0-4E24-99DA-9A61C0C5F8F9}" +EndProject + +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + EasyTest|Any CPU = EasyTest|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {683BB2A8-F56B-4F37-9DCF-DE906FCAD530}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {683BB2A8-F56B-4F37-9DCF-DE906FCAD530}.Debug|Any CPU.Build.0 = Debug|Any CPU + {683BB2A8-F56B-4F37-9DCF-DE906FCAD530}.EasyTest|Any CPU.ActiveCfg = EasyTest|Any CPU + {683BB2A8-F56B-4F37-9DCF-DE906FCAD530}.EasyTest|Any CPU.Build.0 = EasyTest|Any CPU + {683BB2A8-F56B-4F37-9DCF-DE906FCAD530}.Release|Any CPU.ActiveCfg = Release|Any CPU + {683BB2A8-F56B-4F37-9DCF-DE906FCAD530}.Release|Any CPU.Build.0 = Release|Any CPU + {4035990A-11F0-4E24-99DA-9A61C0C5F8F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4035990A-11F0-4E24-99DA-9A61C0C5F8F9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4035990A-11F0-4E24-99DA-9A61C0C5F8F9}.EasyTest|Any CPU.ActiveCfg = EasyTest|Any CPU + {4035990A-11F0-4E24-99DA-9A61C0C5F8F9}.EasyTest|Any CPU.Build.0 = EasyTest|Any CPU + {4035990A-11F0-4E24-99DA-9A61C0C5F8F9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4035990A-11F0-4E24-99DA-9A61C0C5F8F9}.Release|Any CPU.Build.0 = Release|Any CPU + {787C7A8E-80C0-47F4-810B-1B41B4E3DA54}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {787C7A8E-80C0-47F4-810B-1B41B4E3DA54}.Debug|Any CPU.Build.0 = Debug|Any CPU + {787C7A8E-80C0-47F4-810B-1B41B4E3DA54}.EasyTest|Any CPU.ActiveCfg = EasyTest|Any CPU + {787C7A8E-80C0-47F4-810B-1B41B4E3DA54}.EasyTest|Any CPU.Build.0 = EasyTest|Any CPU + {787C7A8E-80C0-47F4-810B-1B41B4E3DA54}.Release|Any CPU.ActiveCfg = Release|Any CPU + {787C7A8E-80C0-47F4-810B-1B41B4E3DA54}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..cd4c9a2 --- /dev/null +++ b/LICENSE @@ -0,0 +1,3 @@ +This code example is provided "as is" without warranty of any kind. Developer Express Inc ("DevExpress") disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. + +For licensing terms and conditions of DevExpress product(s) required for, or associated with the use of this code example, please refer to the applicable End-User License Agreement at https://www.devexpress.com/Support/licensingfaq.xml \ No newline at end of file diff --git a/readme.md b/readme.md index 645051c..fbe93e1 100644 --- a/readme.md +++ b/readme.md @@ -1,32 +1,54 @@ -*Files to look at*: + +[![](https://img.shields.io/badge/Open_in_DevExpress_Support_Center-FF7200?style=flat-square&logo=DevExpress&logoColor=white)](https://supportcenter.devexpress.com/ticket/details/T952649) +[![](https://img.shields.io/badge/📖_How_to_use_DevExpress_Examples-e9f6fc?style=flat-square)](https://docs.devexpress.com/GeneralInformation/403183) + -* [Contact.cs](./CS/NonPersistentObjectsDemo.Module/BusinessObjects/Contact.cs) -* [Article.cs](./CS/NonPersistentObjectsDemo.Module/BusinessObjects/Article.cs) -* [NonPersistentObjectBase.cs](./CS/NonPersistentObjectsDemo.Module/BusinessObjects/NonPersistentObjectBase.cs) -* [Module.cs](./CS/NonPersistentObjectsDemo.Module/Module.cs) +# XAF - How to filter and sort non-persistent objects -# How to filter and sort Non-Persistent Objects +If a collection of [non\-persistent objects](https://docs.devexpress.com/eXpressAppFramework/116516/concepts/business-model-design/non-persistent-objects) contains many items, you may need to filter it. However, built-in filters are disabled for non-persistent collections by default. -## Scenario +> [!WARNING] +> We created this example for demonstration purposes and it is not intended to address all possible usage scenarios. +> If this example does not have certain functionality or you want to change its behavior, you can extend this example. This can be a complex task that requires good knowledge of XAF: [UI Customization Categories by Skill Level](https://www.devexpress.com/products/net/application_framework/xaf-considerations-for-newcomers.xml#ui-customization-categories), and you may need to research how our components work. Refer to the following help topic for more information: [Debug DevExpress .NET Source Code with PDB Symbols](https://docs.devexpress.com/GeneralInformation/403656/support-debug-troubleshooting/debug-controls-with-debug-symbols). +> We are unable to help with such tasks as custom programming is outside our Support Service scope: [Technical Support Scope](https://www.devexpress.com/products/net/application_framework/xaf-considerations-for-newcomers.xml#support). -When a [Non\-Persistent Object](https://docs.devexpress.com/eXpressAppFramework/116516/concepts/business-model-design/non-persistent-objects) colletion contains a lot of objects, it is often useful to filter it. However, the built-in filtering facilities are disabled for non-persistent collections by default. +## Implementation Details -## Solution +To enable filtering and sorting for [non\-persistent objects](https://docs.devexpress.com/eXpressAppFramework/116516/concepts/business-model-design/non-persistent-objects), you can use either the built-in `DynamicCollection` class or a custom `DynamicCollectionBase` descendant. -To enable filtering and sorting for [Non\-Persistent Objects](https://docs.devexpress.com/eXpressAppFramework/116516/concepts/business-model-design/non-persistent-objects), use the built-in **DynamicCollection** class or a custom **DynamicCollectionBase** descendant. +1. Create a `DynamicCollection` instance and pass it in the [NonPersistentObjectSpace\.ObjectsGetting](https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.NonPersistentObjectSpace.ObjectsGetting) event handler. +2. Subscribe to the `DynamicCollection.FetchObjects` event and pass a new collection of non-persistent objects every time filter or sort parameters change. +3. If you cannot filter the collection, set the `ShapeData` event parameter to `true`. The `DynamicCollection` then processes the data (filter, sort, and trim) internally. + + When you use the `DynamicCollection`, the built-in [FullTextSearch action](https://docs.devexpress.com/eXpressAppFramework/112997/concepts/filtering/full-text-search-action) is displayed in corresponding non-persistent list views. -Create a **DynamicCollection** instance and pass it in the [NonPersistentObjectSpace\.ObjectsGetting](https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.NonPersistentObjectSpace.ObjectsGetting) event handler. Subscribe to the **DynamicCollection.ObjectsGetting** event and pass a new collection of non-persistnet objects every time the filtering or sorting parameters are changed. If you cannot filter the collection manually, set the **ShapeRawData** event parameter to *true*. Then, **DynamicCollection** will process data (filter, sort, trim) internally. +4. The `FindArticlesController` in this example shows a custom search form with a lookup editor that allows filtering non-persistent objects in a lookup list view. This example demonstrates two approaches to filter objects. -- The *Contact* objects are filtered at the storage level. The Criteria and Sorting values passed in event parameters are converted to the storage-specific format and used in arguments of the DataSet.Select method call. The DataSet returns filtered and sorted data that is then transformed into non-persistent objects. This approach can be useful if data for non-persistent objects is obtained from a remote service, a custom database query or a stored procedure. +- **Contact** objects are filtered at the storage level. `Criteria` and `Sorting` values passed in event parameters are converted to a storage-specific format and used as arguments of the `DataTable.Select` method call. `DataSet` returns filtered and sorted data that is then transformed into non-persistent objects. This approach can be useful when data for non-persistent objects is obtained from a remote service, a custom database query or a stored procedure. -- The *Artice* objects are filtered and sorted by the DynamicCollection internally. This functionality is enabled when the **ShapeRawData** parameter of the **DynamicCollection.ObjectsGetting** event is set to *true*. This approach is useful when all data is already available and no custom processing is required. +- **Article** objects are filtered and sorted internally by a `DynamicCollection`. This functionality is enabled when the `ShapeData` parameter of the `DynamicCollection.FetchObjects` event is set to `true`. This approach is useful when all data is already available and no custom processing is required. -When **DynamicCollection** is used, the built-in [FullTextSearch Action](https://docs.devexpress.com/eXpressAppFramework/112997/concepts/filtering/full-text-search-action) is shown in corresonding non-persistent list views. +## Files to Review -The *FindArticlesController* in this example shows a custom search form with a lookup editor that allows filtering non-perssitent objects in a lookup list view. +- [Contact.cs](./CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/BusinessObjects/Contact.cs) +- [Article.cs](./CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/BusinessObjects/Article.cs ) +- [NonPersistentObjectBase.cs](./CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/BusinessObjects/NonPersistentObjectBase.cs ) +- [Module.cs](./CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/Module.cs ) +- [FindArticlesController.cs](CS/EFCore/NonPersistentFilteringEF/NonPersistentFilteringEF.Module/Controllers/FindArticlesController.cs) -Filtering and sorting at the data source level is also supported in Reports. Use the [Criteria](https://docs.devexpress.com/eXpressAppFramework/DevExpress.Persistent.Base.ReportsV2.DataSourceBase.Criteria) and [Sorting](https://docs.devexpress.com/eXpressAppFramework/DevExpress.Persistent.Base.ReportsV2.DataSourceBase.Sorting) properties of [CollectionDataSource](https://docs.devexpress.com/eXpressAppFramework/DevExpress.Persistent.Base.ReportsV2.CollectionDataSource) to specify filter criteria and sorting parameters. +## Documentation +- [Non-Persistent Objects](https://docs.devexpress.com/eXpressAppFramework/116516/business-model-design-orm/non-persistent-objects) + + +## More Examples + +- [How to implement CRUD operations for Non-Persistent Objects stored remotely in eXpressApp Framework](https://github.com/DevExpress-Examples/XAF_Non-Persistent-Objects-Editing-Demo) +- [How to edit Non-Persistent Objects nested in a Persistent Object](https://github.com/DevExpress-Examples/XAF_Non-Persistent-Objects-Nested-In-Persistent-Objects-Demo) +- [How to: Display a List of Non-Persistent Objects](https://github.com/DevExpress-Examples/XAF_how-to-display-a-list-of-non-persistent-objects-e980) +- [How to filter and sort Non-Persistent Objects](https://github.com/DevExpress-Examples/XAF_Non-Persistent-Objects-Filtering-Demo) +- [How to refresh Non-Persistent Objects and reload nested Persistent Objects](https://github.com/DevExpress-Examples/XAF_Non-Persistent-Objects-Reloading-Demo) +- [How to edit a collection of Persistent Objects linked to a Non-Persistent Object](https://github.com/DevExpress-Examples/XAF_Non-Persistent-Objects-Edit-Linked-Persistent-Objects-Demo)