.Net 4.5 / WPF | .Net Standard 2.0 | Xamarin.Android | Xamarin.iOS | UWP | |
CrossPlatformLibrary | yes | yes | yes | yes | yes |
CrossPlatformLibrary.Forms | no | yes | yes | yes | not yet |
This library is available on NuGet. Use the following command to install CrossPlatformLibrary using NuGet package manager console:
PM> Install-Package CrossPlatformLibrary
The Xamarin.Forms specific library can be installed using following command:
PM> Install-Package CrossPlatformLibrary.Forms
The library contains a rich set of customized user controls which extend basic implementations of existing controls. Following screenshots of the SampleApp demonstrate the usege of some of the delivered controls. The coloring is pretty random and mainly used for debugging/development purposes. Since every control uses dynamic styles, you're free to override the default styles.
In order to use the user controls of CrossPlatformLibrary, the styles used in these controls need to be initialized properly. For this reason, add following line of code just after the line this.InitializeComponent();
in App.xaml.cs
:
CrossPlatformLibrary.Forms.CrossPlatformLibrary.Init(this, "SampleApp.Theme");
TODO: to be documented
System.Collections.Generic.KeyNotFoundException: The resource 'Theme.Color.TextColor' is not present in the dictionary.
This error eventually appears if user controls of CrossPlatformLibrary are used without calling theCrossPlatformLibrary.Forms.Init(..)
method.
The base viewmodel BaseViewModel
implements a pretty sophisiticated and praxisproven user input validation system which allows to run client- and server-based property validation side-by-side.
There are a few steps to follow to get input validation to work:
- Inherit your viewmodels from
BaseViewModel
or implement a similar logic which exposes aBaseViewModel.Validation
property. - Override the protected method
SetupValidation
. This enables your viewmodel to use input validation. The most simple setup just returns an emptyViewModelValidation
. - Setup validation rules inside
SetupValidation
. There are basically two different approaches: Either you validate viewmodel properties locally (validation logic provided by the viewmodel) or you call a backend service which validates a given object (DTO) against some central validation logic. - Configure the according view to react on validation errors. This is done in XAML by binding a dependency property to the string list of validation errors for a certain property. The following example binds to validation errors for property 'UserName':
ValidationErrors="{Binding Validation.Errors[UserName]}"
- In order to run the validation, just call
Validation.IsValidAsync()
. Depending on the result (true/false) we proceed with further actions (e.g. saving the object).
var isValid = await this.Validation.IsValidAsync();
if (isValid)
{
// TODO Save...
}
Following snippet is an extract of a unit test. It demonstrates some setup variations.
protected override ViewModelValidation SetupValidation()
{
var viewModelValidation = new ViewModelValidation();
// Validation function with parameter-less custom error message
viewModelValidation.AddValidationFor(nameof(this.UserName))
.When(() => string.IsNullOrEmpty(this.UserName))
.Show(() => "Username must not be empty");
// Validation rule with parameter and custom error message
viewModelValidation.AddValidationFor(nameof(this.Email))
.When(new IsNotNullOrEmptyRule())
.Show(p => $"Email address '{p}' must not be empty.");
// Validation delegated to async service
viewModelValidation.AddDelegateValidation(nameof(this.UserName), nameof(this.Email))
.Validate(async () => (await this.validationService.ValidatePersonAsync(this.CreatePerson())).Errors);
return viewModelValidation;
}
The bootstrapping mechanism is used to startup and shutdown an application in a controlled way. The boostrapper is called at the entry point of an application and it cares about the basic initialisation tasks. The entry point of the application can differ from application type to application type.
CrossPlatformLibrary provides you with a base implementation of a bootstrapper. You may want to inherit the Bootstrapper class in order to influence the startup procedure and/or bootstrap parts of your own application. Following things can be done with a custom Bootstrapper:
-
Register project-dependant dependencies in the IoC container
-
Define your own IExceptionHandler to be used for unhandled exceptions
-
Handle exceptions that happen during Bootstrapping (BootstrappingException)
TODO: to be documented
Unhandled exceptions may occur in every application. Better we are prepared for such exceptions. IExceptionHandler instance is used to handle any System.Exception that is not handled by the application.
The tracing functionality provided by CrossPlatformLibrary can be used to write application debug traces. The purpose of trace messages is to assist developers and 3rd level support locating and fixing bugs or other program flow related problems.
<document abstraction, design desicion>
Tracer Name | Description |
EmptyTracer | EmptyTracer doesn’t trace anything. Each call to the Write method will not execute anything. |
DebugTracer | DebugTracer uses System.Diagnostics.Debug.WriteLine to write traces. |
ActionTracer | ActionTracer allows you to define an Action/Delegate to which traces are written to. |
Your own ITracer implementation | Write your own tracer by implementing ITracer or abstract TracerBase. |
You can implement your own tracer by either implementing the ITracer and ITracerFactory interface on you own or extend the provided base implementation of the TracerBase and TracerFactoryBase.
Trace Category | Description |
Debug | Information traced for debugging purposes. Usually only active in test or pre-production releases. |
Information | Important trace information which is usually also traced by production software. |
Warning | Some warnings which are not critical but need care. |
Error | Typically handled exceptions which have to be traced in order to be analyzed and avoided. |
Fatal | Software crashes, unhandled exceptions. |
CrossPlatformLibrary was designed in a way which promotes modular design. Modules are loosely coupled and self-contained units which serve a concrete purpose. This approach supports the separation of concerns in your application. You can easily test modules in isolation and integrate them later into your application(s) without having them too tighly coupled.
TODO: to be documented
TODO: to be documented
Dependency injection containers are used to manage dependencies between components. This typically involes registration and instanciation and resolution of dependencies. CrossPlatformLibrary uses its own implementation of a dependency injection container, CrossPlatformLibrary.Ioc.SimpleIoc.
TODO: to be documented
Want to contribute to this project? Feel free to start a discussion in the issues area to see if your idea could fit in.
CrossPlatformLibrary is Copyright © 2019 Thomas Galliker. Free for non-commercial use. For commercial use please contact the author.