Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Features that apply to the whole application, and to all the controls.
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
To install Wisej.NET 4, you will need two files: the "Wisej.NET-4-VS2022.vsix" extension and the "Wisej-4.4.0.0-beta.#.nupkg" package. The most current "Wisej.NET-4-VS2022.vsix" can be downloaded from the link provided below.
Meanwhile, the latest beta versions of the Wisej-4 package, and all the Wisej-4 extensions, will be accessible on NuGet.
Be sure to obtain both files for a successful setup and to enjoy the full feature set offered by Wisej.NET 4, incorporating advancements like managed System.Drawing, the .NET Core out-of-process designer, and the new fluent markup extensions.
Please be aware that the designer is no longer included within the VSIX extension. Instead, it is now deployed with each NuGet package. The VSIX extension, however, is still necessary for the replacement of the ResXFileCodeGenerator and several other enhancements within Visual Studio.
Editors, especially collection editors, present the most significant challenges when migrating to the out-of-process designer. As of now, we have integrated the following collection editors using the basic editor system that comes with the designer. However, we are planning to transition the more complex editors in an upcoming release.
DataGridViewColumnCollection
TreeNodeCollection
The ImageSourceEditor is presently unable to load icons from icon packs. However, this functionality will be completed and available before the official release.
The cell style editor is functional but incomplete. It does not provide a preview of the style changes being made. Additionally, any modifications are applied directly to the DataGridViewCellStyle
instance. Consequently, if you press the Cancel button, the edits will still be committed.
Data binding and the associated editors function as expected. However, it's worth noting that Microsoft has not yet provided an implementation for the typed DataSet editor. Currently, Microsoft suggests using the new Object Data Source Binding as an alternative to accommodate this gap.
If you prefer to use .NET 9 or .NET 10 instead of .NET 8, you can do so with minimal issues. However, it's important to note that with .NET 9, Microsoft has completely removed the BinaryFormatter
, as part of their ongoing initiative to improve developer security by protecting them from themselves.
Interestingly, they have reintroduced the same "unsafe" classes by offering them as a NuGet package.
This change affects all designer .resx
files that contain values serialized with the BinaryFormatter
. While these files are safe as internal .resx
files — something even Microsoft acknowledges — they will not load properly in .NET 9 and above unless you include the following NuGet package reference in your project:
Additionally, we are actively working on removing the binary serialization of custom snap lines and responsive properties to align with the latest security practices and ensure optimal compatibility with .NET 9 and new releases.
Welcome to Wisej.NET - the first Web Integrated Server Environment to design, build, debug, and manage Real Time ASP.NET Applications using C# or VB.NET with JavaScript in Visual Studio.
Wisej.NET is the most advanced, enterprise-scale, ASP.NET and ASP.NET Core development system in .NET. It covers just about the entire spectrum of features that business developers need to build and manage complex web applications.
It is also a Rapid Web Development system, thanks to its unique WYSIWYG pixel-perfect designer integrated into Visual Studio, and its familiar component object model.
Developers can achieve in a few days what would take months, if at all possible, with any other web framework. The power and versatility of Wisej.NET also mean that it's a large and sophisticated system, with hundreds of features and several ways to accomplish most tasks.
The documentation is organized in multiple cross-linked books. This one is the most extensive, being about the concepts and features for each one of the many available controls.
There is also a full API book, and a book for the extension, integration, deployment, and more.
Welcome to Wisej.NET - the first Web Integrated Server Environment to design, build, debug, and manage Real Time ASP.NET Applications using C# or VB.NET with JavaScript in Visual Studio.
The first thing to do, now that you have installed Wisej.NET, is to launch Visual Studio and create a new project. Or, launch Visual Studio and open one of our many examples.
Sometimes Visual Studio decides not to show the new project templates. If that happens, please follow the instructions in the missing templates section.
The first time you open the designer, you will get the license activation dialog. Enter your developer (or trial) license and everything should work.
If you are using the Wisej.NET Developer Community edition, please make sure to comply with the terms & conditions. Commercial use is only permitted for small organizations.
The Wisej.NET library can be used with any version of Visual Studio or Visual Studio Code. However, the designer plug in is supported on Visual Studio 2019 and 2022 (Community, Professional, or Enterprise) on Windows.
Make sure that you have installed these 2 workloads:
ASP.NET and web development
.NET desktop development (needed for the designer)
Wisej.NET 4 Introduction
Wisej.NET 4 introduces significant improvements driven by two main factors:
The adoption of a .NET Core
-only designer
The replacement of GDI+
with our managed graphics system
The .NET Core
-only designer, in addition to the existing .NET Framework 4.8
designer enables projects to use the latest .NET Core
libraries without maintaining .NET Framework
compatibility.
Replacing GDI+
with our managed System.Drawing
library standardizes font measurements across platforms and removes the need for libgdiplus
on Linux systems.
It is crucial to ensure that any changes made by the designer can be undone and recovered. This ability is essential because if the designer serialization behaves unexpectedly, there is a risk of losing code.
We will extend the support for Wisej.NET version 3.5. This includes continuing to offer bug fixes and enhancements to ensure stability and reliability for users who are transitioning to version 4.0.
For instructions on how to download the Wisej.NET 4.0 Beta packages, please refer to the Public Beta section.
Rebuilding Wisej.NET designers for the out-of-process .NET Core Designer required substantial changes and may present challenges in upcoming builds. Please be prepared to troubleshoot potential issues as we refine the implementation.
Because Visual Studio uses the .NET Framework, Microsoft divided the designer into two parts: the "client" component running on the .NET Framework within Visual Studio and the "server" component running in a hidden .NET Core process. These components connect through an interprocess communication framework. For details on these Visual Studio changes, visit Microsoft's documentation.
For details on the .NET Core designer in Wisej.NET 4, visit:
System.Drawing
in .NET Framework and System.Drawing.Common
In .NET Core wrap Windows GDI+, the graphics device interface is used to render graphics and load fonts on Windows. System.Drawing.Common
extends to Linux using libgdiplus. Microsoft provides no graphic support in .NET Core for iOS or Android platforms.
In Wisej.NET 3.5, font loading used different libraries per platform. .NET Framework 4.8
used System.Drawing
with Windows GDI+. .NET Core used System.Drawing.Common
with libgdiplus on Linux. Wisej.NET Hybrid applications used an early System.Drawing
reimplementation using ImageSharp for iOS and Android. This caused font measurement differences across platforms.
Read below to understand how these changes affect your projects and potential issues to avoid:
Microsoft introduced Fluent Markup extensions for .NET Multi-platform App UI (MAUI), which are documented at Fluent Markup Extensions. These extensions streamline declarative UI development in code.
Wisej.NET 4 incorporated comprehensive support for Fluent Markup syntax in both C# and VB.NET, enabling consistent coding across programming languages.
This enhancement came from Tim at POET, one of our Technology Partners.
For an introduction to Wisej.Web.Markup
extensions, visit:
Wisej.NET controls with labels include the AllowHtml property for HTML tags in text.
We've added the AllowMarkdown
property to complement AllowHtml
. This property enables markdown text rendering across Wisej.NET controls - expanded text formatting options.
Application.Services methods are now chainable, allowing concise syntax like Application.Services.AddService<Service1>().AddService<Service2>()
.
The new AddOrReplaceService
method replaces a service without requiring prior removal.
We now fully support HttpOnly
cookies. Previously, developers could use HttpOnly cookies through the native HttpContext. The Wisej.Base.Cookie
class now includes a property for managing HttpOnly
cookies.
All controls now include the ControlRendered
and ControlUpdated
events. This allows applications to modify control JSON rendering and handle browser updates without subclassing.
These events enable Wisej.AI to add AI capabilities to any Wisej.NET control.
All C# templates have been revised to incorporate the latest C# syntax enhancements, specifically utilizing file-scoped namespaces and top-level statements.
The updated file-scoped namespace declaration is now implemented across all .cs
files. However, the transition to top-level statements is applied exclusively to the Startup.cs
file. This modern approach simplifies the code structure, making it cleaner and easier to read.
Some Wisej.NET projects need changes in .resx
(resource) and .Designer.cs
(designer) files for Wisej.NET 4 and managed System.Drawing
compatibility.
To facilitate this transition, we have provided an upgrade tool that automatically implements these changes across your project files.
For detailed instructions, visit:
Wisej.NET continues to support .NET Framework 4.8
(and newer) and VB.NET at both runtime and design time. As with all preceding versions, we will maintain this support for the foreseeable future.
To facilitate a smooth transition from Wisej.NET version 3.5 to version 4.0, we will continue to maintain the 3.5 branch by providing bug fixes and enhancements for at least one year following the initial stable release of version 4.0. This ensures ongoing support and stability for existing users during their upgrade process.
In Wisej.NET 4, we have reimplemented all designers and editors to be compatible with the new out-of-process Visual Studio designer for .NET Core
. We will support both sets of designers and editors for .NET Framework
and .NET Core
, providing flexibility and functionality for developers in various environments.
The design experience remains unchanged, with one exception: a slight delay at startup occurs because Visual Studio needs to load the hidden DesignToolsServer.exe
process. The overall functionality and user experience remain consistent.
To maintain compatibility with the .NET Framework, you can leave your multi-targeting unchanged:
To eliminate dependencies on the .NET Framework and switch to using only the .NET Core designer, you will need to employ multi-targeting exclusively with .NET Core targets:
Replace your target framework from "net48
" to "net8.0-windows
", and leave the rest unchanged.
The net8.0-windows
target is required to load the Visual Studio designer because it relies on Windows controls. You won't deploy net8.0-windows
itself. Instead, deploy net8.0
on both Windows and Linux platforms.
Any project that contains Wisej.NET controls that need to be loaded by the designer requires the `net8.0-windows' target. Otherwise, any non-visual library can simply target `net8.0`.
When you choose one of the updated templates, categorized under Project Type as either Wisej.NET 4 or Wisej.NET 4 Hybrid, you will be presented with the new startup wizard shown below.
The primary change is that you can now independently choose .NET Framework and .NET Core versions. Additionally, under the .NET Framework option, you can select "(None)". The project will be configured with the specific settings relative to each target, either included or excluded, based on your selection.
If your projects use local and global embedded images in .resx
files, you will need to update the type attribute in all .resx
files and change all casts from System.Drawing.Bitmap
to Wisej.Base.ResourceImage
.
If you are using System.Drawing.Bitmap
, System.Drawing.Image
, or relying on image names, no changes are necessary.
Refer to the page below for instructions on how to update your projects manually or using the provided tool:
Please be aware that .NET Core is capable of reading all designer files initially created with .NET Framework. However, if the designer code is subsequently updated in .NET Core, it may become incompatible with the .NET Framework designer. Specifically, the .NET Core designer modifies the serialized code in the following ways:
It removes the this
keyword. For example, the line this.button1.Text = "button1"
is simplified to button1.Text = "button1"
.
It also eliminates the use of the delegate class when attaching to events. For example, this.button1.Click += new System.EventHandler(this.button1_Click);
is simplified to button1.Click += button1_Click;
.
The first change, which involves the removal of the this
keyword, maintains compatibility between .NET Core and .NET Framework.
However, if you open the designer code that has been updated in .NET Core using the .NET Framework designer, all the event handlers will be lost. This is due to the change in how delegate instances are created and attached to events.
With .NET Framework
, everything, including your application, Wisej.NET designers, editors, and serializers, was integrated and run within Visual Studio. With .NET Core
, this integration isn't feasible because Visual Studio cannot directly load .NET Core
code.
Microsoft divided the designer system into two main components:
A "client" component running on .NET Framework
within Visual Studio
Manages Visual Studio elements like "menus," "toolbars," "property editors," "edit windows," and the "property grid."
A "server" component running in a hidden .NET Core
process
Loads your Wisej.NET code and executes it to render designer windows
"Injects" these windows into Visual Studio through the DesignToolsServer.exe
process
These components communicate through an interprocess framework:
The client sends request packets for themes, classes, and application data
The server processes these through handlers and returns responses
If you have developed a custom designer, contact us for support on making it compatible with the .NET Core out-of-process designer system.
If you're developing cross-platform applications, be particularly mindful of graphics-related code. While our managed implementation provides consistent behavior across platforms, you should still test the target platform thoroughly to ensure compatibility.
Until version 6.0.0
, you could set the System.Drawing.EnableUnixSupport
application switch to use System.Drawing.Common
on Linux systems with libgdiplus. This is why Wisej.NET references version 6.0.0
of the System.Drawing.Common
NuGet package.
Our new System.Drawing.Managed
implementation delivers consistent performance across all platforms and aligns much more closely with the browsers' font measurements. This ensures a uniform experience regardless of the deployment platform.
Wisej.NET requires a graphics library for loading images from files or embedded resources and measuring text on the server side for controls AutoSize
set to true
. No painting functionality is needed within Wisej.NET.
The Wisej.NET 4 package includes this dependency:
The namespace remains System.Drawing
, so no code changes are needed. All primitives like Point
, Size
, and Color
come from System.Drawing.Primitives
. System.Drawing.Managed
classes like Font
and Image
can cast to and from their System.Drawing.Common
(GDI+) counterparts.
In Wisej.NET 4 for .NET Framework, we shield developers from this difference. Although Font
and Image
come from System.Drawing.Common
, all font measurements use the managed System.Drawing.Font
internally, ensuring compatibility with .NET Core deployments.
As explained on the .NET Core Designer page, using the Visual Studio Designer required building a version of Wisej.Framework compatible with "net8.0-windows
". This build uses System.Drawing.Common
for public properties.
For deployment, we recommend using the non-OS-specific net8.0
target instead of "net8.0-windows
" as it uses only managed code.
As shown above, System.Drawing
(GDI+) is only used for deployment on Windows servers using the .NET Framework.
Wisej.NET imports System.Drawing
on .NET Framework targets and System.Drawing.Common
on .NET Core targets to enable multi-targeting. It also imports System.Drawing.Managed
. Since all three use the same namespace, failing to alias them may cause compiler errors, such as the Font
class being available in multiple assemblies.
Since all three use the same namespace, failing to reference one of the assemblies correctly may cause compiler errors, such as the Font
class being available in multiple assemblies.
In Wisej.NET 4, we reference and alias System.Drawing.Common
like this:
If you get a namespace collision error, remove any System.Drawing.Common
reference from your projects, as it's included with the Wisej.NET 4 NuGet package.
If a third party NuGet pulls in a reference to System.Drawing.Common with a different version causing compiler errors, you can instead add a <PackageReference>
item in your project with the same version and add Alias="sdm
" to the tag.
Here are Microsoft's four alternatives and our assessment of each:
The Aspose.Drawing
package provides a completely managed re-implementation of System.Drawing
. While it offers excellent GDI+ compatibility, it uses a different namespace and requires a commercial license.
Provides interfaces, classes, and supporting types for .NET MAUI Graphics, the abstracted, unified drawing APIs that work cross-platform.
It provides minimal functionality to replace System.Drawing.Font
or Image
and gives different results on different platforms. It requires many dependencies and native bindings from various sources.
For details on these Visual Studio changes, visit .
In the Wisej.NET designer toolbar, you will notice a new button positioned to the right of the options and license information buttons. This button opens a small diagnostic window that displays important data, such as the total memory usage and count of objects used by the designer process. By clicking the "Recycle" button within this window, you can close the designer windows and terminate the current designer process. The designer process will automatically restart when you reopen a design view.
.NET (formerly .NET Core) version 7.0.0 and later System.Drawing.Common
on Linux. This change leaves Linux users without a direct, Microsoft-provided alternative.
Additionally, .NET code running on iOS or Android platforms has never supported any version of System.Drawing.Common
. Microsoft recommends using such as ImageSharp
or SkiaSharp
for these platforms.
In Wisej.NET 3, there are three graphics implementations: GDI+
on Windows, libgdiplus
on Linux, on iOS and Android. All three implementations provide different font measurements, leading to inconsistencies across platforms.
Applications built on Wisej.NET can use the event to draw on controls or within grid cells, enabling complex UI features.
System.Drawing.Managed
(and ) has two major implementations: Font and Graphics. Font handles loading, measuring, and rendering fonts. Graphics handles loading, saving, and drawing images, providing operations available in System.Drawing.Graphics
.
Only the Font implementation is available on the .NET Framework because 's Graphics implementation relies on graphics acceleration primitives exclusive to .NET Core.
Fully Managed Code: With no native dependencies or interop code, ImageSharp simplifies development and can be installed anywhere supports- anything from external devices to embedded/IoT scenarios.
is a managed graphics library that handles various graphic formats, including WebP
. Combined with its Fonts library, it provides a foundation for implementing a cross-platform version of System.Drawing
.
We licensed the source code and worked with SixLabors' founder to create System.Drawing.Managed
. This single, self-contained, managed .NET library replaces System.Drawing.Common
on all platforms, ensuring consistent font measurements across browsers and platforms.
SkiaSharp is a cross-platform 2D graphics API for .NET platforms based on Google's . It provides a comprehensive 2D API for rendering images for mobile, server, and desktop models.
Developed by the Mono team, this library offers classes built around Google's native library. It requires different native assets for platforms and differs from System.Drawing
basic operations like reading font size or measuring text. It cannot measure wrapping lines of text without extensions. Our tests showed font measurements that differed from those of Chromepite Chrome using ; it appears to use many extensions and modifications.
A thin wrapper with limited functionality around (a wrapper around UWP and WinUI platforms) and (a wrapper around , which wraps ).
Font
Managed
Managed
Managed
Graphics
GDI+
Managed
GDI+
Windows
net481
or net8.0
Linux or MacOS
net8.0
iOS Hybrid
net8.0-ios
Android Hybrid
net8.0-android
MacOS Hybrid
net8.0-maccatalyst
Windows Hybrid
net8.0-windows10.0.19041.0
Fluent Markup
is a collection of helper methods and classes aimed at simplifying the creation of declarative .NET
App UI in code.
While Wisej.NET allows you to use the designer to build rich UI components, there are many occasions where it is necessary to build or modify visual components through code. The new Wisej.Web.Markup
extensions make this task significantly more enjoyable.
Fluent Markup is not supported with VB.NET. Properties are similar to methods and clash with extension methods with the same name.
Currently, if you want to add a Button
with a label, a data-bound text with binding events, and attach a "click" event to the button, you would need to write code similar to the following:
With the new Wisej.Web.Markup
extensions, the same code can be written as follows:
Properties are added as methods with the same name as the property. Events are added with the prefix ".On"
followed by the name of the event.
Events that use the EventArgs
type are represented by simple methods that only use the sender as a single argument. Events that pass an argument are represented by actions that take both the sender and the arguments.
For example:
Due to the extensive range of properties and events in Wisej.NET controls, we are excited to enhance the markup extensions. Additional properties and methods will be included in upcoming builds.
Wisej.NET 4 now offers Markdown
support alongside HTML
. This enhancement benefits Wisej.AI by aligning with the preferences of LLMs
for formatting responses in Markdown
.
The conversion from Markdown
to HTML
occurs server-side, ensuring the browser receives HTML
data without client-side JavaScript conversion.
For developers, we've added the AllowMarkdown
property to complement the existing AllowHtml
property. We also provide the System.Markdown
class with a ToHtml(string)
method. This method lets applications convert Markdown
text to HTML
format at any point.
To use Markdown
in your application, set the AllowMarkdown
property to "true
". Then assign the Markdown
text to the "Text
" property for standard controls, or to the "Value
" property for DataGridViewCell
objects.
The example below shows a button in the designer and the "Text" property editor. You can mix Markdown
and HTML
.
To convert Markdown
to HTML programmatically, use the Markdown.ToHtml(text)
method from the System.Markdown
class:
Like the AllowHtml
property, you cannot automatically resize controls with HTML
content. This applies to HTML
and Markdown
content, as Markdown
converts to HTML
before rendering.
Previously, upgrading to Wisej.NET 4 involved a complex process that required replacing instances of System.Drawing.Bitmap
with Wisej.Base.ResourceImage
. However, with the latest build, the requirement to use Wisej.Base.ResourceImage has been eliminated and the class has been removed. This update simplifies the upgrade process and enhances ease of development, making it more straightforward for developers to transition to the latest version.
Transitioning to Wisej.NET 4 and the .NET Core Designer requires replacing these two classes:
System.Resources.ResourceManager
⇒
Wisej.Resources.ResourceManager
System.ComponentModel.ComponentResourceManager
⇒ Wisej.Resources.ComponentResourceManager
The rationale behind this change is that the implementation of System.Resources.ResourceManager
in .NET loads the specific type specified in the resources file without providing a way to override its behvior. Consequently, when dealing with embedded images, this approach fails on Linux systems without the installation of libgdiplus
, and it is inherently incompatible with iOS and Android devices, resulting in failure on those platforms as well.
Our re-implementation maintains full compatibility with all existing resources and is flexible enough to adapt to the target platform seamlessly. On Windows, it utilizes System.Drawing
(GDI+), while on all other platforms, it leverages our newly developed System.Drawing.Managed
, which is based on ImageSharp.
The new ResourceManager will be included in a future update of Wisej.NET 3.5 to ensure backward compatibility.
Since the .Designer.cs or .Designer.vb file associated with a project's resources is automatically generated by Visual Studio using the ResXFileCodeGenerator
tool, we have replaced it to ensure that the generated code utilizes the updated types introduced with Wisej.NET 4.
If you target only .NET Framework
, these changes don't apply to you.
The Upgrade Tool is designed to automate the migration of .Designer.cs/vb
files by replacing the ResourceManager
references.
The tool applies the following modifications:
ComponentResourceManager
Replaces all references to System.ComponentModel.ComponentResourceManager
to Wisej.Resources.ComponentResourceManager
. These are commonly found nested under the project's .resx files.
ResourceManager
Replaces all references to System.Resources.ResourceManager
to Wisej.Resources.ResourceManager
. These are commonly found in the designer files related to visual components.
Wisej.NET 3.2 adds new enterprise-grade features that simplify the development of complex Line of Business (LOB) cloud applications for the enterprise. Our goal is always to help improve developers productivity and make the applications using Wisej.NET more resilient and maintainable.
The Visual Studio 2019 and 2022 extension packages are linked below:
We added a new Validation property extender to provide a modern, centralized, and flexible validation system to Wisej.NET applications.
Once you drop the new Validation component on a container at design time, all the controls are extended with a new property ValidationRules. You can assign multiple validation rules to any control.
Using the ValidationRules Collection Editor requires the Wisej.NET 3.2 VSIX to be installed within Visual Studio.
With Wisej.NET 3.2 we are introducing a new concept to build views using a JSON representation. In the future we may add XML or any custom parser, and we are also planning to use the new View Builder as an optional serializer in the designer.
Font support has been enhanced in the JavaScript layer as well as the server side .NET layer in Wisej.NET. Now we support using theme fonts that are not installed on the server.
The DevExpress Dashboard is a control that allows developers to create interactive and customizable dashboards for business intelligence (BI) purposes. The platform offers a wide range of data visualization tools and widgets, such as charts, graphs, maps, gauges, and pivot tables.
Added Enable HTTPS option to the new project wizard.
Now projects include the full applicationhost.config
file in /Properties, or in /My Project for VB.NET, preconfigured to listen to https://localhost:44391, for IIS Express and .NET 4.8.
For .NET Core it listens to the same https://localhost:44391 URL and it doesn't need to use applicationhost.config
.
improvements across the board.
Consolidated bug fixes and enhancements to all controls.
DataGridView memory footprint for large data sets has been reduced.
New BindableComponent base class to enable data binding on components.
We added the option to enable the design-time debug mode in the Designer Options dialog. When enabled, Wisej.NET will show the Edge renderer(s) it uses to display each control in the pixel-perfect design view.
The latest Wisej.NET 3.2 is available on . To use the build, make sure to check the Prereleases option in the NuGet Package Manager.
Using this extension requires a .
Expanded Binding and MVVM support to and .
We added a new Validation property extender to provide a modern, centralized, and flexible validation system to Wisej.NET applications.
Once you drop the new Validation component on a container at design time, all the controls are extended with a new property ValidationRules. You can assign multiple validation rules to any control.
There are 7 built-in validation rules:
Required: Validates the presence of any value.
Email: Validates an email entry.
Decimal: Validates a decimal value.
Integer: Validates an integer value.
Currency: Validates a currency value.
Telephone: Validates a phone number using a validation mask.
Regex: Validates any value using a custom regular expression.
Each built-in rule has a set of custom properties in addition to the basic properties inherited from the abstract ValidationRule class.
When design mode, you can add and manage the validation rules using Visual Studio's collection editor; it will automatically load the built-in rules and any custom rule you may have added to your solution.
Once you add validation rules to a control, the Validation component will automatically attach to the control's Validating and Validated events and invoke the rules in sequence. When a rule fails to validate, it will set the InvalidMessage property of the control being validated, and set the e.Cancel property of the event to true.
👉 This is more or less what you do now in code when handling the Validating event. With the difference that now you can reuse the same validation rule for multiple controls in an easy way.
Build your own custom validation rule classes by extending Wisej.Web.ValidationRule. You can add any property and perform any validation procedure required by the application.
Using validation rule classes allows you to implement complex business rules for the validation of user-entered data in a single, reusable, place.
Example of a custom rule to enforce a minimum-age value:
Validation messages are typically displayed in an error tooltip by setting the InvalidMessage property of an editor control. A second way to show validation errors, is to use the ErrorProvider extender. However, an application would have to explicitly set the error message in code when processing the Validating event.
The Validation extender, and each Validation rule, expose the ErrorProvider property (accepting any implementation of the new IErrorProvider interface), allowing the validation system to display the error message anywhere!
On the control itself, the default.
Using the ErrorProvider extender.
On any custom implementation of the new IErrorProvider interface: i.e, a MessageBox, a slide-in Panel, any logger, etc.
We have also added two new interfaces:
IValidation. All controls Controls that support the InvalidMessage property and fire Validating and Validated now implement this interface. (it's similar to the IReadOnly or ILabel interfaces that normalize common features.)
IErrorProvider. Exposes the same two public methods implemented by the existing ErrorProvider component. Allows an application to have full control of where an how to show error information related to data field validation. The Label control now implements IErrorProvider.
Now any class can implement the IErrorProvider interface and be connected to either the Validation component or to any (even multiple) ValidationRule implementation.
The Wisej.Web.Label control implements the IErrorProvider interface and it automatically shows or hides itself when an error message is set or cleard.
The code below shows a simple custom IErrorProvider that collects the errors and displays them in a list, all at once, in a MessageBox.
Validation rules are invoked twice, on Validating and on Validated events. A validation rule implementation may alter the text of a control while it's being validated or after it has been successfully validated.
For example, the built-in CurrencyValidationRule exposes a boolean Format property. When set to true, the rule will format the value of the control, if successfully validated, to display the currency symbol and the correct number of decimals.
The Validation extender exposes the same Validating and Validated events that are available to any control. However, for the Validation extender these events are fired for the controls that have been associated to at least one validation rule.
Your handler code attached to the Validation extender will receive the array with all the validation rules associated with the control being validated. This feature allows an application to perform additional custom validation at the Validation extender level, for all the related controls.
When enabled, Wisej.NET will show the Edge renderer(s) it uses to display each control in the pixel-perfect design view.
You will see one or more small windows that show the renderers managed by the design view. When debugging the client side JavaScript, we recommend setting the Parallel Renderers to 1 - it's much easier to have only one Developer-Tools window open.
Click anywhere on the renderer window and press F12 to open the Developer Tools window.
With the Developer Tools open you can fully debug everything the designer renderer does on the JavaScript side. In Visual Studio you will also see the same debug view displayed in Chrome or Edge when showing the developer tools.
Using this powerful features allows widget developers to debug and test their JavaScript implementation at design time.
On a separate Label (which now implements the IErrorProvider interface). The Label is automatically show or hidden.
Wisej.NET 3.5 adds native support for hybrid applications running on all sorts of devices, including full offline support, and many enhancements to the .NET class library and the corresponding JavaScript widgets.
The latest Wisej.NET 3.5 is available on NuGet.
The Visual Studio 2019 and 2022 extension packages are linked below:
Wisej.NET 3.5 is now compiled against .NET 7. This means that existing .NET 6 projects that would like to use the latest version of 3.5 must update the target framework dependency.
Wisej.NET 3.5 is now able to run on iOS, Android, and MacOS devices using the EmbedIO server in a new Wisej.NET Hybrid shell build using MAUI's native integrations.
Wisej.NET Hybrid includes three new project templates for creating applications:
This project template is used to create a Wisej.NET Hybrid Client. The Client project builds and runs an executable (.exe, .apk, .ipa, etc.) that can be deployed on any desktop or mobile platform.
This template is based on .NET MAUI. You can interact with this project the same way you would with any other MAUI project.
Allows developers to build and deploy a traditional Wisej.NET application with the added ability of interacting with the Hybrid device's native functionalities.
This application is deployed to a remote web server such as IIS, Kestrel, or Nginx on Windows or Linux.
Alternatively, you can add the Wisej-3-Hybrid NuGet package to an existing Wisej.NET project.
To use native device functionalities, you must access this application through the Wisej.NET Hybrid Client Application
Allows developers to build and deploy applications that run entirely on the Hybrid device. The project template contains similar features to the Remote application template such as a Page control.
This project needs to be linked into the Wisej.NET Hybrid Client Application to use.
In 3.5 we also focused on extending the programming side of Wisej.NET with a number of enhancements to the object model, data a binding, the various components.
ListViewItem gained the new Visible property. It allows the application to hide items without having to remove and add them back to the Items collection.
All controls that show a label gained a new AutoToolTip
property. When set to true
and the text is truncated, it will automatically use the title attribute to show the full label as a native tooltip.
The Validation extender now supports the IDataErrorInfo interface and data binding. We also added the Enabled
property to the base ValidationRule class to allow the code to disable a specific validation rule without removing it from the Validation extender.
DataGridView exposes the CreateSummaryRow, CreateDataBoundColumn, and CreateDataGridViewColumnFromType methods as public virtual to allow an application to customize the grid's inner behavior and fully control the automatica creation of rows and columns.
The ErrorProvider extender allows a derived class to override its methods and fires the new ErrorChanged event to allow an application to customize error message and icons in a single location.
TextBox.Text
now converts all \n to \r\n when Multiline
is true
. Previously Wisej.NET allowed the browser to strip \r\n and instead return only \n as a new line.
Most controls have gained several new constructors, some with optional and default arguments, that allow developers to use the controls in code adopting a more flexible and easier syntax:
All basic methods in Control now return this
to allow code to chain calls:
Wisej.NET 3.5 includes a new theme for building dark-style applications. The new Bootstrap Dark theme (BootstrapDark-4) is based on the existing Bootstrap-4 light theme.
The new Chat control can be used to build conversations into an existing Wisej.NET application. The new chat control supports text and custom message types, allowing users to share any type of control or data in the conversation.
The new Signature control can be used to collect and export user signatures. The control includes undo, redo, image import/export, and line customization features.
See documentation: https://docs.wisej.com/extensions/extensions/signature
The new Pull to Refresh component can be used to trigger a refresh of a data source associated with a scrollable panel. All containers inheriting from ScrollablePanel support the Pull-to-Refresh component.
The new TesseractJS component allows developers to add real-time OCR scanning to the Wisej.Web.Ext.Camera control.
The new Dynamsoft Barcode & Scanning premium extension gives developers an enterprise-ready option for barcode scanning and text (OCR) scanning on the web.
Developers are required to purchase the following licenses from Dynamsoft:
Dynamsoft Barcode Reader – JavaScript Web SDK
Dynamsoft Document Normalizer – JavaScript Web SDK
The new Mobiscroll premium extension gives developers a suite of mobile-friendly controls and components to use in Wisej.NET applications.
Developers are required to purchase a license from Mobiscroll for use of any components. The Wisej.NET integration uses the Mobiscroll JavaScript integration.
Yes.
There are two sets of templates available in Wisej.NET 3.
One set of templates uses Wisej.NET 3 with the old template style. This template format allows you to use IIS Express and Local IIS normally.
The templates based on the new SDK-Project format are more complicated.
Running a project in the new SDK Project format that is set to .NET Framework will start with IIS Express. Running a project in this format that targets .NET 6+ will use Kestrel.
No. Wisej.NET 3 was designed for .NET 5+.
Yes.
Yes, but you will lose access to the designer.
All Wisej.NET projects must target .NET Framework v4.8 to use the designer.
Yes but you have to create the docker file. We only provide a basic docker file for Ubuntu.
Yes. We provide a basic docker file for Ubuntu.
Yes, unlike standard ASP.NET Core projects, which have dropped VB.NET, Wisej.NET features VB.NET templates for .NET 6.
We have added a new experimental extension to build all sorts of views using a plain JSON representation. It will eventually allow us to integrate it with the designer and optionally serialize views to JSON or XML rather than code in InitializeComponent.
The Wisej.Web.Ext.ViewBuilder source code is available in our public GitHub extensions repository and on NuGet.
As a simple start, this is what you can do with the ViewBuilder:
In the code above you can see two ways to use the ViewBuilder: as an extension method on any ContainerControl
type (Form, Page, UserControl) to create the child components inside the target control; or as a static method used to create a new view from the model.
You can also see three different input types: Stream, Object, and String:
Stream is any stream that returns a JSON string.
Model is any object of any kind, just like any data object or view model.
String is a JSON string.
In all three cases, the input is an object model that is used to build the view. The code below shows a simple form with a TextBox and a Button:
As you can see in the simple model above, the model is always the same. The representation can be JSON (could be XML or yaml or anything else) or directly a .NET object. These are the most important features to notice:
Lower case field names. The ViewBuilder recognizes lowercase names and resolves them to the correct property. It allows JSON models to follow the JavaScript camel casing convention.
Events are treated like properties. Assigning an handler is the same as calling += or AttachHandler.
Extension properties, like the ToolTip extender", are addressed using the name of the extender component: i.e. "toolTip1.ToolTip". (Note that you don't need to use the ToolTip extender for tooltips, all Wisej.NET controls have the ToolTipText property.)
When declaring a model property, extender properties use the underscore instead of the dot to address the component.
All non-numeric values are in strings. Including Point, Size, Color, Font, etc. The ViewBuilder uses the property's TypeConverter to parse the string.
The object model is simply the same model as the target component, with just one system property: _type
. Use "_type" to define the class of the component to create. It can be a fully qualified type name or a simple name. If it's a single string, Wisej.NET will search in the Wisej.Web.
namespace first.
Collections are assigned as arrays. The ViewBuilder detects what kind of collection is expected on the target and either assigns an array or calls the collection's AddRange method.
Use the components
collection at the root level of the top-level container to add Wisej.NET components and extenders: Animation, ToolTip, ErrorProvider, etc.
The ViewBuilder can also resolve references to other components in the same container by name. If you set a property that expects another component, for example, ContextMenu, or DropDownControl, you can use the name of the component or control in any location of the model.
The ViewBuilder will search for the component or control name at all levels and assign the reference to the property.
Wisej.NET supports the IExtenderProperty system at design time. Now it supports it also in this new ViewBuilder model. There are usually two kinds of extenders: a component and a container.
For example, when you drop a control in a TableLayoutPanel, you will notice that the control has "gained" new properties at design time: Column, Row, RowSpan, ColumnSpan, and others.
The ViewBuilder model fully supports both, extender properties defined by another component and extender properties directly on the container.
In the JSON sample above you can see that button1 sets properties it doesn't have: columnSpan, column and row. These properties are extender properties provided by its TableLayoutContainer.
It also sets two more properties it doesn't have: animation1.name and animation1.event. These properties are provided by the animation1 component declared in the components collection.
Data binding is also fully supported. We used a syntax similar to WPF or MAUI. Any property in the model can be assigned a string that starts with "{Binding"
to become a data-bound property.
The complete syntax is:
"{Binding Name, Source=Source, Format=Format, OnParse=OnParseHandler, OnFormat=OnFormatHandler, SourceUpdateMode=SourceUpdateMode, ControlUpdateMode=ControlUpdateMode}"
Everything is optional except Name.
If the Source is not specified, the current container (this or Me) is assumed to be the source. When the Source is specified, it's also relative to this or Me, unless it's a reference to a component, a BindingSource, for example.
Name
Name of the property in the data source to bind to.
{Binding UserName} {Binding Company.Name}
Source
Reference to the data source. Can be any object in the current context (this) or a component in the components collection.
{Binding Name, Sorce=DataContext} {Binding CompanyName, Source=bindingSource1}
Format
Any standard or custom .NET format string.
{Binding Amount, Format=Total: c}
OnParseHandler
{Binding Location, OnParse=ParseLocation}
OnFormatHandler
{Binding FullName, OnFormat=FullNameFormat}
SourceUpdateMode
{Binding Name, SourceUpdateMode=Never}
ControlUpdateMode
{Binding Name, ControlUpdateMode=Never}
Data binding and parsing is a large and complex system. This is probably one of the areas on the ViewBuilder that will evolve the most in the next builds.
Attach handlers to any event by name. You can refer to static methods using their name or fully qualified type name, or you can attach to local methods simply by name or using this or Me.
Event handlers are resolved through the ViewBuilder.ResolveEventHandler
function , which is overridable. The default resolver looks up the method and returns its MethodInfo object.
You may also create your own, and attach to JavaScript handlers or compile the code on the fly!
Your ResolveEventHandler
implementation (see Custom Resolution) receives the string assigned t the "click" event and it's up to you to return the MethodInfo to attach to the event.
The ViewBuilder class exposes two assignable methods: ResolveReference and ResolveEventHandler:
It's invoked when the ViewBuiler needs to convert a string name to a reference to a component or a control. If you assign your resolver to this method then it's entirely up to your code to resolve those references.
It's invoked when the ViewBuilder needs to convert a string to a MethodInfo reference in order to create a delegate and attach to the event.
If you assign your resolver to this method, then it's entirely up to your code to convert the string to a method. This handler allows you to attach any kind of handler, event one you build on the fly, to any event on any control created by the ViewBuilder.
Font support has been enhanced in the JavaScript layer as well as the server side .NET layer in Wisej.NET 3.2. Now we support using theme fonts that are not installed on the server and can load all the different variations for a font family.
montserrat-bold.ttf
montserrat-bolditalic.ttf
montserrat-italic.ttf
montserrat-regular.ttf
Wisej.NET will load all the montserrat-*.ttf files in a private Montserrat family and use it at runtime for autosizing and layout calculations.
This new feature is particularly useful when deploying to Azure App Services or other providers that don't allow you to install custom fonts on the servers.
Font sources added to a theme now support specifying the font-style and font-weight properties. It allows a font family in the theme to use different sources (woff, woff2, ttf, etc.) for different styles and weights.
Until now Wisej.NET supported only the "normal" source and let the browser render the different styles and weights.
This is the definition in the theme file:
You can also reuse the same .tff files deployed in /Themes/Fonts in the sources for the font definition in the theme or theme mixin.
Beginning with Wisej.NET 3, projects will be able to target multiple frameworks.
net48 must always come first in the csproj file to load the Wisej.NET designer.
You use four preprocessor directives to control conditional compilation:
#if
: Opens a conditional compilation, where code is compiled only if the specified symbol is defined.
#elif
: Closes the preceding conditional compilation and opens a new conditional compilation based on if the specified symbol is defined.
#else
: Closes the preceding conditional compilation and opens a new conditional compilation if the previous specified symbol isn't defined.
#endif
: Closes the preceding conditional compilation.
When the C# compiler finds an #if
directive, followed eventually by an #endif
directive, it compiles the code between the directives only if the specified symbol is defined. Unlike C and C++, you can't assign a numeric value to a symbol. The #if
statement in C# is Boolean and only tests whether the symbol has been defined or not. For example:
Multitargeting will inevitably require the use of conditional compilation and excluding certain source code files from some platforms.
If you combine this technique with partial classes you can build very flexible classes that have code that compiles on different platforms:
Visual Studio will show you which targets apply for each file on a drop down at the top left.
Once your main project targets multiple frameworks, all the projects and the libraries it references must also provide their binaries for multiple targets.
This is all done automatically as long as the referenced projects build the binaries using the standard .NET naming convention, and libraries are added using NuGet packages that provide their binaries for multiple targets.
If you use a package only for .NET 6 or only for .NET 4.8 it will still work but you have to exclude the code in the target framework that cannot use the package.
The Visual Studio designer in Wisej.NET 3 has been upgraded to support Visual Studio 2022. Everything else is unchanged, and it requires the .NET Framework 4.8 target to work with Visual Studio.
Wisej.NET 3 components are available in the toolbox under the "Wisej.NET 3" tab name. Since Wisej.NET 2.5 we have stopped installing components in the toolbox and instead rely on the automatic installation of nuget components.
Unfortunately Visual Studio still doesn't support toolbox icons for nuget components. You can always install a custom tab and drag & drop /net48/Wisej.Framework.dll to the toolbox to see the icons. Don't use "Wisej.NET 3" for the tab name or nuget will replace your toolbox content.
Extensions added to a project using the NuGet Package manager will show up under the "Wisej.NET 3 Extension" tab name.
If the toolbox doesn't show the Wisej.NET tab and tools, make sure that the Automatically Populate Toolbox option is set to true.
A Docker container image is a lightweight, standalone, executable package of software that includes everything needed to run an application: code, runtime, system tools, system libraries and settings.
Using Visual Studio Docker Tools, Wisej.NET 3 applications can be packaged and run in these containers.
When creating a cross-platform Wisej.NET 3 application, Visual Studio will prompt the user to add Docker support to the project.
To run the Wisej.NET application in a Docker container, change the runtime target to Docker.
When building and running a Docker project, the first TargetFramework is always used. If Docker can't run the first TargetFramework, it will target the second or third listed framework.
Docker can build images automatically by reading the instructions from a Dockerfile
. A Dockerfile
is a text document that contains all the commands a user could call on the command line to assemble an image. Using docker build
users can create an automated build that executes several command-line instructions in succession.
Below is a sample Dockerfile configured to run a Wisej.NET 3 application that targets .NET 5.
Be sure to update the Dockerfile if the TargetFramework is not .NET5.0.
Verify the templates are located in
My Documents\Visual Studio 2022\Templates\Project Templates\Visual C#
My Documents\Visual Studio 2022\Templates\Project Templates\Visual Basic
2. Close all instances of Visual Studio.
3. Run devenv /updateconfiguration
as Administrator in the Developer Command Prompt.
4. Reopen Visual Studio.
Ensure that you are targeting the correct framework. This error will occur when net48 is the first-listed framework in TargetFrameworks. Temporarily switch net48 with your Docker runtime target (net5 / net6).
Ensure that you restore net48 to the first listed framework in TargetFrameworks to load the designer.
Ensure that you are targeting the correct framework. This error will occur when an incorrect framework is loaded into the Docker container. Temporarily switch the first-listed TargetFramework with your Docker runtime target (net5 / net6).
Ensure that you restore net48 to the first listed framework in TargetFrameworks to load the designer.
Occasionally when creating a new Wisej.NET 3 project using .NET48 and .NET6+ the designer will not be visible upon project creation. Rebuild the project and then restart Visual Studio.
The most common designer error is "Unable to cast object of type ‘Wisej.Web.Page’ to type ‘Wisej.Core.IWisejControl’ (or another base type).
This issue occurs when trying to loading multiple versions of Wisej.NET into one Visual Studio instance. Visual Studio loads the Wisej.NET designer assembly for the first page that is shown in the designer. If you open a page from a different project using a different version of Wisej, you will get this error.
Simply restart Visual Studio and re-open the new page.
There is no need to change the project format if you are staying with .NET 4.8! Wisej.NET 3 supports both .NET Framework and .NET Core. You only need to change the project format to the SDK format if you are going to use .NET Core and ASP.NET Core.
When migrating a Wisej.NET 2.x project to Wisej.NET 3, it's not recommended to change the existing project but rather create a new Wisej project using the new templates and copy over files.
Moving from older versions of Wisej.NET to Wisej.NET 3 requires updating the project to the new SDK Project format.
Take note of all embedded resources, references and build customizations within the Project.
Unload the Project.
Delete the content of the .csproj file.
Copy the following text into the .csproj file.
5. Reload the Project
6. Add embedded resources, references, and build customizations back.
Files that are Embedded Resources are reset to Content, don't forget to set them again to Embedded Resource.
All the localization .resx files need to be upgraded to Wisej.Framework, Version=3.0.0.0. It's a simple task that can be completed using Visual Studio Search & Replace.
Replace "Wisej.Framework, Version=2.0.0.0" with "Wisej.Framework, Version=3.0.0.0".
A Startup.cs file is required for ASP.NET Core projects (Wisej projects targeting .NET Core).
Right-Click the Project.
Click Add > Class.
Set the name to Startup.cs.
Click Add.
Copy the following content into the Startup.cs file or download the file below.
Don't forget to update the Namespace.
Wisej 3 projects targeted for .NET Core require adding a launchSettings.json file to the /Properties directory of the project.
Right-Click the project on the \Properties folder.
Click Add > New Item > JSON File.
Name the file launchSettings.json.
Copy the following text into the file.
The new SDK project format has many properties that are not available in the project property panel. You have to get used to editing the .csproj or .vbproj files directly.
Unfortunately, there isn't a comprehensive list anywhere and many properties are not standard and depend on build targets. All you can do is search around...
These are just a few that we have added to our templates:
With the release of Wisej.NET 3.0, which is the first version to support both .NET Framework and .NET Core, we have standardized all classes to ensure compatibility across these two environments. This means that any class differences between the two have been reconciled, and unique classes from either environment have been seamlessly integrated.
Originally, the class System.Drawing.Design.UITypeEditor
was utilized. However, because it does not exist in .NET Core, we have reimplemented it as Wisej.Web.UITypeEditor
.
Therefore, attributes that were previously declared as [Editor(typeof(MyEditor), typeof(System.Drawing.Design.UITypeEditor))]
must be updated. You can now specify them as [Editor(typeof(MyEditor), typeof(UITypeEditor))]
or [Editor(typeof(MyEditor), typeof(Wisej.Web.UITypeEditor))]
, depending on the namespaces defined in your using directives.
Previously, all Http*
types were located in the System.Web
namespace. However, in .NET Core, these types differ significantly. To address this, we have reimplemented a unified Http
type system under Wisej.Core.Http*
. This ensures consistency and compatibility when working across different .NET environments.
When transitioning from System.Web
classes, you will likely encounter compilation errors, making it straightforward to identify where these classes are used in your code. Typically, these classes are utilized in the Upload control, within any implementation of the IWisejHandler
interface, and in managing cookies collections. Identifying and updating these areas will be essential to ensure compatibility with the new system.
An event handler for the event.
An event handler for the event.
One of the fields.
One of the fields.
To support private fonts, simply deploy the .ttf files for the fonts used in the theme that are not installed on the server to the /Themes/Fonts folder. For example, in case your application uses the Montserrat font and it's not installed on the server, put the following files in /Themes/Fonts:
To add multiple targets to your Wisej.NET application, ensure the project uses the format and add the following tag.
In our sources we used and conditional property groups in the project file to compile "net48/Test.cs" only on .NET 4.8 and "net6.0/Test.cs" only on .NET 6.
If the \Wisej.NET 3 directory is missing, run the installer again or download the templates from this .
You may also need to clear the .
Wisej.NET 3 introduces a new approach for creating and working with projects based on ASP.NET Core. The changes include a new , Kestrel Web Server, and more.
= false
= true
= false (.NET Framework)
= bin/ (.NET Framework)
Wisej.NET 3 is the first release of Wisej.NET that supports both .NET Framework (4.8) and .NET Core (now .NET 6, will be 7...) and runs on Windows, Linux and MacOS.
Wisej.NET 3 for .NET Framework 4.8 replaces Wisej.NET 2.5 while Wisej.NET 3 for .NET Core 6 is a new build for ASP.NET Core applications that can run on Windows, Linux and MacOS.
Adding support for .NET Core and ASP.NET Core required changes to the HTTP/WebSocket layer and the implementation of a new Wisej.NET Middleware module. Everything else is fundamentally unchanged or enhanced: .NET Controls, JavaScript Widgets, Designer, Themes, Theme Builder.
We have been using Wisej.NET 3 on Linux internally on many test projects and we have run it on several Linux distributions as well as small devices like the Raspberry Pi for over a year. And we are in the process of testing it on even smaller embedded devices running custom Linux builds.
Existing Wisej.NET 2 applications should be able to run on Wisej.NET 3 mostly unchanged. Hopefully, all you need to update is the Visual Studio project format to the new "Sdk" project format.
The designer in Visual Studio is not available for the .NET Core targets and relies on the dual target approach, with the added benefit that Wisej.NET applications can be deployed on .NET Framework 4.8 on Windows and .NET Core on Windows, Linux and MacOS.
New projects can target multiple .NET platforms. When you create a new Wisej.NET 3 project, our wizard will allow you to select the target and enable certain options:
You can edit the .csproj or .vbproj at any time and change the <TargetFrameworks> tag. Just make sure that "net48" is always the first, if you want to use the designer.
Multitargeting will inevitably require the use of conditional compilation and excluding certain source code files from some platforms. In our sources we use conditional properties and partial classes to neatly separate code keeping the same class structure.
Now that Wisej.NET applications can run on .NET 6+ they are standard ASP.NET Core applications. When running on .NET 4.8 they are standard ASP.NET applications.
ASP.NET Core applications don't use System.Web anymore and are not integrated with the IIS pipeline. They are all based on OWIN and Microsoft's Kestrel. Which means that they are almost always self-hosted web applications.
Wisej.NET supported the OWIN middleware approach since 1.5, based on Microsoft's Katana.
This is how you add Wisej.NET to a standard ASP.NET Core application:
All ASP.NET pages and all ASP.NET controls will NOT work on ASP.NET Core.
While the vast majority of the work in Wisej.NET 3 has been to split the code between .NET Core and .NET Framework, replacing all of the ASP.NET code with ASP.NET Core, we have also added some cool new features.
All the Application.Download, and Application.DownloadAndOpen methods have a new optional argument: a callback function, invoked when the file has been downloaded by the client.
This is a powerful new feature that allows an additional level of control that was not possible before.
Wisej.NET supports all sorts of very powerful layouts (impossible to achieve with any other web platform). However, all the layouts are implemented in layout engines and are "permanent": you have to set layout properties for the children and the container manages the layout using the specific layout engine.
If you just need to apply a specific layout, or a combination of layouts, by code, without having to change containers, use the Control.LayoutChildren() methods:
LayoutChildren(controls, dock, viewArea, spacing, useMargins, hAlign, vAlign)
LayoutChildren(controls, direction, viewArea, spacing, useMargins, hAlign, vAlign)
Each method is overloaded with multiple variants and most parameters are optional using predefined values.
Calling LayoutChildren without the controls collection and without the viewArea argument, arranges all the direct children using the control's DisplayRectangle as the bounding area.
Otherwise you can specify only a subset of the child controls and define a view area to limit the layout space. You can also try this new automatic layout functionality at design time using the new AutoLayout Panel.
You can call this method as many times as you need and with as many combinations of rules as you like. It doesn't change the layout engine or the layout options, it only moves and resizes the child controls according to the specified arguments.
We have introduced a new experimental feature to extend the current data binding model to make it compatible with MAUI's Commanding approach. In our implementation, commands work seamlessly with the existing data binding and have access to the full context of the command source. In MAUI the command's code is limited to a single parameter.
In this first implementation, Button and SplitButton have a new Command property and CommandChanged event. The Command property can be data-bound to ICommand properties of the data source.
When ICommand.CanExecute returns false, the command source button automatically disables itself. Clicking the button invokes the method attached to the command.
Use the new Command class or Command<T> class to wrap the implementation of a command and to cast the data item coming from the data source.
This new feature is still experimental and may change in future builds.
Added new interfaces that allow code to use common features across controls:
ILabel. Implemented by all controls that have the Label property.
IImage. Implemented by all controls that have the various Image (ImageIndex, ImageKey, ImageSource) properties.
IReadOnly. Implemented by all controls that have the ReadOnly property.
IModified. Implemented by all controls that have the Modified property.
Using these interfaces eliminates the need to cast a control to the specific class.
Wisej.NET 3 adds a new experimental feature to support the dependency injection model natively.
The Application class now is an IServiceProvider and has two new methods to manage services: AddService and GetService with several overloads.
Using this new feature is quite simple, flexible and very powerful. Use Application.AddService() to register a service and Application.GetService() to retrieve it. Services can be added with several scopes:
Global. Only one instance (singleton) is shared among all sessions.
Session. Each session gets its own instance.
Transient. Each request gets a new instance.
When the services instance passed to AddService is null, Wisej.NET will automatically try to instantiate the service class on first use (on demand). As soon as the service goes out of scope, Wisej.NET will automatically dispose of it. If the service implements the IDisposable interface, it gets a call to IDisposable.Dispose()
A service can also be instantiated on demand in a callback.
Using the service is also quite simple. Regardless of the scope, the service consumer simply calls:
The return is just null if the requested service is unavailable.
Our DataGridView control can handle an unlimited number of rows thanks to its built-in virtual scrolling and page caching on the client side. As the user scrolls the rows, the control manages a client-side cache of pages or rows and requests from the server only the pages that are needed to render the current view.
You can control the size of the client-side cache using the BlockSize and MaxCachedBlocks properties. When the DataGridView is in VirtualMode, it doesn't hold any data and can manage any number of rows with minimal memory usage. Your code provides the data as needed handling the CellValueNeeded and CellValuePushed events.
However, the VirtualMode events are fired every single time the application code uses a cell in the grid (in VirtualMode the grid doesn't hold any data). Usually, implementations of a virtual DataGridView must implement some kind of cache management on the server.
The new DataRead event makes this task a lot easier. It is fired when the client requests a page allowing an application to build and manage a small server-side cache in sync with the client scrolling, resulting in a much simpler usage of the VirtualMode events.
This property has been available as an experimental feature for a while and it's now a supported property. It takes an HTML string and it displays filling the entire grid space when there grid contains no rows.
Shows like this when the grid is empty.
Rolled up all bug fixes.
Layout speed improvements on the client and server.
Refreshed all icons in designer and Theme Builder.
Wisej.NET 3.1 enhances the milestone 3.0 release by adding several new unique features and a simplified installation procedure.
In addition to numerous bug fixes and considerable performance enhancements to our libraries, 3.1 includes the following notable new features:
Wisej.NET is now easier to use than ever before. It is available as a VSIX installer through the Visual Studio Marketplace or via the Visual Studio Extension Manager. Without using the GAC, the new VSIX installer automatically registers Application Templates and the Wisej.NET designer.
A basic but very useful Typed TextBox is one of the most desired features in practically all web development platforms and is now available in our toolkit
You can use this new editor control to define the type of Value property to which the text should be parsed, a.NET format string (standard or custom), and whether the formatted string should be preserved when editing or removed when entering the editor.
You can also take over the parsing and formatting using the new events and virtual methods.
New "Tiny Tool Icons" have been added to the Property Editor in the designer to indicate some of their attributes or reset New their value.
These new icons may save time for developers by providing information and features that needed several clicks to reach.
Reset. Instead of having to right-click and select the Reset option (if enabled), this tiny tool allows developers to reset the value of a modified property with a single click.
Data Bound. Indicates that a property is data-bound. This information was only available by opening the data binding dialog.
Localizable. Indicates that the property can be localized. Previously, this information was unavailable without inspecting the source code or attempting to localize the value.
Responsive. Indicates that the property is a Responsive Property and can hold multiple values associated with client profiles.
The new property ListBox.Orientation changes the layout of the items in the ListBox from the standard Vertical layout to the new Horizontal Flow layout.
Everything else remains the same, including horizontal scrolling, keyboard selection, and so on.
Previously, the data binding system in Wisej.NET only supported the BindingList<> class for advanced data binding. However, MAUI and WPF support the simpler ObservableCollection<> type for their data binding.
Now Wisej.NET seamlessly supports both. Support for the INotifyPropertyChanged is identical in all data binding implementations.
Together with the Commanding support introduced as an experimental feature in 3.0, it now supports most 3-letter or 4-letter binding models.
The Commanding implementation introduced with 3.0 is now fully supported.
Services and Dependency Injection are now first-class citizens in Wisej.NET 3.1.
Using the Visual Studio Marketplace allows us to provide new project and item templates. You can use the Visual Studio Extension Manager to install our new templates and automatically register them within Visual Studio.
We have moved the Tour Panel Extension's Templates to the Marketplace and added new Navigation App Templates similar to the Blazor startup templates.
When Wisej.NET is installed from the VSIX installer (Visual Studio Market Place or downloaded from our builds page), you can press F1 to get directed to our extensive online documentation.
The system can determine the Wisej.NET class, property, or method by the location of the cursor in the editor. This has support for the main API and all the extensions!
We have selected new automation tools as we built our new automated test suite, which we’ve decided to share using TestProject.io, an end-to-end automation solution for Web and Mobile apps with all the latest browser drivers.
Our Wisej.NET extension helps in several ways like scrolling widgets into View, handling Tree Views, Keystrokes, counting Alert or Message Boxes, and much more.
We have added a new module to our open-source toolkit. The new extension employs the Web Authentication API (known as WebAuthn).
The extension enables developers to add external and platform-specific authenticators into Wisej.NET applications. You can read more about the new extension in our blog post here.
This is a new experimental feature. We added a new Application.OpenWindow(url, ...) method with an optional onclose callback action, and added new onclose callback action to the existing Application.Navigate() method.
Application.OpenWindow() opens the url in a new popup window. If you specify the onclose callback method, it is invoked when the user closes the popup window.
It can be used for several purposes:
Dispose a resource (i.e. delete a file or close a handle) when the user closes the tab or the popup.
Simulate detaching a specific window from the browser and allow the web application to work with multiple monitors.
The same effect can be achieve using a browser tab that the user can detach and move to a second monitor.
After launching Visual Studio, click Create a new Project, select your language (either Visual Basic or C#), then select Wisej, and you will see the list of Wisej.NET templates.
After you pick a project type, Visual Studio will create a new solution with the project template you have selected and will start up by showing our welcome page.
And that's pretty much it. Now you can compile the project and open Page1 in the designer.
Pick whatever control you need from the toolbox and you have a web application!
Creates a project containing a custom desktop container. Looks like your Windows desktop. You can add items to the taskbar, show floating windows, change the position of the taskbar, etc.
You are basically building a desktop environment in the browser.
Creates a library project with a custom Wisej.NET control that can be used in other projects.
Creates a web application with a floating window shown in the browser. It's up to you to build a navigation system to manage your application's forms in the browser.
Creates a web application with a main page where you can drop any control. The page fills the browser. You can navigate from page to page simply by creating more pages and calling their Show() method.
Creates a web application with a main page (similar to the Web Page Application). However, it adds the necessary JavaScript and manifest files to make the browser recognize the application as a PWA app.
The app can be installed on the client, and you can control some basic colors and icons in the manifest. Additionally, Wisej.NET creates the client-side web worker that caches locally all the Wisej.NET JavaScript files allowing the app to launch faster.
Upgrading from Wisej.NET 1.X to recent Wisej.NET versions is extremely easy. All you need to do is replace the references and make sure some "using" statements referring to design-time features are updated.
Set target .NET Framework to 4.8
Setting the target .NET Framework to 4.8 is crucial to avoid any issues when installing or compiling your application
Replace project references to Wisej.Web.dll and Wisej.Core.dll with a NuGet Package reference
It's highly recommended that you use the new PackageReference format instead of the old Packages.config file for managing your Packages. Click here for more info.
Replace .resx namespaces to Wisej.Web. and Wisej.Core. with Wisej.Framework. You can do that by doing a mass replacement. From Visual Studio, go to Edit > Find and Replace > Replace in Files or simply use the Ctrl+Shift+H Hotkey.\
Make sure to edit the File types field to only include RESX files.
Change using Wisej.Core.Design to using Wisej.Design using the same process as the previous step, although this time change the File type from RESX files to CS files.
Change calls from ApplicationBase. to Application, again following the same process as the previous step.
Modify Web.config and replace "Wisej.Core" with "Wisej.Framework"
Wisej.NET 3.0 introduced the ability to target .NET 6, with this change came the need to introduce the new SDK Project Format.
If you're aiming to migrate to .NET 6 or newer, click here for more info.
There is no need to change the project format if you are staying with .NET 4.8! Wisej.NET 3 supports both .NET Framework and .NET Core. You only need to change the project format to the SDK format if you are going to use .NET Core and ASP.NET Core.
Starting with Wisej.NET 3.0, we're now shipping the Designer and Templates as VSIX installers. This gives you the ability to manage updates directly from Visual Studio's Extension Manager.
For Wisej.NET 2.X , you can install the designer as its own NuGet Package.
Templates can also be manually installed, click here for more info.
Wisej.NET 2.1 consolidates several new features from 2.0, while adding several new controls (including a powerful new DataRepeater) and reaches a high level of stability.
The new DataRepeater container is a sort of a custom data grid. Instead of rows it repeats a template panel containing child controls in any layout. Child controls are automatically data-bound to the current record.
The infrastructure is virtual, which means that the DataRepeater only creates the visible panels and updates the controls as the user scrolls them into view, allowing the management of an unlimited numbers of records.
It can scroll its items vertically or horizontally, supports touch scrolling, can hide the scrollbar, and it can adapt to the user's device layout. You can use the DataRepeater to build data-bound lists of any kind for mobile or desktop devices.
All editors have a new Label property. It adds a responsive, localizable and themeable label next to the editor.
The Label supports 5 positions: top, left, bottom, right and inside (this is the material style that shrinks the label when there is content).
The size of the inner label and the inner editor can be set to proportional, fixed, or auto-sized. All the properties can automatically change according to the device profile (e.g. the label can be on top for mobile devices, and on the left for the desktop). Supports mnemonics focus, colors, and many other features.
This is a new simple time editor, based on the UpDownBase class.
This is a new editor similar to the existing DomainUpDown and NumericUpDown. Handles a TimeSpan value in different localized formats. Supports minimum and maximum values, it’s bindable, nullable, and supports the quick increase of the time part under the cursor using the arrow keys.
It is an all-purpose shape control that can represent simple shapes with different styles.
Use the Shape control to frame content, including images, and to handle the four borders of a plain DIV tag. It lets you rotate the item, display circles, ovals, rectangles, and triangles using a simple data-bindable all-purpose control.
You can place it behind the controls to frame, or use it as a container and place the controls inside.
This new extender component (drop it on a design surface to use it) adds a new property TabOrder to all containers. If your page or form contains other containers (i.e. Panel, GroupBox) each one can manage the tab order of its children independently.
Supports 3 options: Default, AcrossFirst and DownFirst. Once set, the TabIndex of all the children is set automatically, and it’s updated automatically when adding or removing children.
We have changed all the static events exposed by the Application class to weak events. This new approach (also present in the WPF platform) prevents the source of the static event from holding on the instance handler. It will prevent applications from accidentally leaking memory when attaching to static events exposed by Wisej.
All controls that supports the VirtualScroll mode (TreeView, ComboBox, ListBox, ListView and DataRepeater) now have a new PrefetchItems property allowing the pre-loading of a items outside of the visible area to support smoother scrolling.
This is a new configuration option in Default.json (sessionStorage: "local" | "session", the default is "session"). It allows the Wisej.NET application to select the browser's local storage ("local") to store the session id. When coupled with a longer or unlimited session timeout allows a user to reopen the browser, or the Wisej.NET desktop executable, and find their work exactly where they left it.
This is a new configuration option in Default.json. When set to true, it allows the server application to impersonate the user's Windows credentials on the server (e.g. access the DataBase, the File System, other services, etc.).
We have added a simple new feature to play system and custom sounds.
This new feature allows your application to modify any Wisej.NET theme at runtime by code. You can create themes on the fly for each specific user, or modify the global theme (shared by all users).
Example: Create a new there only for the current user by cloning the current theme and changing the background color of buttons.
Example: Modify the current theme. If it is a shared theme (from the /Themes folder), the change will affect all users.
You may also save the newly created theme to /Themes to make it available to all users through Application.LoadTheme(name).
Wisej.NET 2.0 includes a number of powerful new features that can enhance developers productivity, simplify deployment, customize browser widgets, implement responsive design, and speed up server communications.
The new designer adds custom ruler snap lines that can be user defined and saved with the container.
You can select the glyph color and take screenshots of your screens in design mode.
In addition to the action selector you can now also directly setup anchoring by using the arrow buttons.
You can create an infinite number of vertical or horizontal snap lines for your containers.
Just click on the appropriate ruler position.
Snap lines are saved with each container so they are reloaded the next time you design it.
This new button in the designer toolbar gives you a quick overview and access to all objects.
ResponsiveProperties and corresponding profiles simplify Responsive Design a lot.
Read more: ResponsiveProperties
Wisej.NET now supports many more client-side properties and methods on all controls. It makes it much easier to customize Wisej.NET widgets from server-side code.
AutoShowLoader
Buttons and MenuItems have a new property AutoShowLoader that automatically shows the loader when the widget is clicked - this is a client side event - and removes the loader when the processing on the server is completed.
It is intended to be used on actions that typically require some time to complete and should give the user immediate feedback, i.e. a login button.
CssClass
Sets custom css class names to the widget. You can also manage the css class names using these methods: AddCssClass, HasCssClass, and RemoveCssClass.
States
Sets a custom array of states that can be used in a custom theme or theme mixin. You can also manage the list of states using these methods: AddState, HasState, and RemoveState.
ClientEvents
Collection of client-side events and JavaScriot event handlers that you can set from the server. You can use the collection directly or use these methods now available to all controls: AddClientEventListener, RemoveClientEventListener, and HasClientEventListener.
InitScript
Sets a custom script that Wisej.NET will execute in the context of the widget when it is first created in the browser.
CssStyle
Sets a custom css style string that is assigned to the widget.
Wisej.NET already compresses all traffic packages (HTTP and WebSockets) above a certain threshold by default.
We now switched from GZIP compression to the Brotli compression algorithm.
Our internal tests showed that the compressed response stream is only half the size now.
Read more: about Brotli.
A Wisej.NET server instance can now decide when to refuse a new session when it receives the first request from the load balance, allowing it to move on to the next instance seamlessly.
This new feature allows the Wisej.NET instance to accept only a certain number of sessions, or to check the memory usage and refuse a request when the memory reaches a certain threshold, or it can use an application-provided function that can refuse the initial request for any reason.
See Load Balancing for more information.
Theme Settings
Themes now can contain system and value settings. See Theme Settings.
Stylesheet Rules
Theme designers now can embed custom css rules directly in theme. This new feature allows for fine tuning a theme and for greater design flexibility. See Theme Stylesheet.
Inherited Control
Adds a custom control based on any visual Wisej.NET class. Use it to create you extended controls without having to use the UserControl container.
Custom Loader
Replaces the initial loader with one of the new spinners or a custom spinners of your choice.
Brotli
Adds Brotli compression support to the application.
Healthcheck
Enables enhanced load balancing support in your application. See Load Balancing.
Wisej.NET 2.5 requires .NET Framework 4.8. This is the last supported .NET version from Microsoft. Wisej.NET 3 will target both .NET Framework 4.8 and .NET Core 5, 6, 7, …
Wisej.NET 2.5 can use the latest Edge/Chrome in the designer, introducing the following features:
Multiple parallel rendering engines
Use widgets based on the latest ES6 ECMAScript
Use JavaScript arrow functions
Accurate SVG positioning
Faster rendering
Visual Studio 2022 64bit
Always make sure that you have the latest WebView2 SDK installer from:
Learn more about WebView2 here:
Theme Builder now can use the latest Edge/Chrome browser to show the preview controls and to run your applications while working on the theme.
As an added bonus, now you can detach the browser tab and work with your application running on a separate window while working on the theme at the same time!
This powerful addition allows you to aggregate and style rows using the standard functions or any custom formula you may need in your code. Aggregated rows are added either above the group, below the group, or can become parent rows in a hierarchical structure.
Wisej.NET 2.5 consolidates several enhancements and bug fixes:
JavaScript Optimization. We have removed all the JavaScript code that could cause the V8 engine to recompile a class improving client side speed.
CharacterCasing Property. All controls that show a text (i.e. Label, Button, MenuItem, ...) have a new CharacterCasing property allowing an app to change the case if the text without having to alter the code.
Design Rendering speed. Several improvements and the new parallel renderers improve the designer experience.
New Bootstrap Theme. We have added a new bootstrap theme and the full bootstrap icon-set in a new Wisej.NET Icon Pack.
This is a major change in the way we deploy Wisej.NET and it prepares for the next major Wisej.NET 3 release with support for dual framework targeting and .NET 6+.
Wisej.Framework.dll will be installed in a local NuGet repository at %ProgramFiles%/IceTeaGroup/Wisej.NET 2.5/nuget as a NuGet package named "Wisej.NET Local". It will not be copied to $ProgramFiles%/IceTeaGroup/Wisej.NET 2.5/bin anymore.
This change will allow developers to switch to any Wisej.NET version without having to run the installer again, or uninstalling and reinstalling. Simply open the NuGet Package Manager and select either "Wisej.NET Local" or nuget.org and filter for "Wisej-2".
All the extensions will only be available at NuGet.org.
In order to use the new <PackageReference> syntax in your .csproj or .vbproj project files, instead of the old Packages.config file, make sure this option in Visual Studio is set to PackageReference:
Starting with Wisej.NET 2.5 you will not find the Wisej.NET components in the toolbox in Visual Studio like before. We have stopped installing the toolbox and instead rely on NuGet and Visual Studio automatic population of the toolbox.
Make sure that your Visual Studio has the "Automatically Populate Toolbox" feature turned on.
This change eliminates the common problem of the Wisej.NET toolbox disappearing, allows us to add Wisej.NET to multiple version of Visual Studio installed on the same machine, and gives us the flexibility to add and publish extensions more frequently.
A downside is that Microsoft still doesn't support toolbox icons for NuGet packages. If you really want to add Wisej.NET Components with their icon to the toolbox, follow these steps:
Add a new tab to the toolbox and name it "Wisej" (don't name it Wisej.NET 2.5 or it will be replaced by the NuGet Package).
Locate the Wisej.Framework.dll (or extension dll) and simply drag & drop it on the new toolbox tab.
Wisej.NET is not limited to C# or VB.NET! We have tested it with other .NET languages and made sure it works also with COBOL, x# (CLIPPER, dBase, Vulcan.NET) and F#.
MicroFocus VisualCOBOL, NetCOBOL, Raincode COBOL can build single-page web apps with Wisej!
CLIPPER, dBase, Vulcan.NET, XSharp can build single-page web apps with Wisej!
Wisej.NET Visual Studio Templates
You can find Visual Studio templates for previous versions of Wisej.NET below:
For each of the below downloads, unblock the zip (this is important!) and expand into:
Documents\Visual Studio (2019|2022)\Templates\ProjectTemplates\Visual C#
Documents\Visual Studio (2019|2022)\Templates\ProjectTemplates\Visual Basic
Wisej.NET applications typically have a single application in the broad sense. For clarity:
"Sub-application" refers to an application in the strict sense
Each Wisej.NET project requires at least one default sub-application
A new Wisej.NET project creates three startup files:
Default.html
Default.json
Program.cs
Default.html
maintains ASP.NET convention for startup pages.
Program.cs
contains the static
(Shared
in VB) Main
method.
The .html
and .json
filenames should match for simplicity but this isn't required.
Create sub-applications in the project's root or any project folder:
Right-click project/folder → Add → New Item
Select Wisej on left side
Click Application in list
Set application Name
Click Add
Example with name "Admin" creates:
Admin.html
Admin.json
Admin.cs
The Admin.cs
file mirrors Program.cs
:
Wisej.NET sub-applications start with the .json
file, not the .html
file. Even when accessing a URL with .html
, Wisej.NET looks for the corresponding .json
file (rules explained below).
For the "Admin" example, Admin.json
contains:
This file provides two key pieces of information:
url
- Which .html
file to display in browser
startup
- Which server-side method to execute
When accessing http://myApp.com/Admin
, Wisej.NET:
Locates Admin.json
Reads the url
key and loads Admin.html
Invokes the startup method specified in Admin.json
Wisej.NET needs the server-side startup method - in this case [ProjectName].Project.Main
in assembly [ProjectName]
.
To instantiate an AdminPage
instead of executing Main
, modify Default.json
:
The Wisej.NET startup process follows these steps:
Locate .json
file
Direct browser to load/display the url
HTML file
Execute server-side action based on .json
file:
Run the startup
method, or
Instantiate the mainWindow
view
Replace Extension with .json
For URLs ending with an extension (e.g., http://myserver.com/Startup.php
)
Wisej.NET looks for matching .json
file (\Startup.json
)
If .json
not found and Wisej.NET loaded, wisej.wx
reloads current page
Append Default.json to Folder Path
For folder URLs:
Root folder (http://myserver.com
) → \Default.json
Folder path (http://myserver.com/Suppliers/
) → \Suppliers\Default.json
Handle URLs Without Extensions
For URLs like http://myserver.com/Customers
, Wisej.NET:
Tries \Customers.json
If not found, treats "Customers" as folder and tries \Customers\Default.json
The Web.config
file in Wisej.NET project templates includes:
This defaultDocument
setting isn't required because:
Website root URLs are treated as folder paths
Wisej.NET automatically looks for \Default.json
in the project root
Rule 2 above handles folder path resolution
There are several different licenses:
Developer
One developer license is required for each developer using Wisej.NET.
Server
One server license is required for each server running Wisej.NET applications.
Community
One license is required for each developer or each server using Wisej.NET.
Trial
The trial license works for both: developer and server activations.
Wisej.NET will ask you to enter the developer (or trial) license key the first time you open a window in the designer.
Enter the Developer License Key or the Trial License Key and click the ACTIVATE button.
If you already have a Trial License and want to register the Developer License, open the Registration form by clicking on the small Wisej.NET icon in the designer's toolbar (all the way to the right) at the bottom. It will reopen the registration window where you can enter the new license.
The web server must have write permissions to the project directory or to "C:\ProgramData" to be able to properly activate the license and generate the wisej-server.lic file.
Wisej.NET saves a copy of the activated server license into the project's folder and to "C:\ProgramData\IceTeaGroup\Wisej".
When you create a new Application Pool or change the user for an existing Application Pool, make sure that the account you have selected has write permissions to the project directory and optionally to "C:\ProgramData".
Usually, the user is "IIS_IUSRS".
You don't need to do anything else. There is no need to re-register or to change the license key in Web.config.
Here are some common issues that users encounter:
Make sure that the key you enter into web.config is a server license, not a developer license.
If you run into this issue, rebuild your project.
A new PWA project template includes a set of professionally-designed offline pages end the required manifest file. The worker process script is embedded in the Wisej.NET loader. Wisej.NET will automatically pre-cache locally all the resources and offline pages. Enable PWA support in Default.json by setting enablePWA: true.
The improved offline detection process automatically switches to the offline pages when it detects a disconnection and restores the application when the connection is restored.
A new event Application.BeforeInstallPrompt allows the application to detect when it can be installed as a PWA, and a new client-side method Wisej.showPWAPrompt() displays the browser's PWA installation prompt. Using the Application.BeforeInstallPrompt event allows the application to display a custom notification to the user (the browser's default PWA notification is just a tiny + symbol in the address bar.)
Additionally, the application can attach a client side event to a button or an icon to show the PWA installation prompt when the user clicks the control.
When the application goes offline, Wisej.NET loads the /Offline/Default.html page. The image below is one of the pages included with the project template. However, you can put an entire JavaScript application inside the /Offline folder. Wisej.NET will pre-cache locally all the files at all level.
Wisej.NET will switch back to the application as soon as it detects that the connection is restored. Unless the session expired, the entire previous state is reloaded and the user is able to keep working from where the disconnection occurred.
Our integration packages create a hybrid application, where the Wisej.NET web application is able to interact with all native-only features of the mobile device.
The Wisej.NET app can: show native alerts, use the camera, use the microphone, use the GPS, read the magnetometer read the gyroscope, read the accelerometer, play sounds, switch the flashlight, push notifications, read and write NFC chips, authenticate using TouchID or FaceID, create a native Toolbar, create a native TabBar, manage the StatusBar, read all the device information, handle multiple screens, lock the screen orientation, manage the screen brightness, brew coffee, and more…
For example, this is all the code you need to authenticate a user using FaceID in C# or VB.NET from the server side.
A Wisej.NET hybrid application can also push notifications, read any property of the device, store files locally, and manage a native toolbar, a tabbar, the status bar, and all the available sensors through the Device object.
Wisej.NET 2.2 also greatly improves virtual scrolling and touch integration.
There are two important enhancements in the Wisej.Web.DataGridView control:
Starting from Wisej.NET 2.2, the DataGridView doesn't create any row when the grid is data-bound or running with VirtualMode set to true. It instead gets the values directly from the data source or the CellValueNeeded event when virtual.
As the code requests rows, the framework converts virtual rows into real rows transparently. However, if the application is changed to use dataGrid.GetValue(col, row ) and dataGrid.SetValue(col, row, value) instead of addressing the cells directly, it will read and save from/to the data source and will not create any row.
Now the DataGridView supports all the standard selection modes (CellSelect, FullRowSelect, FullColumnSelect, RowHeaderSelect, NoSelection) and adds a new mode: RowColumnHeaderSelect.
You can use the SelectedCells, SelectedRows and SelectedColumns collection to read the selected objects.
Unlike the MessageBox and AlertBox, which are static classes, the Toast is a component that you create and can hold on to in your application. You can reuse it and you can update the content while the Toast is visible.
It can be located in any of the 9 standard locations. By default it appears at the TopCenter location. It contains an icon and a text that can display any HTML content (by setting the AllowHtml property to true).
Toasts auto close by default after 5 seconds but they do not auto dispose. To auto dispose a toast instance when it's closed, set the AutoDispose property to true. You can detect when the user clicks on a Toast by handling the Click event, and handle the Close event to run code when the Toast is closed.Populate a ComboBox without keeping the binding link with the data source.
Now the DataRepeater supports items of variable height (when in vertical mode) and width (when in horizontal mode). It can auto size the child items to fit the content, or you can set the size of each item programmatically.
Additionally, the virtual scrolling, mobile scrolling, and prefetching have been improved considerably. The DataRepeater can now handle unlimited items seamlessly without a glitch.
All controls that support data binding have been improved with two new methods:
Fill
Populates the control from a data source object without keeping the control linked to the data source.
Append
Appends the data source object to a previously populated control without keeping the control linked to the data source.
These new methods allow a control to retrieve the data from the data source without keeping the bidirectional binding link. All the properties that specify the fields to bind to are still used, making the population of list controls much easier.
Wisej.NET 2.2 also adds full data binding support to the ListView control, including support for the new Fill and Append methods.
The new ListView control supports the following data binding properties:
DataSource
Returns or sets the data source for the ListView control.
DataMember
Returns or sets the name of the list or table in the data source for which the ListView is displaying data.
ColumnHeader.DisplayPropertyName
Returns or sets the property to display in the ListView items.
ListViewItem.DataBoundItem
Returns the data-bound object for the ListViewItem.
You must buy a license directly from the vendor of the widget library. Wisej.NET doesn't include any free license!
The ComboBox and the ListBox control have a new LazyLoading property, similar to the existing TreeNode.LazyLoading.
When LazyLoading is set to true, the list items (or child nodes in a TreeNode) are sent to the client the first time the ComboBox is dropped down, or when the ListBox "appears" on the client browser. It reduces the size of the data sent to the browser when creating a page and speeds up the initial loading of pages and windows.
All controls in Wisej.NET 2.2 have some enhancement:
Control.ToolTipText
All controls have a new ToolTipText property. It allows an application to set the tooltip text on any control without having to add the Wisej.Web.ToolTip provider.
However, if the application needs to modify some additional aspects of tooltips, it should still use the Wisej.Web.ToolTip provider which exposes the additional tooltip properties.
PictureBox.Filter
TabControl.ScrollStep
Sets the number of pixels to scroll when the scroll buttons are pressed to bring a tab into view.
ListBox.IncrementalSelection
When true (default) the ListBox caches keystrokes for less than a second allowing a user to type and incrementally select the list items, i.e. typing "ab" selects the first item that start with "ab". When false, typing "ab" will select the first item that starts with "b".
TextBoxBase.SelectOnEnter, ComboBox.SelectOnEnter, DateTimePicker.SelectOnEnter, UpDownBase.SelectOnEnter
When SelectOnEnter is true, the entire content in the editable area is always selected when the control gains the focus.
TreeView.RighClickSelection, ListBox.RightClickSelection
When true, right clicking a TreeNode or a ListBox item (i.e. to show a ContextMenu) will select the item.
TagTextBox.KeepWatermark
When true, the TagTextBox keeps showing the Watermark text in the editable portion of the control after the tags.
DataGridView.SelectionDelay
When set to a value greater than 0 (the default), the grid waits the specified number of milliseconds before notifying the server that the selected element has been changed using the keyboard.
This property prevents the server from being flooded with row selection events when a user rapidly navigates and selects different rows using the up/down keys.
FileDialog.LoadPath, FolderBrowserDialog.LoadPath
The file and folder dialogs expose a new LoadPath event. It is fired for each file and each folder loaded by the dialogs. An application can handle this event and set the icon to display, the size, and the dates related to the file or folder. The event is cancelable, allowing the handler to set e.Cancel to true to filter out specific files or folders from the list.
Application.SetSessionTImeout
Changes the session timeout for the current session only.
The Application object exposes two new global events:
ActiveWindowChanged
This event is fired when the active floating window changes. Allows an application to react to the change of the active window globally.
FocusedControlChanged
This even is fired when the focused control changes, regardless of where it's located. Allows an application to process changes to the currently focused control.
There are two new settings that are supported in the Default.json configuration file:
threadPool
enablePWA
Enables PWA support. When set to true, the Wisej.NET bootstrapper will include the built-in service worker. It will preload and cache locally the Wisej.NET libraries and all the assets found in the /Offline directory.
Wisej.NET applications are standard Web Projects in Visual Studio. All standard Web.config
settings remain valid.
In addition to Web.config
, Wisej.NET applications use individual JSON configuration files. A single project can define multiple Wisej.NET applications with one configuration file for each.
Wisej.LicenseKey
The server license key required to activate the server. Located under appSettings
.
Wisej.DefaultTheme
The default theme name (without extension: e.g. Blue-1) used by the Wisej.NET Designer and all project applications. Each application can override this in its JSON configuration file. Located under appSettings
.
<compilation debug="true" targetFramework="4.8">
Wisej.NET reads the "debug" value to determine javascript library minification. When debug is false
, Wisej.NET automatically bundles and minifies all required javascript libraries, including core libraries, extension libraries, and custom application libraries.
Wisej.NET requires the module and handler settings in Web.config
. We recommend increasing allowed content size to maximum:
All default Wisej.NET settings are predefined in the Web.config
file added by Wisej.NET project templates.
Each Wisej.NET application defines its configuration using JSON format. The default application uses Default.json
.
Configuration settings explained:
startup
Full name of the startup static method. Example: "MyApp.Program.Main, MyApp". Wisej.NET calls this when creating a new session. Define either a simple method without arguments or one with a single NameValueCollection
argument to receive URL arguments. Optional - you can use mainWindow
instead. If defined, you must create a component to show the user in the Main method: a main page, desktop, or window.
mainWindow
Full name of a view (Page or Form) created at startup. Example: "MyApp.MainView, MyApp". Wisej.NET automatically loads, creates, and shows the window class - either a Wisej.Web.Form
or Wisej.Web.Page
.
If both startup
and mainWindow
are specified, Wisej.NET creates the main window and calls the startup method.
theme
Theme name to load at startup (without extension). Optional - overrides the Web.config
theme setting at runtime.
url
The application's page URL. Optional - if omitted, users must type the page URL (e.g., http://server.com/admin.html), unless using Default.html with defaultDocument
in Web.config
.
When specified, users can type the application name without extension (e.g., http://server.com/admin).
allowedRoutes
Defines URL routes separated by semicolons. Example: "api;admin;query/users".
When specified, the application processes the main URL and child paths starting with specified routes. URL changes trigger the Application.ApplicationRefresh
event. Check current URL using Application.Url
.
allowedRoutes has a known issue with applications having a "." in the project or solution name.
debug
Enables logging to client browser console. Default: false
. When enabled, Wisej.NET logs events in the browser's console.
culture
Application's default culture. Default: "auto" (detects browser culture).
rightToLeft
sessionTimeout
Session timeout in seconds. Default: 120. Minimum: 60.
Time without user activity before firing Application.SessionTimeout
. If unhandled, shows built-in timeout countdown window.
Note: Session expiration occurs either when the timeout window completes or after twice the sessionTimeout
value (minimum 60 seconds).
Handle Application.SessionTimeout
with e.Handled = true
to prevent expiration. Use Application.Exit()
to terminate manually.
Application.ApplicationExit
is the only event fired on session expiration - this is unrecoverable as the session is already terminated.
sessionStorage
Session ID storage location: "local" (localStorage
) or "session" (sessionStorage
). Default: "session".
"session": Clears when browser closes, abandoning user session
"local": Persists in browser storage, attempts session restoration on browser reopen
"local" storage limits browser to 1 session, sharing across tabs/windows. Wisej.NET refreshes tabs on activation to ensure latest state.
responseTimeout
Wisej.NET ajax request timeout in seconds. Default: 300. Minimum: 300.
Increase for applications with long-running task responses to prevent timeouts.
pollingInterval
Automatic polling interval in milliseconds. Default: 0 (disabled). Minimum: 1000.
Ignored with WebSocket connections. Use Application.StartPolling
and Application.EndPolling
for manual polling control.
autoReload
Automatically reloads application on session expiration or Application.Exit()
. Default: false
.
secure
Forces SSL usage. Default: false
. Changes HTTP to HTTPS and WebSocket to WSS protocol.
impersonate
Enables automatic user identity impersonation at request start. Default: false
.
Use with <authentication mode="Windows">
for user credential resource access.
showLoader
Controls Wisej.NET ajax loader display. Default: true
. When false
, shows HTML content during library loading.
loaderTimeout
Ajax loader appearance delay in milliseconds. Default: 5000. Set 0 to disable.
notAvailableUrl
URL for page shown when server cannot create new session. Default: "resource.wx/NotAvailable.html,Wisej.Core".
Wisej.NET checks maxSessions
value and license concurrent user limits.
notSupportedUrl
URL for page shown when browser is unsupported. Default: "resource.wx/NotSupported.html,Wisej.Core".
Wisej.NET verifies XMLHttpRequest
support and custom checks via browserCheck
.
browserCheck
Custom javascript expression returning true
for supported browsers. Example:
enableWebSocket
Enables WebSocket connections when supported. Default: true
.
webSocketCompressionThreshold
Since 3.5.5
Response size (bytes) triggering server-side compression. Default: 2048. Use -1 to disable, 0 to always compress.
maxSessions
Maximum concurrent active sessions before redirecting to notAvailableUrl
. Default: -1 (unlimited).
maxModalStack
Maximum nested modal states (dialogs/message boxes). Default: 10.
validateClient
Enables client request validation using browser's unique client ID. Default: true
. Helps prevent session hijacking.
validateResources
Since 3.5.5
Validates image, download, and resource requests. Default: false
. Blocks non-browser requests.
When validateResources
is true
, non-browser requests receive 404 response. External viewers/processors (e.g., Google Doc PDF Viewer) will not work.
dropDuplicateClicks
Drops "execute" client events during pending requests. Default: false
. Prevents multiple executions from rapid clicking while maintaining other pointer events.
disableClientObjectModel
enablePWA
Includes built-in worker process javascript in initial loader. Default: false
. Preloads/caches Wisej.NET core scripts and \Offline folder files.
Use PWA Application template with manifest.json
or add it to enable PWA support.
offlineUrl
Navigation URL on connection failure. Default: "". Set to "Offline/Default.html" with enablePWA
for cached offline pages.
threadPool
Configures thread pool without machine.config
changes. Format: {minWorkerThreads, minCompletionPortThreads, maxWorkerThreads, maxCompletionPortThreads}. Uses system defaults for omitted values.
embeddedResourcesCacheControl
Since 2.5.23
Cache-Control for embedded resources. Default: "browser" (1-month browser cache). Options:
options
settings
Custom application settings map. Example: {jquery: "http://cdn...", rootPath: "c:\users..."}. Access via Application.Configuration.Settings
.
Additional Wisej.NET applications use their own configuration files named [ApplicationName].json
, using the same settings described above.
In case Visual Studio decides not to show the new templates try this:
For Visual Studio 2017 and 2019, open the VS command line and run:
For Visual Studio 2022, open the VS command line and run:
Documents\Visual Studio (2019|2022)\Templates\ProjectTemplates\Visual C#
Documents\Visual Studio (2019|2022)\Templates\ProjectTemplates\Visual Basic
Starting with Wisej.NET 3.0, we took the approach of distributing the Designer and the templates in a Visual Studio Extension installer (.vsix).
The path to the templates can vary from one machine to another:
%LOCALAPPDATA%\Microsoft\VisualStudio\17.0_{id}\Extensions\{extension_id}
As an example, it can be something like this:
%LOCALAPPDATA%\Microsoft\VisualStudio\17.0_315d49d1\Extensions\x2rkvlci.xbt
If multiple developers use the same machine, installing a VSIX package can become a challenge. To manage this efficiently, you might need to manually install the VSIX package using the Visual Studio Developer Command Prompt. This method ensures that the extension is accessible to all users on the system. You can achieve this by executing the command VSIXInstaller /admin path_to_the_vsix.vsix
. This command runs the installer with administrative privileges, making sure the extension is deployed globally rather than limited to a single user profile.
With Wisej.NET 4, developers have access to two distinct designers: one for the .NET Framework (net48) and another for .NET Core (.NET 8.0-windows and later versions).
The designer for the .NET Framework is included in the VSIX installer, which also provides various templates and other Visual Studio add-ons. In contrast, the designer for .NET Core is distributed and updated through the NuGet package that includes Wisej.NET itself.
We also provide the templates to download as another option:
Unblock the zip (this is important!) and expand into:
Documents\Visual Studio (2019|2022)\Templates
Select to overwrite existing files when asked. The zip archives contain the \ItemTemplates and \ProjectTemplates files in the same structure expected by Visual Studio.
Templates will not show up when starting a Visual Studio Experimental Instance.
Occasionally you may start getting designer errors when opening a container in design mode. The most common error is "Unable to cast type..." It's a well-known issue related to Visual Studio having to load a shadow copy of the assemblies used at design time.
Since assemblies cannot be unloaded in .NET Framework, Visual Studio loads shadow copies of the assemblies loaded by the designer. Sometimes it ends up loading the same assembly multiple times, leading to the "Unable to cast" error because the same type is loaded more than once.
The WebView2 component can be silently updated by Microsoft, these updates can eventually break Wisej.NET's Edge-based renderer.
The current workaround for this type of issue is to switch back to the Internet Explorer renderer, this allows you to use the designer with little to no issues, one side effect would be the use of some complex JavaScript components that don't usually work with IE.
Usually, it's enough to:
Close all designer tabs
Close all Visual Studio instances
Delete /bin, /obj, /.vs
Open Visual Studio and reload the solution
Recompile
Visual Studio makes shadow copies of the assemblies loaded by the designer here:
%LOCALAPPDATA%\Microsoft\VisualStudio{version}\Designer\ShadowCache
Each installation of Visual Studio has a different unique ID. Visual Studio 2019 versions start with "16.0" and Visual Studio 2022 versions start with "17.0".
Developer and Server licenses include one year of free upgrades. You can renew it after the year expired.
While you can of course continue to use the same version for an unlimited time, you need to renew your license in case you want to upgrade to a later (after expiration) or the latest version.
We offer consulting packages which can be purchased and used to provide training on best practices, code evaluations, and more.
Katalon Studio for automation testing in the browser. Any standard .NET testing framework for the server.
Yes, we help you and your developers design and build a stunning new User Interface while keeping most of your application intact.
For the first steps, we need a couple of screenshots of your application. We will deliver a style proposal and show you what your application can look like.
No.
Yes. You know all the internals of your application. We provide data sheets, the UI mockup, assets, support, theme files, etc.
Yes.
Depends. Varies from little to very little. Especially after you see what your app can really look like.
Using a third party web widget in your Wisej.NET application and wiring the properties, methods and events in a neatly built .NET class.
There is virtually no limit to what can be integrated with Wisej. We can check rather quickly once you send us the link to whatever components you’d like to use.
Yes. We have several blogs showing the integration of popular widgets from DevExpress, SyncFusion, Telerik and others.
Hit Run.
This is the recommended project template.
Wisej.NET 2.5 improves the designer experience using the new Edge/Chrome engine to render the pages at design time in Visual Studio, simplifies the deployment of the growing list of Wisej.NET Extensions, and completes the control with powerful new features.
Wisej.NET 2.5 is deployed as a local and online NuGet. It will not be in the /bin folder in Program Files anymore. See .
The control now integrates and expands the SummaryRows extensions, and fully implements the frozen rows feature.
Finally the supports frozen rows, including frozen cells spanning multiple rows.
Wisej.NET 2.5 adds support for frozen rows at the top of the DataGridView, including support for and to allow a cell to display its content across rows and columns.
Make sure your Visual Studio is configured to use the latest NuGet syntax in .csproj or .vbproj. See .
To add an extension simply select the package and it will be automatically downloaded and installed on your development machine. All it's components will also be automatically added to the .
Use .aspx files for pre-load .NET code execution (see )
For more information about Wisej.NET licenses, see the handbook.
The Server License Key (or Trial Key) goes into Web.config. See . You can change it at any time. Wisej.NET will automatically activate a new license when the application is loaded.
Wisej.NET detects when a license has expired and the application is using a newer build of Wisej.NET. When this occurs, the license manager automatically downloads the new license, provided you have renewed the upgrade period on .
You may run into this issue if you have an old server license that is no longer working. The community license is deprecated. You will need a server express license instead, which you can get here: . Simply click on "get it now" under the "express" column. You will be taken to a checkout page with the free license. Complete the checkout.
The minimum version for the Server Express license is Wisej.NET 3.5.6.9. If you attempt to use a Server Express license with an older version of Wisej.NET, you will get an error message that says "Invalid Server License". To fix this error, you will need to update the Wisej.NET nuget package. You will also need to update the Visual Studio Extension (VSIX) for Wisej.NET, which can be downloaded here: . Make sure to rebuild your project once you have the new version of Wisej.NET installed.
Licenses can be viewed by going to the WIsej.NET website () clicking on "Support" in the upper right hand corner and then "Account".
Wisej.NET 2.2 introduces built-in PWA support, dynamic integration with all major JavaScript vendors, native iOS and Android integration (available for ), enhancements to all controls, improved memory management, and lots of new functionality across the board.
Progressive Web Application () support is now built-in into Wisej. It allows a Wisej.NET application to be installed in the desktop or a mobile device along with the locally cached libraries and offline pages.
At this time it appears that only Chrome fires the event.
Currently the native integration packages for iOS (Xcode) and Android (Android Studio) are available for free only to . However, we are planning to add new license options to Wisej.NET to make these packages available without having to sign up for the Technology Partner program.
See for a description of each selection mode.
Wisej.NET 2.2 includes a new and lighter notification control: .
All the premium integration libraries are now free. Each library is a GitHub ongoing project. The libraries for Wisej.NET 2.1 include some extra dynamic code that is not built-in the class in Wisej.NET 2.2.
The class exposes a new property. It's a dynamic object that is able to convert any method call into a JavaScript call on the third-party widget and can attach custom event handler to events fired by the implementation.
Sets a on the PictureBox image.
ThreadPool is a map defined as {minWorkerThreads, minCompletionPortThreads, maxWorkedThreads, maxCompletionPortThreads} that corresponds to the system's ThreadPool settings that can be applied by code or in machine.config. See . All properties are optionals. A typical settings is "threadPool":{minWorkerThreads: 100}.
Beyond the standard settings handled by IIS, Wisej.NET supports:
Specify a to override browser/OS settings.
Controls Right to Left mode. Default: "auto". Set true
to force RTL mode, "auto" to detect from current culture. See .
Prevents creation of for named controls. Default: false
.
When unset, shows localizable "Offline" toast on connection loss. See .
"server": Server-side caching
Custom string (e.g., "private, max-age=600")
Platform-specific options map. Example: {debug: true, nativeScrollBars: true}. Recognized by client-side framework.
If it still doesn't work, check if the \Wisej.NET 2 or \Wisej.NET 3 templates are present on your development machine under your user name here:
Run the >devenv command above again.
If it still doesn't work, delete the Visual Studio templates cache. Each installation of Visual Studio has a different unique ID. Visual Studio 2019 versions start with "16.0" and Visual Studio 2022 versions start with "17.0".
Run the >devenv command above again.
In case you encountered this issue, please post in our , or contact us via email.
We're constantly updating the Designer component, please make sure to follow the forum for any , usually, those posts would contain links to newer releases of the Wisej.NET Designer.
If you still get the problem, try to clean the designer assembly cache and repeat the steps above.
Reopen Visual Studio, recompile again and the problem should be solved.
Wisej.NET is licensed per Developer and per Server. There are different license types available: Developer, Server, Mobile Packages, and options for Technology Partners. You can get a first impression with the Wisej.NET Trial license or use the free Wisej.NET Community license. .
Yes, we offer volume licensing including single key deployment through our .
Yes, it's available as an additional option to our .
Yes, it's available at .
Yes, it's available as an additional option to our .
Yes, you can find more information about training options here: .
Yes, there are a number of options available. See for more details.
Check out our and open-source .
Syncfusion
DevExtreme
Telerik
Infragistics
Wisej.NET recognizes embedded JavaScript files (.js
), style sheet files (.css
) and theme files (.theme
and .mixin.theme
).
You can use any embedded resource in your application and manage them as you would in any standard .NET application. This section covers the types and locations of resources that Wisej.NET detects and manages.
To use embedded resources in Wisej.NET, add the [assembly:WisejResources]
attribute to your assembly in AssemblyInfo.cs
.
The attribute takes two optional parameters:
A list of excluded resource names
The root name of resources when different from the default namespace
Only *.js
and *.css
files in these two folders are recognized by Wisej.NET and bundled in wisej.cs
and wisej.css
. To include a resource with [assembly:WisejResources]
without bundling, place it in a different folder.
For VB.NET developers: The VB.NET compiler builds embedded resource names differently. It uses only the project's default namespace + file name, ignoring folder names. Resources in \Resources
or \Platform
won't be recognized when compiling with VB.NET.
To use these folders in VB.NET, rename your files like this:
\Resources\my-code-to-bundle.js
→ \Resources\Resources.my-code-to-bundle.js
\Platform\my-code-to-bundle.js
→ \Platform\Platform.my-code-to-bundle.js
In release mode (debug flag off in Web.config), Wisej.NET automatically bundles and minifies all embedded .js
and .css
files from \Resources
and \Platform
.
JavaScript files are bundled in wisej.js
. StyleSheet files are bundled in wisej.css
.
The \Themes
folder has special handling:
Embedded themes/mixins in the main assembly load without [assembly:WisejResources]
Themes/mixins in other assemblies need [assembly:WisejResources]
to load
Deployed theme files override embedded ones with the same name
Use embedded resources from any assembly by prefixing the path with resource.wx/
, with or without [assembly:WisejResources]
.
Resource URLs work in HTML, CSS, JavaScript and Wisej.NET control ImageSource
properties.
You can use the assembly name (without .dll
) or just the resource name in the path.
Without an assembly specified, Wisej.NET searches all loaded assemblies for the resource.
The resource.wx
URL works only with these file types:
".css", ".js", ".html", ".jpg", ".png", ".gif", ".svg", ".bmp", ".jpeg"
Other file types return a 404 error.
Override embedded resources by placing a file with the same name in the deployed directory.
Examples:
resource.wx/button.png
returns either:
button.png
at application root
embedded button.png
resource.wx/CoolImages/button.png
returns either:
button.png
in \CoolImages
folder
embedded button.png
in CoolImages.dll
Wisej.NET provides built-in compression support for all HTTP
and WebSocket
communications.
Compression is enabled by default. Both browser and Wisej.NET server use gzip
as the default compression system.
Wisej.NET automatically compresses all HTTP
and WebSocket
packets when the size exceeds a certain threshold, ensuring that compression doesn't result in larger packets.
You may disable WebSocket
compression by setting the enableWebSocketCompression
setting to false
in Default.json
.
Disabling WebSocket
compression allows you to debug the frames when examining Network packets using the browser's Developer Tools.
Wisej.NET fully supports the Brotli
compression library - even on browsers without native Brotli
support.
Use Add New Item and select Brotli to add the Wisej.Web.Ext.Brotli
assembly. The source code for this extension is available in our Github repository: Brotli extension source code.
Under some still unknown circumstances, the Brotli
implementation from Google may generate the error "Unused space" on the browser. If you encounter this error, simply remove Wisej.Web.Ext.Brotli.dll
.
Wisej.NET supports Right-to-Left and Right-to-Left-Layout (mirroring) quite extensively in most controls, in the themes, in the Theme Builder, and in the designer.
The following controls do not fully support RightToLeft at the moment: DataGridView
, ListView
, PropertyGrid
.
The RightToLeft
property makes a control adapt its internal layout and alignment for right-to-left languages. The default value is Inherit
, which works in most cases. However, an application can:
Force a control to ignore right-to-left mode by setting the value to No
Force right-to-left mode by setting the value to Yes
This property is localizable.
The RightToLeftLayout
property mirrors the horizontal position of a container's direct children. The default value is false
.
When set to true
, horizontal layout is mirrored only when RightToLeft
resolves to Yes
.
Set this property to:
false
to prevent Wisej.NET from mirroring layout in right-to-left mode
true
to mirror horizontal location of direct children in right-to-left mode
This property is localizable.
Application.RightToLeft
takes its value from:
The "rightToLeft" Configuration setting
Can be forced to true
or false
programmatically
The default value of Control.RightToLeft
is Inherit
, meaning a control inherits the value from its parent. Top-level containers and parentless controls with RightToLeft
set to Inherit
take their value from Application.RightToLeft
.
All Wisej.NET themes support RightToLeft mode with minimal required changes. When a widget operates in right-to-left mode, it has the "rightToLeft" state allowing theme adaptation.
Most cases need no changes. Typical right-to-left adjustments include:
Mirroring icons
Switching single side border location
Example of mirroring icons with a state style:
TreeView arrows requiring 45-degree rotation when expanded and mirroring can adapt using these states:
Thread synchronization is very important in Wisej.NET due to its Real-Time nature and the small frequent WebSocket communication with the server. Understanding the basics of Wisej.NET synchronization helps when dealing with long-running actions, or parallel background tasks that need to interact with the user interface.
All events from the client are synchronized. Wisej.NET will always execute only one client event at a time in the order they are received from the client.
Refresh requests are not synchronized with the session and are processed in parallel. The user can refresh the browser while the server is processing an event and reload the page at any time.
Data loading requests (DataGrid pulling rows, ListView pulling items) are not synchronized with the session and are processed in parallel. However, they need to lock the collection they are rendering. This feature allows a user to refresh the browser while the server is processing an action and receive back the entire application.
All collections in Wisej.NET are now synchronized at the collection level. It's the tightest possible locking and avoids any possibility of deadlocks since there are no external events in the locked blocks.
Background tasks that need to alter a collection of components owned by a control (i.e. Rows, Items, Child Controls, etc.) may lock the collection itself. Wisej.NET uses the collection instance as the SyncRoot
object.
Usually thread locks are not guaranteed by the OS to be released in the order they are acquired.
Wisej.NET uses a special implementation of the "Fair Locking" pattern to guarantee that the threads are released in the order they are received and that if a component is disposed while waiting for the server to process its events the execution is aborted.
If your application runs background tasks that interact with UI controls, remember to check if the control has been disposed and lock the collections you are manipulating. If the user closes the application or the parent of a control, the control is disposed and your background task may generate an exception.
In general, the synchronization of your application is entirely up to you, like in any other system. Wisej.NET can only guarantee the synchronization of its internal functions.
Wisej.NET has a unique and powerful responsive system that extends beyond CSS and media selectors used in plain HTML+CSS systems. The responsive system in Wisej.NET is based on two features: Responsive Properties and ClientProfile
.
Client Profiles are device-related properties associated with a name that match to the client device when the page loads or the browser resizes.
ResponsiveProperties
are standard .NET properties available at design time (serializable) that use the [ResponsiveProperty]
attribute. These properties can hold multiple values associated with a Client Profile.
The process is straightforward: Wisej.NET reads the client profiles in ClientProfiles.json
, and from top to bottom matches the properties with current browser information. The first match becomes the Application.ActiveProfile
and triggers the ResponsiveProfileChanged
event.
When the ActiveProfile
changes, all [ResponsiveProperties]
update with their values associated to the Client Profile. For example, the Visible property of a button can be true for the "Default" Client Profile and false for the "Galaxy Tablet" profile, or the Display
property of a Button or TabControl can be Both on Desktops and Icon on Phone devices.
You can define custom client profiles by adding the ClientProfiles.json
file to your project. Click Add -> New Item, select Wisej.NET 3 and select ClientProfiles:
It will add the file ClientProfiles.json
containing the pre-configured profiles:
name
Unique name assigned to the profile (e.g., "Large Monitor", "Galaxy Tablet", "Airport Kiosk")
minWidth
When > 0, specifies minimum browser width to qualify the profile (e.g., 500px for width >= 500px)
maxWidth
When > 0, specifies maximum browser width to qualify the profile (e.g., 1500px for width <= 1500px)
minScreenWidth
When > 0, specifies minimum screen width to qualify the profile (e.g., 500px for screen width >= 500px)
maxScreenWidth
When > 0, specifies maximum screen width to qualify the profile (e.g., 1500px for screen width <= 1500px)
device
Regular expression matching browser-detected device type ("Desktop", "Mobile", or "Tablet"). Example: "(Tablet)|(Mobile)" matches either "Tablet" or "Mobile"
userAgent
landscape
Boolean indicating if profile matches when browser width exceeds height
The ResponsiveProfileChanged
event fires on:
Application
ContainerControl
(Form
, Page
, Desktop
, UserControl
)
DataGridView
ListView
This event allows your code to adapt controls to the client profile without limitations. While responsive properties are useful and easy to use (especially at design time), handling this event in code provides complete control over adaptations.
Wisej.NET includes several built-in layout engines and allows developers to easily build custom layout engines. This enables implementing layouts of any complexity, beyond what's available using plain CSS in browsers.
Traditional web frameworks using HTML string concatenation and CSS layouts (Blazor, Angular, PHP, ASP.NET, JSP, etc.) support only a fraction of the layouts available in Wisej.NET applications.
Layout engines handle arranging controls in their container. Every control's LayoutEngine
property returns the current engine and can be overridden in derived classes. The engine measures preferred size for AutoSize
controls and arranges position/size of container's direct children.
All controls use the DefaultLayout
engine, which supports:
Docking: Children can dock to the parent using DockStyles
Anchoring: Children can anchor their sides to the parent using AnchorStyles
Docking applies to child controls in inverse order "away from the viewer". The child control order affects how docking uses available space and intersections between horizontal/vertical docked controls.
Controls dock using the container's DisplayRectangle
area, reduced by the Padding
property.
The DefaultLayout
engine doesn't use margins. To increase distance between docked controls, add docked Spacers
.
Anchoring styles can be applied to any of the four sides of a control, or none.
When a control has no anchoring (AnchorStyles.None
), it will "float" within its container, preserving its relative location. Likewise, if anchoring is not set only for the vertical sides or horizontal sides, the control "floats" vertically or horizontally.
To keep a control centered in its parent, center it and remove the anchoring.
The default initial value of the Anchor
property is Top
+ Left
.
Padding and Margins are irrelevant to anchoring.
The flow layout engine is implemented for the FlowLayoutPanel
. Child controls are arranged horizontally or vertically next to each other.
When using a FlowLayoutPanel
in the designer, it extends all its children and adds several extension properties relevant only for flow layout:
FillWeight
: An arbitrary integer determining whether the child control grows horizontally or vertically (depending on FlowDirection
) to use remaining space. Default is 0, preserving control size. ⚠️ When using FillWeight
, set the control's MinimumSize
to prevent shrinking to 0.
FlowBreak
: When true
, causes a flow break, wrapping to the next line/column depending on the panel's FlowDirection
.
In the animation below, green buttons have FillWeight
set to 1. Left panel flows horizontally, right panel flows vertically:
The FlowLayout
engine enforces margins. Changing a child control's Margin
property increases distance to adjacent controls.
The table layout engine is implemented for the TableLayoutPanel
. Child controls are arranged in cells in a grid.
When using the TableLayoutPanel
in the designer, it extends its children and adds several extension properties relevant only for table layout:
Row
, Column
, Cell
: Determine the grid cell placement for the control. Only one control can occupy a specific cell.
RowSpan
: Determines how many rows are occupied by the cell.
ColumnSpan
: Determines how many columns are occupied by the cell.
This layout engine doesn't allow wrapping but supports growing. When adding a child programmatically, you can control whether to add a new row or column when all cells are assigned by setting the GrowStyle
property.
Use the RowStyles
and ColumnStyles
collections to determine cell sizing modes. Cells can:
Resize proportionally using percentage
Auto-size to fit content
Have fixed pixel size
Additionally, controls can dock or anchor inside their assigned cell.
The animation below shows a TableLayoutPanel
where button3
spans 2 columns and is anchored left and right while vertically centered in the cell. Adding new controls using this code automatically adds new rows when the last row's cells are occupied:
The TableLayout
engine enforces margins. Changing a child control's Margin
property affects distance to adjacent controls.
The flex layout engine is implemented for the FlexLayoutPanel
. It comprises two layout engines: HBoxLayout
and VBoxLayout
. This container arranges its children horizontally or vertically, always filling the client area.
Controls can use Margin
, MinimumSize
, MaximumSize
and several extension properties to customize the layout:
FillWeight
: An arbitrary integer determining whether the child control grows horizontally or vertically (based on LayoutStyle
) to use remaining space. Default is 0, preserving control size. ⚠️ When using FillWeight
, set the control's MinimumSize
to prevent shrinking to 0.
AlignX
: Controls horizontal alignment of child controls that can't fill a vertical FlexLayoutPanel
due to width constraints. Overrides the default HorizontalAlign
for that control.
AlignY
: Controls vertical alignment of child controls that can't fill a horizontal FlexLayoutPanel
due to height constraints. Overrides the default VerticalAlign
for that control.
The animation below shows two FlexLayoutPanel
s - first using HBox layout, second using VBox layout. Some buttons have FillWeight
set to 1, and button3
is set to align vertically:
The FlexLayout
engine enforces margins. Changing a child control's Margin
property affects distance to adjacent controls.
You can build a custom layout engine by deriving from the Wisej.Web.Layout.LayoutEngine
class and overriding the Control.LayoutEngine
property in your container class.
You can create a single instance (singleton) of your layout engine to reuse, rather than creating a new instance for each container instantiation.
A layout engine needs to implement three methods:
InitLayout(child, specifiedBounds)
: Optional - can use base implementation. Since layout engines can be cached, this call refreshes any internal cache related to a child control.
GetPreferredSize(container, proposedSize)
: Optional - can use base implementation. Used when the container's AutoSize
property is enabled and needs to measure children for preferred size.
Layout(container, args)
: Arranges child controls in their container. The simplest layout engine does nothing, letting controls use their own Location
and Size
.
This sample shows a basic custom layout that arranges child controls in a cascading pattern from top-left to bottom-right:
The CascadeLayout
engine works with this CascadingLayoutPanel
. It adds a Gap
property used by the layout engine:
Depending on the value of the Gap property and the size of the container, this is the result.
Since 3.0
The designer's toolbar has a new option to arrange child controls without setting the Dock or the Anchor properties.
Clicking the AutoLayout button opens the AutoLayout floating panel:
Arranges the controls horizontally, using the available space proportionally.
Arranges the controls vertically, using the available space proportionally.
Docks the controls to the left of the containing area.
Docks the controls to the right of the containing area.
Docks the controls to the bottom of the containing area.
Docks the controls to the top of the containing area.
Resizes the controls to fill the containing area.
Toggles using the controls' margin when applying the auto layout.
Selects the horizontal alignment of the controls within the containing area.
Selects the vertical alignment of the controls within the containing area.
Sets the spacing between the controls in pixels.
Margins are used by the designer to create proximity snap lines.
When moving a control near another, proximity snap lines appear based on the controls' margins.
The vertical snap line between controls combines the top control's Margin.Bottom
and bottom control's Margin.Top
values. Using this feature correctly simplifies UI development and helps maintain UI/UX guidelines.
Wisej.NET is the only web application system that supports a pixel-perfect designer. This unique technology integrates with Visual Studio designer to render final HTML directly on the design surface with minimal limitations.
You can design any JavaScript widget, including custom-built controls and C#/VB.NET backed widgets.
The Visual Studio designer can display any Wisej.NET control, effectively turning JavaScript widgets into fully designable controls.
The first thing you'll notice is the new toolbar at the bottom of the design surface:
Shows a welcome page with resources, help and tips.
Switches the theme used in the current design surface.
Changes the color used to draw selection lines and glyphs.
Changes the size of the grid in the background of the design surface.
Takes a screenshot of the selected control or the entire design surface and saves it in the clipboard.
Hides or shows controls with Visible set to false. Visual Studio designer always shows all controls, including the controls with Visible set to false. When a container has several controls that overlap and may be shown/hidden at runtime, the design view can become quite messy. This toggle button solves this problem.
Refreshes the select controls or the entire designer surface. It's useful when the rendering of the widget is incomplete because of a complex control or a third party library slow to load.
Shows or hides the anchor glyhps. In complex screens it is possible to click the anchoring glyphs by mistake, this tool disables the feature.
Shows the toolbox.
Shows the Document Outline viewer.
Shows the property viewer for the selected control.
Shows the name, location and size of the selected control.
Shows the current HTML renderer and opens the designer options dialog.
Shows the Wisej.NET License Panel.
All controls in the designer provide snap lines and snap rules to help developers align controls. Wisej.NET adds custom snap lines that are saved with the container.
You can create, delete, and move horizontal or vertical snap lines in a design surface and save them in the .resx
file. When other developers open the same control in design mode, they see the same snap lines, helping enforce consistent design across the development team.
To work with snap lines:
Create: Click on the ruler
Delete: Click again on the ruler at the same location
Move: Drag the line on the design surface
Wisej.NET controls extend Visual Studio's quick actions feature. When you drop a control on the design surface, the designer immediately opens the quick action menu showing common properties.
This feature significantly speeds up initial UI construction.
Add properties to the quick actions menu by applying the **DesignerActionList**
attribute:
The DesignerActionList
implementation in Wisej.NET eliminates the need to create custom designers for controls that need quick action lists.
When designing a Wisej.NET page, form, desktop, or control you can manage multiple "views" for the same container by selecting the current Client Profile in the designer toolbar.
Wisej.NET preloads the list with the few built-in client profiles. However, you can create your own by adding a ClientProfiles.json file and see your custom profiles in the designer.
All the responsive properties set at design time are saved in the resx file of the container. You can find which client profiles and, for each profile, which properties are changed by inspecting the (Responsive Properties) collection.
See also:
The document outline view shows the full hierarchy of all the controls in the main container being designed. It's an invaluable tool to understand the structure of complex pages.
You can change the theme used in the designer on the fly without changing the theme used by the application. This feature allows you to see what the screen would look like with another theme and to test your custom themes.
The list is automatically populated with all the built-in themes plus all the themes that Wisej.NET can find in the /Themes folder or embedded resources in referenced assemblies.
The last option ("Select Theme...") lets you pick a theme file from any other location. This setting is saved in the registry on the developer's machine.
The designer is also able to render overlapping controls transparent colors. Since controls are rendered individually, it's a difficult task to "compose" the overlapping parts together for each control in the right order and at any depth.
This feature is off by default. You can turn it on by turning on the ShowDesignerTransparency property on the design container.
Wisej.NET supports all sorts of extensions, including Extension Providers. These are components that when added to a container extend (add properties and functionality) to all the qualified controls in the container.
The designer also supports this functionality, and is capable of updating the view of the extended controls as they are designed.
This dialog lets you switch the rendering engine between the legacy Internet Explorer (IE) and the new Edge/Chrome. You can also select how many parallel rendering engines are used by the designer and the default rendering timeout.
Wisej.NET always creates the full number of parallel renderers for each designer surface open in Visual Studio. When a designer is closed, Wisej.NET places the renderers in a pool to be able to reuse the instances quickly. However, after a certain timeout, Wisej.NET disposed all the renderers above the number of parallel renderers.
The renderer timeout indicates how long the designer waits for a control to complete its rendering before showing the alert icon in the design view.
A common reason for the timeout icon to display in the designer are broken image links or broken font links.
All Wisej.NET control support custom painting using a standard GDI+ Graphics context and a simple Paint event.
Custom painting also supported at design time, when the painting is done in the control's class (not in the Paint event handler created in the same design surface).
Animations are not supported at design time
Extender providers that add visual items outside the extended component's rectangle (e.g., tooltips, error icons, information bubbles) are not shown at design time since they typically exist outside the component's frame
When rotations cause component content to exit its rectangle, the outside parts are truncated at design time but visible at runtime
Tab navigation concepts.
Managing the tab order of complex screens can become very time consuming. If you add a control in the middle of a set of fields you have to renumber the following fields. Do that for a form with 100+ fields and you'll appreciate what we have added to Wisej.NET.
Press Manual and the designer enters "tabbing mode" - you must click every single control from the start to set the correct sequence. Miss one and you'll have to start again.
Press Horizontal or Vertical and Wisej.NET automatically renumbers all the tab indexes using a horizontal or vertical navigation algorithm and enters "tabbing mode".
Sometimes you may want to use horizontal tabbing in one container and vertical tabbing in another, or disable renumbering altogether. The Wisej.NET TabOrderManager
component allows you to do that at design time.
Drop the TabOrderManager
on the designer and all containers in the design surface will expose a new extender property named TabOrder
allowing you to set the order direction for each container.
The same design-time issue is present at runtime when the Wisej.NET application adds or removes controls dynamically. In code you can go through the controls collection and assign new tab indexes. However, the assignment becomes more complicated when there are containers and nested containers.
In code you can create an instance of the Wisej.NET TabOrderManager
component or use an existing instance already created at design time. This component exposes a number of methods that will help your code update the tabbing order.
Wisej.NET enables adding unlimited JavaScript code with direct widget references. Your JavaScript code can be in .js
files, called from C#/VB.NET, or embedded in resource files.
All controls written in C#/VB.NET on the server are created as pure JavaScript widgets on the client and registered in a new object model under App
. See JavaScript Object Model.
You can add JavaScript to a Wisej.NET application in several ways:
Script tag in Default.htm
You can add scripts in the application startup page (usually Default.htm
). However, scripts in the <head>
tag execute before the Wisej.NET library loads and initializes. Even scripts loaded on document ready are too early for application widgets. Therefore, JavaScript in Default.htm
should only be used for non-Wisej.NET purposes.
Embedded resource
Create a .js
file, set it to EmbeddedResource under /Resources
or /Platform
and add [assembly:WisejResources]
to AssemblyInfo.cs
. Wisej.NET loads and invokes these JavaScript files in order with the framework library.
While too early for application objects, this is ideal for installing additional widget classes or overriding existing ones. All Wisej.NET widgets use this technique.
JavaScript Extender Provider
Drop the JavaScript Extender
on any top-level container (Form
, Page
, Desktop
or User Control) to extend all controls with two properties: JavaScript
and JavaScriptSource
.
The JavaScript
property accepts JavaScript code that runs in the control's context - this
refers to the control's widget on the client. You can use widget methods, properties and address related widgets. This code runs last, after Wisej.NET renders and updates page widgets.
Use this extender to attach client events or modify widget behavior. The image below shows a button code snippet displaying a client-side alert:
The JavaScriptSource
property works similarly but accepts a .js
file instead of inline code. This is useful for longer scripts and leverages Visual Studio's JavaScript editor.
Note that Call
method's first parameter is just the function name, while Eval
expects a complete script:
From Wikipedia:
The real-time web is a network web using technologies and practices that enable users to receive information as soon as it is published by its authors, rather than requiring that they or their software check a source periodically for updates.
In our view, a Real Time Web Application must be able to:
Update the user's browser (client) seamlessly at any time, as if directly connected to the server
Receive events and updates from the client without delay
Web-based video games exemplify Real Time Web. Wisej.NET extends this concept to Line of Business Applications.
When the server supports WebSocket connections, Wisej.NET "pushes" real-time updates to the client at any time. A background task can update connected clients asynchronously by calling Application.Update()
.
Some servers or browsers may not support WebSocket connections and can only use HTTP requests. In these cases, the server cannot contact the browser directly since each HTTP request starts and terminates when the browser contacts the server. One solution is to create a Wisej.Web.Timer
to periodically fire server events and allow Wisej.NET to update the client.
SignalR emulates WebSocket connections using "long polling" - keeping a pending request open to allow server responses, then opening a new suspended request. However:
Each request blocks a thread
Prone to timeout errors
Browsers limit open AJAX requests (4-8), risking request blocking
Without WebSocket support, use automatic polling in Wisej.NET:
Call Application.StartPolling()
and Application.EndPolling()
Configure polling Interval
in the configuration file for non-WebSocket clients
Wisej.NET sends all updates since the last request back to the client with each request. With a background task but no WebSocket connection, the browser updates on every event (timer, click, etc.).
Push updates
Wisej.NET applications can update the client during a request or asynchronously from a background task
Modal workflow
Server-side business logic, UI logic, or UI code can display modal dialogs/message boxes and suspend execution until closure
Complete session state
Application state stays synchronized between client/server - refresh at any time to reload full state including modals
Live events
Server code responds to real-time pointer events (mouse movement, wheel, control enter/leave)
Remote methods
Server code can call client JavaScript and vice-versa at any time
Drawing and painting
In a program, a modal workflow is a mode of operation in which a particular task or feature must be completed before the user can proceed to other tasks or features. This is typically implemented by displaying a modal window or dialog box that requires user interaction before continuing.
Modal workflows are often used when users must complete specific tasks or provide required information. For example, a modal workflow might prompt users to save work before closing a document, or enter login credentials before accessing restricted areas.
Modal workflows help guide users through specific steps or highlight important actions. However, if overused, they can disrupt workflow.
In web applications, supporting modal workflow means:
Suspending server-side code execution
Waiting for user input
Resuming execution with received user information
While straightforward in desktop applications, this becomes challenging in web applications where code executes on the server and the UI runs asynchronously on different machines.
The code and images below demonstrate how Wisej.NET handles modal code execution:
The server code suspends, waiting for user choice. After clicking Yes
or No
on the client-side, the server code resumes exactly where it was suspended.
Wisej.NET supports:
Nested modal states
Custom DialogResult
values
Control references in modal dialogs
User input data access
Modal workflow works for MessageBox
and forms (dialog boxes) with any type of control, data binding, and code-behind. The example above, modified to use a modal dialog, looks like this:
Regular modal dialogs or MessageBox
controls suspend the current thread while waiting for user input. By default the system handles about 32,000 threads. While suspended, threads use no CPU time.
Wisej.NET fully supports the async/await programming pattern for modal dialogs.
Using the await
keyword, a modal dialog can wait for closure without thread suspension. Simply use the "Async" version of the ShowDialog
method.
Asynchronous modal dialogs or MessageBox
controls don't use any threads while waiting for user input.
You can implement modal behavior and wait for user input without using modal dialogs or MessageBox
controls. Wisej.NET provides Application.DoModal(component)
for this purpose.
For example, the PropertyGrid
uses Application.DoModal()
to suspend code flow while waiting for dropdown selection box closure. Use Application.EndModal(component, result)
to terminate the last modal state - modal states are stacked.
The code above opens a dropdown and waits for user action. DoModal
returns DialogResult.Cancel
if closed without selection, or DialogResult.OK
otherwise.
This provides powerful control over code execution and user action synchronization.
Background Tasks are one of the most important features of Wisej.NET. No other Web development system allows developers to launch background tasks (threads) on the server and update the client asynchronously with the same level of simplicity and robustness.
A Background Task runs on the server in the background after the client request has completed, allowing users to continue working while the task executes.
Background tasks operate independently from the session and user that initiated them. They run as separate threads without any session knowledge. You can even start separate threads when an application first loads, before any session or user request exists.
What can I do in a Background Task?
Anything - connect to other servers, query databases, use the file system, access remote services, etc.
How do I terminate a Background Task?
Simply return from the call. A background task (like any thread) starts by calling your start method and runs until you exit it. Typically it's a loop that checks conditions and uses Thread.Sleep(ms)
periodically, exiting when complete.
Wisej.NET provides a straightforward way to launch a Background Task bound to a specific session, allowing code to interact with the user's UI in real-time.
The example above updates the specific button1
in the session that started the task because the thread is started using Application.StartTask()
.
Application.StartTask()
starts a new thread and updates the context to match the calling session. If using Thread.Start()
instead, the thread method couldn't access session objects unless wrapped in Application.RunInContext()
.
When code runs in context (either in-bound or out-of-bound for background tasks), you can call Application.Update()
anytime to push UI updates to the client.
If the client or server doesn't support WebSocket, Application.Update()
has no effect since the connection doesn't exist. Wisej.NET provides alternative client updates through automatic polling. See Real Time Web Applications and pollingInterval in Configuration.
Older clients or servers may not support WebSocket connections, preventing out-of-bound UI updates from background tasks reaching the client browser.
Wisej.NET provides alternative client updates using Application.StartPolling(milliseconds)
and Application.EndPolling()
to enable periodic server polling. These methods are ignored when using WebSocket connections.
Since Background Tasks aren't bound to specific sessions, they can perform global tasks serving multiple users simultaneously. While the previous example showed a single-session task, we can create session-independent tasks.
Examples include chat servers, stock market watchers, or any task periodically checking resources. The recommended approach is firing events from the service (background task) and letting user sessions subscribe to these events.
Below is a simplified service firing events every second with a subscribing client.
Handling Events from the Background Service
The power and simplicity of background tasks in Web applications through the Wisej.NET framework allows handling the browser from the server as if it were a screen directly connected to the server.
Wisej.NET keeps the server and client browser in sync, including the application's UI object model. This allows JavaScript code to interact with Wisej.NET controls in the browser while simultaneously updating their server-side components.
Wisej.NET registers all top-level windows and their children hierarchically with the browser using App
as the root object. For example, the simple HelloWorld
tutorial application registers the JavaScript object App.Window1
. You can view the object model using F12 and typing App.
in the console.
Child objects are reachable as members of their parent control, e.g.: App.Window1.button1
.
The example below shows how to change button1
text using JavaScript and trigger the server-side event. Type this code in the browser's console (F12):
When a name collision occurs between a child control and a widget method/property, Wisej.NET ignores the child control name. You can still access it using parent.getChildControls()[index]
. For component collisions (e.g., multiple Window1
objects), Wisej.NET converts the member to an array: App.Window1[0]
, App.Window1[1]
, etc.
Wisej.NET supports calling server-side methods from the client. Any public method in a visual component with the [Wisej.Core.WebMethod]
attribute becomes a remote method. You can call it from the browser, passing arguments and receiving return values from the server.
You can also declare public static [Wisej.Core.WebMethod]
methods in your Program.cs
class - these are registered as methods of the App
object on the client side.
The example below shows adding remote methods to a form and the application, demonstrating return values:
Here's how to use these web methods in the browser console:
Only web methods declared in top-level containers (Page
, Form
, Desktop
) are automatically registered with the client widget.
Web methods in child control classes need explicit registration by overriding OnWebRender()
and adding the webMethods array: config.webMethods = new[]{"method1", "method2"};
Learn how to apply different themes to your Wisej.NET application.
See below for more information on theming and customizations.
To change the theme at runtime, use the following line in your code:
To change the theme before the application runs, you can apply it in one of two ways:
or
Changing the theme in the Wisej.NET Designer in Visual Studio will only show the changes at design-time. Use one of the above methods to apply it at runtime.
New Wisej.NET applications come with several built-in base themes that can be used to style the application.
This theme uses a blue base color, thick window borders and FontAwesome SVG icons.
This theme is based on the popular Bootstrap theme, using its distinctive colors, focus shadow, and Bootstrap SVG icons.
This theme is based on the popular Bootstrap theme, using its distinctive colors, focus shadow, and Bootstrap SVG icons. This theme has a dark background and light text.
This theme uses overlapped scrollbars to implement cool disappearing and overlapped scrollbars similar to the Windows UWP style.
This theme is based on Windows Vista metrics, font, icons and design.
Wisej.NET provides comprehensive session management - among the most complete server-side state management systems compared to other web frameworks.
Web systems are inherently stateless:
Each browser request may be processed by different server threads
Server threads can be reused across browsers
Session management requires generating and tracking session IDs with each request
Wisej.NET fully supports server-side state management for both HTTP and WebSocket connections.
Important distinctions:
Sessions differ from users and authentication
Web sessions parallel desktop application instances
Desktop apps can run with/without users/authentication
Multiple instances create separate sessions
Web apps don't run separate executables per session
No dedicated UI thread exists
Each request independently restores session state
Web applications face unique session management challenges:
Browser and server on different machines
Intermittent connectivity
Users leaving browsers open
Unexpected shutdowns
Navigation between pages
Browser refresh/F5
Sessions must survive some events while terminating for others. With no reliable way to detect browser closure, device shutdown, or distinguish navigation from tab closure, Wisej.NET uses:
When a session times out, it's permanently removed - like terminating a desktop application. ASP.NET's Session_End
handler in Global.asax fires after session removal, allowing only cleanup.
Beyond sessionTimeout
, Wisej.NET employs a keep-alive ping system that triggers after periods of user inactivity. This helps detect when users are "gone" due to:
Closed browser
Powered-off device
Lost connectivity
With no user activity but an open browser, the client sends keep-alive messages. Without these messages, Wisej.NET terminates the session after sessionTimeout * 2
.
After sessionTimeout
seconds without user interaction, Wisej.NET:
Shows built-in SessionTimeoutForm
if unhandled
You can:
Show a custom window
Extend SessionTimeoutForm
Show nothing by setting e.Handled = true
Wisej.NET supports two types of infinite sessions:
Standard Infinite
Suppress the timeout window
Session stays alive while browser is open and connected
See above for suppressing timeout window
Best practice: Set sessionTimeout
to 1-3 minutes (60-180 seconds) and handle Application.SessionTimeout
to control expiration notices or suppress them entirely.
Browser-Bound Sessions
Bind session to browser by saving Session ID to local storage
Optionally set sessionTimeout
to 0 (never expires until server shutdown)
Users can return later to continue where they left off
Requires controlled session count
Traditional HTML systems (PHP, ASP.NET, JSP) store session IDs in cookies that:
Persist after browser closure
Share across browser tabs
Limit to one session per browser
Wisej.NET offers two storage options:
Cleared when browser closes
Not sent in request headers
Unique per browser tab
Survives browser closure/device shutdown
Session reloads automatically if not expired
Continues work from previous state
Various scenarios affect session termination:
Free the session immediately
These scenarios stop keep-alive pings, triggering session termination after sessionTimeout
* 2:
Closing browser tab
Closing entire browser
Navigating away
Device shutdown
Wisej.NET is secure by design and supports all the latest security defenses. This document covers common threats and how they are handled.
A key difference between traditional HTML-based applications (ASP.NET/MVC/JSP) and Single Page Applications (SPAs) is how they handle HTML:
Traditional apps concatenate HTML strings on the server and parse HTML requests
SPAs (like Wisej.NET Real Time Web Applications) don't build or parse HTML strings
In Wisej.NET, DOM manipulation happens directly in the browser through Ajax JSON packets. This prevents HTML/script injection since HTML isn't used and scripts remain as text when manipulating the DOM.
Cross-Site Scripting can affect Wisej.NET applications when displaying unencoded or unsanitized HTML text.
A malicious user might enter text like this in a TextBox
or DataGridView
cell:
If displayed as HTML, this script executes. When shown to other users, it could potentially access screen content.
By default, Wisej.NET encodes all text sent to the browser, displaying HTML as plain text. However:
Setting AllowHtml
to true
on controls (labels, grid columns, buttons, tree nodes) allows HTML execution
Using MessageBox
or AlertBox
with user-entered text executes HTML by default since AllowHtml
is true
You can either sanitize text or disable HTML:
Starting from Wisej.NET 3.0.10, we added a global method to process any user input, regardless of source control. Assign your method to TextUtils.ConvertToString(owner, value)
. Default implementation:
Your implementation of TextUtils.ConvertToString(owner, value)
can "clean up" any user input before assignment to the control. The owner
argument is the receiving component.
Cookies managed through Wisej.Web.Application.Cookies
do not support setting the HttpOnly flag because they are written using JavaScript to be compatible with WebSocket connections. However, you can create HttpOnly cookies effortlessly by leveraging the underlying ASP.NET or ASP.NET Core HttpContext
. Refer to the code example below for guidance.
Starting from Wisej.NET 4 Wisej.Base.Cookie
supports the HttpOnly
property that was added as an experimental feature in 3.5.13.
To enable IHttpContextAccessor
, add builder.Services.AddHttpContextAccessor();
in Startup.cs
.
When WebSocket is enabled (default), you can write HttpOnly cookies only during:
Initial Program.Main()
execution
Application.ApplicationStart
event handling
Application.ApplicationRefresh
event handling
Any time when Application.IsWebSocket
returns false
However, all cookies set with HttpOnly remain accessible in the Application.Cookies
collection.
Session hijacking affects all web applications maintaining sessions. Sessions require either:
A session cookie
A session ID in the URL
Wisej.NET supports both cookie and cookieless modes. For security:
Wisej.NET generates a client fingerprint hash using browser information
Each request is validated against this fingerprint
Mismatched fingerprints trigger new sessions
WebSocket connections add protection - impossible to attach multiple live sockets to one session
SSL can be enforced (https: and wss: for WebSocket) via the secure setting
With WebSocket, spoofed requests to active sessions are impossible. With HTTP-only, the attacker's computer must match the original client's browser version, OS, and IP address.
The OWASP-described session hijacking attack is fully blocked by Wisej.NET server-side, making the system "secure by design".
Session fixation is a form of "reverse session hijacking". The attacker creates a valid session, then "fixes" it on the victim's machine through some means.
After "fixing" the session, if the victim logs in, the attacker's session becomes authenticated. This naive attack fails with Wisej.NET - the server immediately invalidates the "fixed" session ID and assigns a new one to the victim.
The OWASP-described session fixation attack is fully blocked by Wisej.NET server-side, making the system "secure by design" (unless "validateClient" is disabled in Default.json).
Denial of service (DoS) protection isn't built into Wisej.NET since it would be too late once requests reach the HTTP handler. While we could mitigate DoS events, IIS thread usage makes handler- level protection insufficient. DoS attacks are better handled at the OS level before reaching the web server (Apache/IIS).
Wisej.NET supports any .NET authentication method. Since nothing displays to users without your application creating it, you can perform any authentication before enabling resource access.
Beyond code authentication, Wisej.NET supports standard IIS authentication methods and exposes user credentials through Application.UserIdentity
.
Traditional HTML-based systems mix JavaScript, callbacks, postbacks, services, and API keys on the client. Potential intruders can inspect code/page/source for sensitive information.
This vulnerability increases with client-side-only SPAs (ExtJS, standalone qooxdoo, dojo). These require exposing business logic, visual logic, and access keys on the client. Any client-side code is inspectable.
With Wisej.NET, no application code reaches the client unless explicitly placed there. Everything runs securely on the server, with only property updates and events communicated between server and client.
Wisej.NET performs server-side verification that "executable" controls triggering click events are enabled and visible. This prevents users from using browser dev-tools to activate hidden or disabled controls.
Syncfusion
Telerik
Most component vendors
The simplest CSP matches DevExpress server-side controls policy:
The strictest CSP requires a random nonce
. Configuration example:
When using the random nonce
you have to actually generate a random identifier. In some cases you may want to change it every time the application is loaded in the browser. Which requires the Default.html page to be modified on the server side on each request.
There are several ways to accomplish that. You can preprocess the Default.html file using a server side handler and replace a placeholder. Or you can use dynamic HTML pages: i.e. Default.aspx or Default.cshtml (razor) pages or any other dynamic html system.
Examples using Default.aspx and Default.cshtml:
Since 3.5.2 Use Application.RefreshSessionId()
to generate a new session id without losing the current session. Best practice: generate new session id after user authentication.
Generating a new session id invalidates any captured sessions immediately.
Services and Dependency Injection in 3.1.
Starting with Wisej.NET 3.1, we added full support for services and dependency injection. Like everything else in Wisej.NET, it's a lean, performant, and flexible implementation.
Our DI implementation is supported in both .NET 4.8 and .NET Core.
You can register services at any point in the application. Services are always registered globally - if a service type is registered more than once, subsequent definitions replace the existing definition.
A good place to initialize services is in the static Program
constructor, though you can register services anywhere in your code.
The code above registers two services:
An _ILogger_
implementation. Wisej.NET creates a MyLogger
instance once (Global scope) on first use. This service is never disposed, even if it implements _IDisposable_
, because it's registered with Shared lifetime as a singleton instance used by all sessions.
An _IFileSystem_
service that delegates creation to the _CreateFileSystemFactory_
method with Session scope. Wisej.NET invokes _CreateFileSystemFactory_
on first request per session. The service instance is automatically disposed if it implements _IDisposable_
when the session ends.
Your code can request a service implementation in three ways:
Using _Application.Services.GetService<T>()_
Using the _[Inject]_
attribute on a property
Adding a service argument to the constructor of another service implementation
_Application.GetService<T>()_
returns the service implementation for the requested T type if it exists, or null.
The _[Inject]_
attribute works by default only on top-level UI containers: _Page_
, _Form_
, and _Desktop_
classes. When you add the _[Inject]_
attribute to a property (protected, private or public), Wisej.NET automatically resolves the service and assigns it during object construction.
Services created by Wisej.NET can receive instances of other services by declaring them in the constructor.
Wisej.NET supports Dependency Injection through constructors and property injection.
Property injection works automatically for all top-level containers (Form
, Page
, Desktop
) and system-created services. Constructor injection works for service creation.
Example MyFileSystemImplementation
with property injection:
Constructor injection example (works only for system-created services):
To inject properties programmatically:
If the object declares any _[Inject]_
properties, they receive service instances according to their lifetime.
You can register generic types as services (starting from Wisej.NET 3.5.4) and request concrete service instances at runtime.
When requesting a service, Wisej.NET constructs or retrieves the correct instance of the generic type.
The line Application.AddService<IServiceProvider>(app.Services);
registers Microsoft's IServiceProvider
with Wisej.NET and replaces our IServiceProvider
.
After this, _Application.Services.AddService<T>()_
is not supported - all services must be registered using Microsoft's DI.
_Application.Services.GetService<T>()_
and _[Inject]_
use the alternative IServiceProvider
to resolve services. The IServiceProvider
instance is registered as a global singleton by default but can be registered per session using a different ServiceLifetime
option.
We support these service lifetimes:
Shared: The service instance is a singleton used by all sessions and threads
Session: The service instance is created per session and disposed (if _IDisposable_
) when the session ends. Note that no other DI container supports session lifetime
Thread: The service instance is created per thread (roughly corresponding to browser requests) and disposed (if _IDisposable_
) when thread code ends
Transient: The service instance is created on each request. It's never disposed - disposal responsibility (if _IDisposable_
) lies with the caller
The default lifetime when registering a service is always _Shared_
.
Regular expression matching browser's string. Used to detect specific OS versions or browsers
Wisej.NET integrates and extends Visual Studio's built-in designer ( significantly!). At design time, all Wisej.NET controls, including third-party JavaScript widgets, are rendered behind the scenes using an array of headless browsers ( this is one of Wisej.NET's patented technologies).
Changes the client profile being displayed in design view. Changing the client profile updates the value of the associated with the client profile.
Enables the and applies the selected auto-numbering order.
Since 3.0 Shows the panel.
Using the toolbar you can change the level of information shown in the tree and, most importantly, you can move controls up and down their container's collection or move a control in or out a container.
The colors drop down lets you change the selection and glyphs colors. Doesn't really serve any purpose other than it's a cool features except that in some cases the colors of the controls may interfere with the designer colors...
At design time use "Tab Order" button in the designer toolbar to enter "tabbing mode". It will give you three options: Manual, Horizontal and Vertical.
Controls can draw/paint on the client browser using HTML5 <canvas>
. See the extension and example
Wisej.NET JavaScript widgets derive from Qooxdoo's widget. See reference for available methods and properties.
Wisej.NET themes are collections of styles, fonts, and images that define the look and feel of components and other UI features. You can use one of the or .
By default, new Wisej.NET applications use the theme. The theme can be changed in several ways.
This theme uses a blue base color, thick window caption, no side window borders borders and SVG icons.
This theme uses a blue base color, thick window borders and SVG icons. Use it as a base to create new variations.
This theme is based on Windows 10 metrics, font, and design. This theme uses the SVG icons for Windows 10.
This theme uses a clear base color, no side window borders, a thick window caption and SVG icons.
This theme uses a clear base color, no side window borders, a thick window caption and SVG icons.
This theme uses a clear base color, no side window borders, a thick window caption and SVG icons.
This theme is inspired by Google Material Design, with sleek animations, a large window caption, and a minimalist layout. It uses SVG icons.
pings
Session
Wisej.NET removes a session from memory after a period without user activity signs. The setting determines when Wisej.NET fires the event.
This event provides an opportunity to react before losing the session and user's work. By default, without handling , Wisej.NET displays a built-in .
After another timeout period without user response, Wisej.NET removes the session and fires .
Fires
Wisej.NET defaults to browser :
Optionally Wisej.NET to use browser :
If your application provides exit options, call to:
Fire
If someone obtains a live session ID, they can access the session and breach the application. According to Microsoft, to prevent this in ASP.NET/MVC, especially with cookieless mode where session IDs appear in URLs.
Wisej.NET supports policies compatible with:
If you need something more complex, we also support switching our with any third-party implementation, including Microsoft's DI, Autofac, or others.
To use a different service manager, register another object.
Since 3.5.6
Some default behaviors in Wisej.NET are configurable with AppContext
switches. These are the switches currently supported:
LabelSelfSize
(default: true
)
The behavior of AutoSize
in Label
controls differs from other controls, especially in standard containers like Panel
, Form
, Page
, or GroupBox
. When a Label
is right-anchored in these containers, AutoSize
adjusts width while maintaining the left position. This ensures the Label
expands/contracts rightward without moving its left edge.
When the Label
is in a custom layout container (FlexLayoutPanel
, FlowLayoutPanel
, TableLayoutPanel
), AutoSize
behaves like other controls.
Corresponds to Label.SelfSizeDefault
and Label.SelfSize
.
DataGridViewAutoSelectFirstRow
(default: true
)
By default, setting the current cell in a DataGridView
selects the row, cell, or column based on SelectionMode
. To prevent automatic selection when setting the current cell, set DataGridViewAutoSelectFirstRow
to false
.
Corresponds to DataGridView.AutoSelectFirstRowDefault
and DataGridView.AutoSelectFirstRow
.
DataGridViewAutoGenerateColumns
(default: true
)
The DataGridView
automatically generates columns when DataSource
is assigned in the designer, then sets AutoGenerateColumns
to false
after creating and serializing columns. Setting DataSource
to null resets AutoGenerateColumns
to true
.
You cannot set AutoGenerateColumns
in the designer as it's managed with the DataSource
property. However, you can set its default initial value to false
using the DataGridViewAutoGenerateColumns
switch.
Corresponds to DataGridView.AutoGenerateColumnsDefault
.
FormAutoCloseModalDialog
(default: false
)
In Wisej.NET, modal dialogs require calling Close()
to close. Setting AutoCloseModalDialog
to true
enables automatic closure when Form.DialogResult
is set to any value except DialogResult.None
.
When AutoCloseModalDialog
is true
, the dialog closes automatically when:
User clicks AcceptButton
or CancelButton
with DialogResult
set
Code sets the DialogResult
property
This matches WinForms behavior but differs from Wisej.NET's default.
Corresponds to Form.AutoCloseModalDialogDefault
and Form.AutoCloseModalDialog
.
See Microsoft's System.AppContext
documentation for various configuration approaches. Example code setup:
Wisej.NET is a powerful web framework for building real-time web applications using .NET. While Visual Studio is the primary IDE for Wisej.NET development, you can also integrate and develop Wisej.NET applications in Visual Studio Code.
The Wisej.NET Designer is not supported in Visual Studio Code.
Before integrating Wisej.NET with Visual Studio Code, ensure you have the following installed:
Launch Visual Studio Code.
Click on File → Open Folder and select your Wisej.NET project directory.
Wait for Visual Studio Code to load the project dependencies.
Navigate to the Run and Debug tab (Ctrl+Shift+D
).
Click C# Project as the Run and Debug target.
The necessary configuration files (launch.json
and tasks.json
) will be generated automatically.
Open the Run and Debug tab.
Select the generated C# Project configuration.
Click Start Debugging (F5
).
The application will start, and you can access it via the local development server.
Ensure that the correct .NET SDK version is installed and matches your project's requirements.
If dependencies fail to load, run dotnet restore
in the terminal.
If debugging does not start, check the launch.json
file and verify that the correct target framework is specified.
Adds standard accessibility attributes to the browser element to help with accessible support software.
When web applications are properly designed and coded, people with disabilities can use them. However, currently many sites and tools are developed with accessibility barriers that make them difficult or impossible for some people to use.
Making the web accessible benefits individuals, businesses, and society. International web standards define what is needed for accessibility.
Wisej.NET has basic accessibility support built-in and provides a WebARIA extension to support most of the WAI-ARIA properties.
All Wisej.NET controls expose three accessible properties:
AccessibleName. It is rendered in the browser as the "name" property.
AccessibleDescription. Rendered in the browser as the "alt" property.
AccessibleRole. Rendered in the browser as the "role" property.
How these properties are used by accessibility tools it is entirely up to the tool.
The WebARIA extension is an extender component that you can drop on any designer surface. It will automatically add a number of new properties to all the controls in the designer.
Some of these properties are cross references to other controls on the same page. These properties allow you to pick a control in the property grid and generate the WAI-ARIA attribute in the browser.
For example, setting the DescribedBy property of a button to a Label, will generate the "aria-describedby" attribute with the id of the label.
See the WebARIA extension for more information.
Allow controls to adjust their size to fit their content.
Many Wisej.NET controls expose the AutoSize property, and when the control is also a container (i.e.: Panel, FlowLayoutPanel, TableLayoutPanel, FlexLayoutPanel, UserControl, GroupBox, Form, etc) it also has the AutoSizeMode property.
The auto-sizing of the control is performed on the server using the content of the control, the current font, and the value of the layout properties Dock and Anchor.
Complex layouts, when a container auto-sizes based on its children and the children are either docked or anchored to the same container, may cause a circular layout arrangement. Wisej.NET is able to handle most of these cases, but it may cause problems or complex reflows under certain circumstances.
Labels are always created in the designer with AutoSize = true, but when you create a label by code, the AutoSize default value is false.
When AutoSize is true, the designer will not show the grab handles used to resize the control. When you change the content, the padding, or the font, the size of the label will grow to fit the text.
Autosizing is not supported when AllowHtml is true since it's not possible to accurately measure HTML text on the server. See HTML Autosizing.
When the label is anchored or docked to the parent, the auto-sizing system grows the label horizontally and then vertically when the anchoring or docking limits the horizontal size.
Buttons are always created in the designer with AutoSize = true, but when you create a button by code, the AutoSize default value is false.
The auto-sizing rules are the same used by the Label control. However, the Button control also implements the AutoSizeMode property (like a container). By default, the AutoSizeMode property is set to GrowOnly, which means that the button will grow to fit the content but will not shrink smaller than the initial size. When AutoSizeMode is set to GrowAndShrink, the button will shrink to the minimum size necessary to fit the content.
All editor and list controls expose the AutoSize property. However, only the editors (TextBox, DateTimePicker, ComboBox, etc) are created in the designer with the AutoSize property initialized to true. When you create these controls by code, the AutoSize property is always initialized to false.
Additionally, the height of the editors is set in the theme. Wisej.NET will use the height in the theme as the minimum height when calculating the auto-sizing dimensions.
Auto-sized containers behave differently from auto-sized labels, buttons, and editors because they calculate their preferred size by fitting all their children, which in turn may also have the AutoSize property set to true, and may be docked or anchored to their container, in a multi-level layout.
Containers expose the AutoSizeMode property to control whether the container can shrink below its original size. By default, the AutoSizeMode property is set to GrowOnly, which means that the container will grow to fit the content but will not shrink smaller than the initial size. When AutoSizeMode is set to GrowAndShrink the container will shrink to the minimum size necessary to fit the content.
A container in the designer may shrink to a size of 0,0 when using AutoSize=true and AutoSizeMode=GrowAndShrink. In this case, you can select the container using the document outline, or by dragging the pointer around it to "catch" the control.
All Wisej.NET controls expose the MaximumSize and MinimumSize properties. They control the maximum and minimum size of a control, regardless of the control's Dock or Anchor or AutoSize values. The minimum and maximum sizes are always enforced.
You can specify only the width or only the height in either the MaximumSize or MinimumSize properties. Leaving the height or width set to 0 indicates that it should be ignored.
Wisej.NET cannot properly auto-size a control when the AllowHtml property is set to true. It is impossible to measure HTML content on the server. However, you can use the Wisej.Base.TextUtils class to request a correct measurement from the browser:
The alternative asynchronous version, without the callback method, is:
The auto-sizing system (when the AutoSize property is true) asks each auto-size control to calculate its preferred size and uses that size to calculate the auto-size.
To implement your own modified auto-sizing calculation, simply override the GetPreferredSize(proposedSize) method and return a new Size. In the override, you may also calculate your own proposed size and then pass it to the base implementation of GetPreferredSize().
Adjusts the size of a container and all its children when the font size changes.
All Wisej.NET container classes support thee modes of auto-scaling through the AutoScaleMode property:
None. No autoscaling is performed.
Font. The container and all its children are automatically scaled when the font changes.
Inherit. Inherits the AutoScaleMode from the parent.
Autoscaling works by calculating the difference in size between the previous font and the new font. It is applied to all child controls size and location, and each control may scale its own internal components. For example, the DataGridView autoscales the width of its columns.
This feature allows an application to resize a page, window, or just a single control, to fit the content to a different font.
Enables scrollbars on a container when the content overflows.
All Wisej.NET containers can scroll their content when the AutoScroll property is set to true (default is false - the content is truncated). When AutoScroll is true, Wisej.NET automatically shows or hides the horizontal or vertical scroll bars, unless the property ScrollBars has a value different than Both.
Once AutoScroll is true, and the container is able to scroll its content, you can control which scrollbar is visible by setting the ScrollBars property:
Both (Default). Horizontal and Vertical Scrollbars are shown or hidden as needed.
None. Scrollbars are never displayed, it's similar to setting AutoScroll = false.
Horizontal. Only the horizontal scrollbar is shown if needed.
Vertical. Only the vertical scrollbar is shown if needed.
Hidden. The scrollbars are never shown but touch scrolling and wheel scrolling is supported. It's usually used for mobile apps when the scrollbars should not be visible.
Check whether the horizontal scrollbar using the HorizontalScroll.Visible property, and if the vertical scrollbar is visible using the VerticalScroll.Visible property.
Regardless of the AutoScroll and ScrollBars properties, Wisej.NET applications can read or set the scroll position (forcing a scroll) of the container using the VerticalScroll.Value and HorizontalScroll.Value properties.
The scrolling area is calculated to fit the content exactly. If you want to add some margin at the bottom or to the right of the content, use the
You can also set a minimum size for the viewport (the scrolling area) to make the container scroll the content regardless of the space occupied by the child controls.
The Scroll event is one of the lazy events (fired only if there is a handler attached). When you handle the event, Wisej.NET will fire it every time the scroll position of either scroll bars (even if set to Hidden) changes.
In the event handler_,_ you can check both the e.OldValue and e.NewValue to determine if the scrollbar was moved up or down, or the e.ScrollOrientation to determine if the Scroll event was fired by the horizontal or vertical scrollbar.
You can also use the e.Type enumeration to determine if the scroll position changed because of a Decrement scroll, an Increment, or if the scroll position was dragged to the First (top or left) position or to the Last (bottom or right) position.
Wisej.NET fully supports touch scrolling and inertia scrolling. When the user swipes a touch device it will initiate the inertia scrolling which will keep scrolling and firing the Scroll event while it slows down.
When RightToLeft is true, the vertical scrollbar and the corner grip are automatically moved to the left. This is separate from the mirroring feature, which "flips" the layout of the child controls. See Right To Left support.
Represent a Wisej.NET application session. Provides methods and events to manage the application in the context of the current session
The Application class exposes to the application everything it needs to interact with the session, the user's browser, and all system events. It is a static class but all the properties, methods, and events are isolated by session.
You can use it to:
Save custom data in the Application.Session object.
Read the server variables in the Application.ServerVariables collection.
Read the Default.json configuration in the Application.Configuration property.
Handle application's exceptions using the Application.ThreadException event.
Handle the session disposal using the Application.ApplicationExit event.
Manage session expiration with the Application.SessionTimeout event.
Detect changes in the client device profile using the Application.ResponsiveProfileChanged, see Responsive Properties.
Access the logged-in user through the Application.User and Application.UserIdentity properties.
Read the current Application.Url and the Application.StartupUrl to extract the arguments, or use Application.QueryString for the collection of the argument name and values in the URL.
Download files to the browser with Application.Download() or open them in the browser using Application.DownloadAndOpen().
Change the culture programmatically by setting the Application.CurrentCulture property.
Read the current theme using the Application.Theme property.
Manage the browser's cookies using Application.Cookies or Application.Browser.CookieStorage. See Cookies for more details.
Application.Session is a dynamic object that can store any kind of object. You can use it as if it was a regular object like this:
Notice that since Application.Session is a dynamic object you can just add any field. You are just limited by the name since it must be compilable. If you want to use a variable name with dots, dashes, or any non-compilable character, use it through the indexer:
Option Strict Off
In VB.NET in order to use dynamic fields, you must have Option Strict Off. Otherwise, always use the Session with the (name) indexer.
All the server variables that are supported by the Web server are available in Application.ServerVariables. Some well known and common server variables are also available as properties of the Application class:
UserAgent is "HTTP_USER_AGENT"
UserHostAddress is "REMOTE_ADDR"
UserHostName is "REMOTE_HOST"
UserLanguages is "HTTP_ACCEPT_LANGUAGE" split by a comma
ServerName is "SERVER_NAME"
ServerPort is "SERVER_PORT" parsed into an integer
There are many global events exposed by the Application class. They let your code receive all sorts of notifications from the Wisej.NET infrastructure.
In addition to the regular exception handling that you have in your code, Wisej.NET lets you handle any unhandled exception through the Application.ThreadException event.
There are three events that are relevant to the session management system in Wisej:
ApplicationStart
Fired after the application is started, after the Program.Main() method is executed. It is fired only once for each new session.
ApplicationExit
Fired when the session is expired and is being disposed. At this point, the session is not recoverable. This is similar to a desktop application being closed.
SessionTimeout
Fired when the session is about to time out due to user inactivity. You can suppress the default behavior setting e.Handled = true. Otherwise, Wisej.NET will show the built-in SessionTimeoutForm.
Use Application.ThreadBegin and Application.ThreadEnd to receive a notification every time Wisej.NET starts a new thread processing code in your application, including Application.StartTask(). This event can be used to clear or initialize thread static variables using the advanced coding pattern below:
The code above shows a static property that is backed by a [ThreadStatic] field. When the field is null, it is initialized from the value stored in the application's session object. When it's not null, it is returned immediately. This pattern allows the creation of very fast session statics that only access the session lookup object once.
Use the Application.Idle event to execute code after the current request is executed, and all the events have been dispatched but before the response is sent to the client.
You can achieve the same using the Application.Post() method (similar to Control.Invoke) to register a code block that will be executed at the end of the current request.
With Application.AddEventFilter(filter) you can inject an object into the Wisej.NET event pipeline and pre-process all the events that coming from the browser for all the controls in the application.
With Application.AddEventFilter(filter) you can inject add an object into the Wisej.NET event pipeline and pre-process all the events that are coming from the browser for all the controls in the application.
All you need to do is implement the Wisej.Core.IEventFilter single method PreFilterEvent(e). You may also implement that IEventFilter interface in a control class and register a specific control as an event filter.
Return true to indicate that your code has handled the event and to stop Wisej.NET from dispatching it any further, or return false to let Wisej.NET continue dispatching the event.
There are two cookies objects in Wisej:
Application.Cookies is a collection of Cookie objects.
Application.Browser.CookieStorage connects the application to the browser's cookies.
You can read the cookies from the browser either using the Application.Cookies collection or directly through the CookieStorage. The Application.Cookies collection is populated when the application starts up. It receives all the cookies that are available on the browser.
Adding, changing, deleting, reading cookies is all done using the Application.Cookies collection:
Remember that when using the Cookies collection cookies are loaded from the browser only once when the application is loaded (or refreshed) and updated back in the browser only after the request is completed. Adding a cookie to the collection doesn't save it to the browser until the current execution is completed.
As an alternative, you can use the Application.Browser.CookieStorage object. It's not a collection and it doesn't contain any cookie information. It's a connection to the browser's storage and lets you read and write cookies directly from/to the browser:
Consider the Application.Browser object as a representation of the individual user's browser window through the Wisej.Core.ClientBrowser class. Wisej.NET initializes and updates the object with all sorts of information regarding the user's browser:
Device is a string that identifies the device type: "Mobile", "Tablet" or "Desktop".
CultureInfo is the primary culture defined in the browser matched to a CultureInfo instance
Type is a string that identifies the browser type.
ScreenSize is the size of the user's device screen.
Size instead is the size of the browser window.
Refer to the API documentation for the full list of properties.
The Browser.Feature object is a dynamic object that defines the features that are supported by the browser. It's an ever changing list that depends on the browser and the features that Wisej.NET detects at startup. Currently, it is implemented like this:
To test if a browser supports a specific feature, simply check the field name: i.e. Application.Browser.Features.speechRecognition == true.
Browser.UserData is also a dynamic object that is populated by Wisej.NET at startup. It allows a web application to save and send custom data to the Wisej.NET application before it is loaded. It is mostly useful to process a POST request, and OAuth2 and other Single Sign On (SSO) systems.
For example, if another system redirects the user to your Wisej.NET web application using a POST request because it is also sending some data, you cannot receive the POSTed data in Program.Main() because the Wisej.NET application is started in an Ajax request.
In cases like this, change your Default.html page into a Default.aspx page (don't forget to change it also in Default.json), read the POSTed data in the code behind and save it to a JavaScript variable named Wisej.userData.
The sample startup page above receives "Name" and "LastName" from a POST request, saves them into a JavaScript object and saves the object in Wisej.userData. It will be available to the Wisej.NET application as a dynamic object in Application.Browser.UserData.
Access the browser's storage system using the Application.Brower object. All the storages have the same methods and work exactly the same. You can read, write, and enumerate the values either using a callback or the async/await pattern. All methods are asynchronous because they all interact with the browser directly.
There are three storages supported:
The stored data is saved across browser sessions.
The stored data is cleared when the page session ends. A page session lasts as long as the browser is open, and survives over page reloads and restores.
Cookies are saved with the browser and are cleared depending on their expiration, scope, etc.
Wisej.NET projects already include a default favicon.ico file at the root. That is the icon that the browser shows on the tab page and in the page's overview. However, being a file, once you create it it's difficult to change dynamically.
The Application class allows your application to change both, the favicon and the title of the page, dynamically at any time through these properties:
Application.FavIcon. Changes the favicon using an Image object.
Application.FavIconSource. Changes the favicon using a source string: a URL, embedded resource, or theme icon.
Application.Title. Changes the title of the application in the browser.
You can print (print preview in the browser and then print), any page, window, dialog, or specific control. it's quite easy, simply use Application.Print() or Application.Print(control).
The first will print the entire surface of the browser.
The second allows you to specify a control to isolate and print. You can indicate a window or just a data grid, an image, a panel, etc...
The Application class also allows your application to download a file to the users browser, or to download & open a file in the browser in any tab. There are two overloaded methods:
Application.Download(). Takes a file, a stream, or an image and an optional filename to send to the browser.
Application.DownloadAndOpen(). Takes the same arguments as Download() plus a string indicating the name of the target tab where the browser should open the file after downloading it.
Play sounds on the user's browser using the Application.Play() method and overloads:
Application.Play(MessageBoxIcon). Plays a predefined sound that matches the MessageBoxIcon value.
Application.Play(url). Plays the sound in the specified .wav file. It can also be a data URL.
Use Application.Eval() and Application.Call(), or Application.EvalAsync() and Application.CallAsync() to invoke JavaScript code or functions in the global context.
See also:
Application.LoadPackages() and Application.LoadPackagesAsync() loads a list of .js or .css files in the order they are passed to the method and in sequence. Each file is loaded only after the previous is loaded, allowing the loading of dependencies.
Each entry has the following properties:
Name. Unique name of the .js or .css file to load. It's used to cache the file on the client and loads it only once even if Application.LoadPackages() is called multiple times, or if a Widget class loads the same file.
Source. Is the URL from where to load the file.
Integrity. Is the optional hash code used to verify that the file hasn't been tampered with. See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script.
LoadPackages() takes a callback method as the last optional argument with a boolean result parameter. Wisej.NET calls this method passing true when all the packages have been loaded successfully, or false if any package fails to load.
LoadPackagesAsync() is the same as LoadPackages() but instead of using a callback to notify the application, it's an awaitable method.
Touch events compatibility and emulation.
Wisej.NET supports all touch events on mobile and touch devices, and it simulates most of the touch events on desktop non-touch devices.
The biggest advantage of being able to use the same events on any device, regardless of their touch-hardware, is to reduce the complexity of the code and handle only one set of events.
Wisej.NET supports the following touch events:
Tap. Fired when a pointer taps on the screen.
LongTap. Fired when a pointer holds on the screen.
Pinch. Fired when two fingers moved away or toward each other.
Swipe. Fired when a pointed swiped over the screen.
Track. Fired when a pointer grabs a control and moves over it.
TouchStart. Fired when a touch point is placed on the screen.
TouchMove. Fired when a touch point is moved over the screen.
TouchEnd. Fired when a touch point is removed from the screen.
TouchCancel. Fired when a touch point is canceled by the implementation. For example, if a new item is created on top of the surface that fired TouchStart.
Event handling for these events is activated only if there is an event handler attached. See Lazy Events.
Tap. Similar to Click.
LongTap. Fired when the mouse is pressed and held down.
Swipe. Fired when the mouse is pressed and moved quickly.
Track. Fired when the mouse is pressed and moved.
TouchStart. Fired when the mouse is pressed.
TouchMove. Fired when the mouse moves over the control. Similar to MouseMove.
TouchEnd. Fires when the mouse is released.
See what data you get on a desktop for a simulated Swipe event.
Event routing concepts.
Event routing is a cornerstone of the Wisej.NET architecture. Wisej.NET client-side JavaScript widgets can fire events on the server and server-side components can fire and handle events synchronously or asynchronously (out-of-bound) using the .NET standard events system.
Handling events is as simple as attaching a listener to the event of overriding the equivalent OnEvent method. There is really nothing else to it.
Another way to handle events in derived classes is to simply override the OnEvent methods and process the event before or after it's fired.
Note that Wisej.NET is able to inform the server of the mouse location (relative to the browser page) as well as the keyboard state, mouse buttons, and wheel delta.
Touch events from mobile devices are all translated to the appropriate mouse events.
All pointer events on all components carry the Role property. This property contains the value of the "role" attribute of the specific HTML element that was clicked by the user.
In most cases it is just an empty string. However, you can use this feature to "deep click" inside a component and detect where the user clicked. For example, if you place HTML content in a DataGridViewCell like this:
"<span>Hello</span><img src="edit.png" role="edit"/>"
You can handle the CellClick event (or any other cell pointer event) and check whether the value of the e.Role property is "edit". This works for labels, buttons, ListView, and any component in Wisej.NET that can display HTML content.
There is a group of "critical" events that are not fired back to the server unless the application has specifically attached to the handler. These are events that would typically fire multiple times.
MouseMove
MouseEnter
MouseHover
MouseLeave
MouseWheel
KeyDown
KeyPress
KeyUp
QueryContinueDrag
DragDrop
DragEnter
DragOver
DragLeave
Swipe
Paint
Pinch
Rotate
Track
TouchStart
TouchEnd
TouchCancel
Scroll
ModifiedChanged
LoadCompleted
ItemMouseHover
CellMouseEnter
CellMouseLeave
CellMouseMove
Once a handler is attached, you may also override the OnEvent method in a derived class.
Out-of-bound events are events fired outside of a browser request (user action). For example, an event fired by a thread monitoring the stock market is an out-of-bound event since the thread is running in the background and is unaware of any browser activity.
The client may also fire unattended events back to the server. However, these are in-bound events since the server is processing a request from the browser and has a valid session to work with.
When processing out-of-bound events you are processing a background task, which is a thread that has absolutely no knowledge of the session that is handling the event. Handling out-of-bound events - something close to impossible with other systems - is easy with Wisej, all you need to do is wrap the handling code in Application.RunInContext(component, ()=>{ code }) or Application.Update(component, ()=>{ code }).
The only difference between RunInContext and Update is that the Update call pushes any changes to the visual components back to the client.
Once you are back in context, you can handle any component in the user session: update text, hide, show, move. There are no limits to what you can do using Wisej.NET Real-Time features.
When creating new Wisej.NET components and widgets, or integrating existing jQuery or other third-party JavaScript widgets, you will most likely need to fire an event from JavaScript running in the browser back to the server and handle it as any other .NET event.
This is how you fire the event from a Wisej.NET widget:
The example below shows how to register a Wisej.NET control to receive custom events and how to handle the data transported with the event.
When integrating third-party widgets, you can handle and process their events in JavaScript and send back to Wisej.NET a custom event of any type. All you need to do is to handle their events as indicated in the third-party widget's documentation and then fire it to Wisej.
Add small buttons inside a control adding custom functionality.
Several controls in Wisej.NET support the Tools property, which allows an application to "insert" custom tool buttons inside the control. It's an extremely efficient way to build flexible and modern controls in a web application.
Tool buttons can be located to the left or right of the target control, can be enabled or disabled, can automatically hide when the control loses the focus, can be always hidden, can be toggled on or off, and can have their own tooltip.
Image and ImageSource indicate the icon of the tool.
Name is the name that your app can use to identify which tool has been clicked when handling the ToolClick event.
ToolTipText shows a tooltip when the pointer is over the tool.
AutoHide hides the tool when the target control is not focused.
Enabled can enable or disable the tool.
Position indicates where inside the control to locate the tool.
Pushed sets the theme state of the tool to "pushed".
Visible can show or hide the tool.
When a control has the Tools property it also implements the ToolClick event. Some controls implement the additional ToolPosition property allowing the application to move the tools to the Top, Bottom, Left (vertical layout), or Right (vertical layout).
These controls support the Tools system in the predefined position, inside the control.
TextBox
TagTextBox
MaskedTextBox
DateTimePicker
ComboBox
ListBox
TreeView
Panels support the Tools system only when the header is visible, and automatically change the orientation of the tools when the panel is collapsed to the left or right side:
Panel
FlowLayoutPanel
TableLayoutPanel
FlexLayoutPanel
AccordionPanel
These controls support the Tools system at one of the four positions (Top, Left, Right, Bottom) indicated by the ToolPosition property:
DataGridView
ListView
MonthCalendar
Forms support the Tools system in their caption, next to the standard buttons.
Tools are styled independently in the theme. You can, however, style the container of the tools and the child tool icons depending on where they are used.
The container of the tools uses the "toolcontainer" appearance and its child buttons use the "toolcontainer/button" appearance. In addition to the default states, the control that implements the tools adds these states, allowing the theme to adapt the tool container to the type of control:
Form
"caption"
Panels
"panel"
Editors
"editor"
ListBox
"listbox"
DataGridView
"datagrid"
MonthCalendar
"calendar"
ListView
"listview"
TreeView
"treeview"
When the toolcontainer is positioned to the Top or Bottom it_ _also has the state "horizontal", when it's positioned to the Left or Right, it has the state "vertical".
All the controls that support the Tools system, also implement the ToolClick event. When you handle the ToolClick event you can determine which tool was clicked by testing the Name property.
If you add the tools programmatically, you can also detect the clicked tool by comparing the e.Tool reference.
Color and font concepts.
All controls in Wisej.NET have at least these three properties:
BackColor. Sets the background color of the control. Returns the control's background color or the inherited color.
ForeColor. Sets the text color of the control. Returns the control's text color or the inherited text color.
Font. Sets the font of the control. Returns the control's font or the inherited font.
Some controls may have additional color properties, the names always end with "Color", and may hide the base BackColor or ForeColor properties. Each control (its corresponding widget) renders these properties on the client.
For the colors, you can use any System.Drawing.SystemColors, any named color in System.Drawing.Color, or create a new color either by theme name or passing the RGBA values.
For the fonts, you can use the theme fonts by name, any System.Drawing.SystemFonts, or create new fonts.
The font you use must be installed on the server and it must be supported by the browser. If it's not a standard web font, then you need to add the font to the theme or a global CSS.
Examples of color and font assignments:
Some properties in Wisej.NET are so-called "Ambient Properties". When the property is not set, it returns the parent's value:
BackColor
ForeColor
Font
Visible
Enabled
In some cases, this behavior may be confusing, especially if the application sets a property and then expects to read back the same value. For example, if you set the Visible property to true but the parent is false, reading it back will return false.
You can use any font you like with Wisej. However, if the font is not known by the browser you need to add it to your theme - either create a custom theme, or use a mixin, or add it to a global .css file.
All Color properties support the built-in color picker dialog. It allows you to:
Pick any color from the color palette, or move the picker anywhere on the screen to sample the color directly from the display.
Select any standard web color.
Select any color defined by the current theme.
Select any system color from the SystemColors enumeration. These colors are also translated by the current theme.
All Font properties support the built-in font picker dialog. It allows you to:
Pick a known standard web font, change the style and the size. You can pick multiple fallback fonts.
Pick one of the fonts defined in the current theme. Once you pick a theme font, you can switch to the first tab to change the style and size.
Use the System.Drawing.ColorTranslator class to convert HTML string to and from a Color object.
Custom painting and drawing in the browser.
All Wisej.NET controls support custom painting. Simply attach to the Paint event and draw whatever you like, it will display in the browser as the background of the control.
You can't use the BackgroundImage and custom painting. Painting will take over the backgound.
There is no limit to what you can draw: e.Graphics is a GDI+ object that Wisej.NET sends back to the browser as a png image and immediately removes from memory.
This code
Produces this circle.
All the HTML5 Canvas method are available in C# or VB.NET on the server. All the arguments are the same and the names are the same. The only different is that the first character is uppercase and the radians are degrees for simplicity.
Tooltip concepts.
Tooltips can be assigned to controls and to child elements of controls. i.e. TreeNode, ListView or ComboBox items, TabPage, DataGridView Cells, ListView items, etc.
When a control can display a tooltip in relation of a child element, it usually exposes the ShowToolTips or ShowNodeToolTips or ShowCellToolTips property. See the documentation for each control for more details.
In the theme you can control any aspect of the tooltip widget, just like any other widget, plus additional properties that control the location and alignment of the tooltip:
offset [offsetTop, offsetRight, offsetBottom, offsetLeft]: Adds the specified distance in pixels between the tooltip widget and the target widget.
placeMethod: indicates whether to place the tooltip in relation to the target widget or the current position of the pointer; values are "widget", "pointer".
placementModeX and placementModeY: indicate how to calculate the placement of the tooltip when the preferred position doesn't fit in the browser; values are:
"direct" to preserve the calculated position even if it doesn't fit in the browser.
"keep-align" to adjust the position to fit in the browser, i.e. "bottom-center" may become "top-center".
"best-fit" to preserve the preferred position but offsetting the tooltip enough pixels to fit in the browser.
position: indicates where to place the tooltip in relation to the target widget; values are "top-left", "top-center", "top-right", "bottom-left", "bottom-center", "bottom-right", "left-top", "left-middle", "left-bottom", "right-top", "right-middle", "right-bottom"
states: indicates the placement of the tooltip in relation to the target widget; values are "p_lacementLeft"_, "placementRight", "placementAbove", "placementBelow" .
There are two kinds of tooltips in Wisej: the regular tooltip that is shown when the pointer rests for a certain amount of time over a control or an element of a control, and the error tooltip that is shown when the pointer rests over an "invalid" control.
All controls that expose the InvalidMessage (available in the designer) and Invalid (only available in code) properties. You can set the Invalid property by code simply by assigning it, otherwise it is set to true or cleared when the control is validated.
The ToolTipText property can be bound to a data source like any other bindable property.
Shared features and properties among all Wisej.NET controls.
All Wisej.NET controls are derived from the Wisej.Web.Control class and share many common properties and methods. While some properties are obvious: BackColor, Font, Text, etc. some other are related to more advanced functionality usually not found in any other web system.
The list below is not complete, but it provides a lot of useful information.
When true, the control is "transparent" to pointer events. If you place a Button on a Page and set the property Anonymous of the button to true, when the user clicks on the button, the event will bubble to Page and will fire on the Page: the button is completely transparent to the pointer.
Some events have the OriginalTarget property. If you have an event that carries the OriginalTarget, you can retrieve which anonymous control the user interacted with.
It's the name of the appearance in the theme that a control uses to style itself in the browser.
The value is null by default, which means that the control will use its default appearance name.
When true, all pointer events, anywhere on the browser and on any control, are captured and redirected to the control capturing the pointer. A resize action is an example of capturing the pointer.
Determines how a control is resized with its parent. The priority of the docking is determined by the order of the controls.
Docking is also affected by the control position in the control list. Controls first are close to the viewer in a hypothetical 3D model.
Anchoring is similar to Docking but it "anchors" a specific side to the parent's control and keeps the relative distance.
When a control is not docked on both sides the relative distance is preserved proportionally on both sides. It can be used to keep a control centered vertically or horizontally.
Enables or disables a control and all its children at any level. Disabled controls are rendered as enabled in the designer.
When reading the value of the Enabled property you may get _false _even when you have set the property to true if any parent is disabled.
Hides or shows a control. Controls are rendered on the client only when they are made visible once.
Setting Visible to true is the same as calling the Show() method, and setting it to false is the same as calling the Hide() method.
When reading the value of the Visible property you may get _false _even when you have set the property to _true _if any parent is not visible.
Sets the tooltip text on any control.
Data binding concepts.
In Wisej.NET, data binding refers to the process of connecting UI elements on a Wisej.NET UI container (i.e., Form, Page, UserControl, Desktop, ...) with data sources, such as databases or data objects. This allows the UI to display data from the data source, and to automatically update the data source when the user modifies the data in the UI.
There are two types of data binding in Wisej.NET: simple binding and complex binding.
Simple binding involves binding a single UI element, such as a text box, to a single data field, such as a customer name. When the data source is updated, the value of the text box will automatically be updated to reflect the new value of the customer name field.
Complex binding involves binding a container control, such as a grid, to a data source. Each row in the grid is bound to a record in the data source, and each cell in the grid is bound to a field in the record. When the data source is updated, the grid will automatically be updated to reflect the changes.
When you are building controls that interact with data, you sometimes need to bind a control to a type, rather than an object. You typically need to bind a control to a type at design time, when data may not be available, but you still want your data-bound controls to display data from a type's public interface.
Create a Windows Forms project (File > New > Project > Visual C# or Visual Basic > Web > Wisej.NET Web Page Application).
In Design view, drag a BindingSource component onto the form.
In the Properties window, click the arrow for the DataSource property.
In the DataSource UI Type Editor, click Add Project Data Source.
On the Choose a Data Source Type page, select Object and click Next.
Select the type to bind to:
If the type you want to bind to is in the current project, or the assembly that contains the type is already added as a reference, expand the nodes to find the type you want, and then select it.
-or-
If the type you want to bind to is in another assembly, not currently in the list of references, click Add Reference, and then click the Projects tab. Select the project that contains the business object you want and click OK. This project will appear in the list of assemblies, so you can expand the nodes to find the type you want, and then select it.
Click Next, and then click Finish.
Add a TextBox to the form.
In the Properties window, expand the (DataBindings) node.
Click the arrow next to the Text property.
In the DataSource UI Type Editor, expand the node for the BindingSource added previously, and select the property of the bound type you want to bind to the Text property of the TextBox.
Developers can bind to a strongly-typed generic list (List<T>) or create a new BindingList<T> implementation to bind data to.
The List<T> class is the generic equivalent of the ArrayList class. It implements the** IList<T>** generic interface by using an array whose size is dynamically increased as required.
You can add items to a** List<T> **by using the Add or AddRange methods.
The BindingList<T> class can be used as a base class to create a two-way data-binding mechanism. BindingList<T> provides a concrete, generic implementation of the IBindingList interface. This is an alternative to implementing the complete IBindingList interface, which can be difficult because of the subtle interaction between IBindingList, IEditableObject, and the associated CurrencyManager. However, the typical solutions programmer will use a class that provides data binding functionality, such as BindingSource, instead of directly using BindingList<T>.
BindingList<T> supports factory-created instances through the extensible AddNew method. (This same type of extensibility is also found in other classes, such as BindingSource) In addition, since this class implements the ICancelAddNew interface, it enables transactional commits or rollbacks of the new item through the EndNew and CancelNew methods.
ADO.NET provides consistent access to data sources such as SQL Server and XML, and to data sources exposed through OLE DB and ODBC. Data-sharing consumer applications can use ADO.NET to connect to these data sources and retrieve, handle, and update the data that they contain.
Entity Framework Core is a modern object-database mapper for .NET. It supports LINQ queries, change tracking, updates, and schema migrations. EF Core works with many databases, including SQL Database (on-premises and Azure), SQLite, MySQL, PostgreSQL, and Azure Cosmos DB.
Language-Integrated Query (LINQ) is the name for a set of technologies based on the integration of query capabilities directly into the C# language. Traditionally, queries against data are expressed as simple strings without type checking at compile time or IntelliSense support. Furthermore, you have to learn a different query language for each type of data source: SQL databases, XML documents, various Web services, and so on. With LINQ, a query is a first-class language construct, just like classes, methods, events.
Example:
Result:
The CurrencyManager in Wisej.NET manages a list of Binding objects.
Each Wisej.NET Form has at least one BindingContext object that manages the BindingManagerBase objects for the form. Because the BindingManagerBase class is abstract, the return type of the Item[] property is either a CurrencyManager or a PropertyManager. If the data source is an object that can return only a single property (instead of a list of objects), the Type is a PropertyManager. For example, if you specify a TextBox as the data source, a PropertyManager is returned. On the other hand, if the data source is an object that implements IList or IBindingList, a CurrencyManager is returned.
For each data source on a Wisej.NET Form, there is a single CurrencyManager or PropertyManager. Because there may be multiple data sources associated with a Wisej.NET Form, the BindingContext enables you to retrieve any particular CurrencyManager associated with a data source.
The Format event is raised when data is pushed from the data source into the control. You can handle the Format event to convert unformatted data from the data source into formatted data for display. When data is pulled from the control into the data source, the Parse event is raised to unformat the displayed value, then the Format event occurs to reformat the data for display. This ensures that the bound control displays correctly formatted data regardless of whether the user enters formatted or unformatted data in the control.
The Format event is raised when data is pushed from the data source into the control. You can handle the Format event to convert unformatted data from the data source into formatted data for display. When data is pulled from the control into the data source, the Parse event is raised to unformat the displayed value, then the Format event occurs to reformat the data for display. This ensures that the bound control displays correctly formatted data regardless of whether the user enters formatted or unformatted data in the control.
The Format and Parse events allow you to create custom formats for displaying data. For example, if the data in a table is of type Decimal, you can display the data in the local currency format by setting the Value property of the ConvertEventArgs to the formatted value in the Format event. You must consequently unformat the displayed value in the Parse event.
The INotifyPropertyChanged interface is used to notify clients, typically binding clients, that a property value has changed.
For example, consider a Person object with a property called FirstName. To provide generic property-change notification, the Person type implements the INotifyPropertyChanged interface and raises a PropertyChanged event when FirstName is changed.
For change notification to occur in a binding between a bound client and a data source, your bound type should either:
Implement the INotifyPropertyChanged interface (preferred).
Provide a change event for each property of the bound type.
Do not do both.
Allows the user to move and resize controls in the browser.
When a control is resized or moved, it will change the Size and Location properties on the server and fire the related events.
Resizable controls can resize in two modes: Live or Frame. By default all the resizable controls, including Forms, use a resize frame and then resize the actual control when the user releases the pointer.
Some controls expose the LiveResize property that lets you change the default behavior and update the control as the user resizes it:
Form. The window is resized immediately.
DataGridView. Columns are resized immediately.
ListView. Columns are resized immediately when Detail view.
When LiveResize is true, every movement of the mouse or the pointer or the touch causes a resize event and it can get heavy on the server.
It's a simple boolean property. Set it to true to make a control movable.
If you set the Movable property to false on a Form window then it will be displayed at the specified location and the user will not be able to move it.
The ResizableEdges property is a flags enumeration that takes the AnchorStyles values. You can enable any of the four sides of a control to be resizable, or any combination of the sides.
Combining the ResizableEdges, Dock, and Anchor properties is an easy and flexible way to create a splitter system without adding split containers or other controls.
Just putting together a Button with ResizableEdges=Right and Dock=Left, a TreeView with Dock=Fill, and a DataGridView with ResizableEdges=Bottom and Dock=Top, inside a Panel creates a flexible composite control.
The Location and Size properties of the control will not change while the user is dragging or resizing the control on the browser.
Wisej.NET provides advanced states and events that allow your application to style a control when it's being moved or resized and to detect when the moving or resizing operations start and end.
When moving, it adds the state "move".
When resizing, adds the state "resize".
When moving starts, fires the event "startmove".
When moving ends, fires the event "endmove".
When resizing starts, fires the event "startresize".
When resizing ends, fires the event "endresize".
These states are not defined in the built-in theme, but you can use them in your theme or in a mixin.
For example, adding a mixin that extends the "tree" appearance like this:
Results in the TreeView control showing the new styled border when it's being moved by the user.
When building class libraries that target .NET 6+, the assemblies that are referenced via NuGet will not be copied to the bin folder unless the following element is added to the library's csproj file:
If a project or assembly reference is not used in the main Wisej.NET project, the referenced project's dependencies will not be loaded into the App Domain automatically.
For example:
If you create a custom control library that implements a custom Bubbles notification that gets dynamically injected into the main Wisej.NET project, you will need to call Application.LoadAssembly() on Wisej.Web.Ext.Bubbles to load the custom library's dependency into the Wisej.NET project.
Wisej.NET is indeed magic
In addition to being able to paint any control, Wisej.NET also provides a control that implements the full HTML5 canvas specification on the server.
Use the event to plug in your drawing code.
The control is entirely created in .NET using the Canvas control.
All Wisej.NET controls can be associated to a tooltip text through the ToolTipText property or the .
Check out also the for a different kind of "tooltips".
Both tooltips can be styled in a custom theme or theme mixin, or using the on the top level container.
The ToolTip property provided by the is not bindable.
You can control several aspects of the tooltip widget using the and setting the properties on the component. All the settings set on the Tooltip extender, except the ToolTipIcon and ToolTipIconSource, also apply to the ToolTipText property when the ToolTip extender is present on the same container.
Enables a control to initiate operations. When false (default), drag & drop is disabled for the control.
Enables a control be the target of the operation. When false (default), the control will deny the drop operation.
Fires the MouseCaptureChanged on the control losing the capture and on the control gaining the capture.
When true, the user is able to grab and move the control. When the user starts moving the control, it will fire the event. When done, it will fire the event and the control's Location property will be updated with the new location.
Allows you to enable any of the four sides of any control to become draggable and resizable. When the user starts resizing a control, it will fire the event. When done it will fire the event and the control's Size property will be updated with the new dimensions.
At design time use or or to alter the position of a control in the collection and adjust the docking priority.
Docking also works with . The padding of a container reduces the space used by the docked child controls.
In the designer you can use the tiny arrows that show next to the four sides to anchor or un-anchor a side. To prevent accidental anchoring, you can turn off the visual shortcut in the design toolbar using the "Show/Hide Anchors"
All controls expose the , , and properties. They allow you to define the background of any control, in addition to any image property that the control may have.
Represents an array of system and custom states. The property allows you to add system or define your own states and style them in the .
The property is a collection of JavaScript events and code that runs in the browser when the event is fired. In the JavaScript handler code refer to the event argument as "e".
accepts any CSS string that will be rendered on the client directly in the style attribute of the widget's main element.
is similar to CssStyle but it accepts one or more CSS class names and adds them to the class attribute of the widget's main element.
In you can add any JavaScript that will run when the control is first created in the browser. The script runs in the control's context (this = widget).
Invisible controls are visible in design mode. You can hide the invisible control by turning off the "Show Hidden Controls" option in the toolbar.
Every Wisej.NET control has the property; when set to true, the control is blocked by an ajax spinner.
There is an property that blocks the entire page.
If you need to run long operations and want to show a loader to block a control, you must either update the client using after setting the ShowLoader property to true, or execute the code after setting ShowLoader to true asynchronously.
Most Wisej.NET controls expose the and properties. TabStop controls whether a participates in the tabbing order. TabIndex indicates the tabbing order of the control within the parent.
You can alter the shared tooltip widget using the component. Most aspects of the tooltip system can be changed in the theme under the "tooltip" appearance key.
Wisej.NET provides several tools and methods for creating and managing data bindings, including the editor and the component.
All Wisej.NET controls support moving and resizing. It's an amazing feature unique to Wisej.
Simply set the property to true and users will be able to grab and drag the control within its parent. Enable the sides to resize using the property and users will be able to grab and drag the resizable sides!
You can enable the live resize mode on any resizable control that doesn't expose the LiveResize property by calling JavaScript in the control's property to set the "useResizeFrame" property to false:
When using the Movable or ResizableEdges properties to allow the user to move or resize a widget on the client, you can use the , , and events to detect when the user starts and ends the moving or resizing operation.
Theme appearance
"tooltip" and "tooltip-error" see Themes.
Child components
"atom" is the inner widget that shows an "icon" and a "label"; "arrow" is the widget that is attached to one of the 4 sides of the tooltip according to the placement.
Source code
There are at least three ways to add custom properties (or user data) to controls in Wisej.NET:
Extend the class
Tag property
UserData property
Extending the class is the most flexible approach but in some cases it's not feasible to create a new class of a control just to add a value use in a small specific context.
The Tag property is available at design time at provides a quick way to add custom information to an instance of a control.
The UserData property is a dynamic object that allows you to add any kind of fields to a control without having to create a new class.
All Wisej.NET control classes can be used as the base class of your classes. You can create new types of buttons, tab pages, tree nodes, grid cells, grid rows, columns, forms, etc.
For example, if you need to have a TreeNode instance that is associated with a Customer instance you can create a CustomerTreeNode class.
You can use the new CustomerTreeNode class just like the base TreeNode class, including at design time. When adding nodes at design time, the designer will show a drop down button to pick the specific TreeNode class to add.
All controls and components in Wisej.NET expose the Tag property of type object. You can "tag" any control or component with any value of any type.
The UserData property is similar to the Tag property except that it's a dynamic object that can hold any number of fields of any kind.
For example, we can "attach" a Customer instance to a TreeNode without creating a CustomerTreeNode class like this:
As shown in the code snippet above, the UserData property is a dynamic object and a dictionary.
To check whether an object has any data in the UserData dictionary without forcing the creation of the storage object, use the HasUserData property.
Properties that change their value according to the client profile.
Wisej.NET supports a unique system of "responsive properties" in order to enable an application to adapt its UI to the client browser without being limited to CSS media selectors and styles.
Conceptually it's a simple system. Certain properties, usually but not necessarily visual properties (i.e. Visible, Display, Size, Location, etc.) can hold multiple values at the same time and apply the one that matches the current client browser profile.
The only way to assign responsive properties is in the designer.
All controls expose the ResponsiveProfiles collection holding the profiles that contain different responsive property values set at design time. You can use this collection to inspect the client profiles set for the control.
See also:
Drag & drop data and files concepts.
In Wisej.NET every control supports drag & drop operations, which is different from dragging (moving) the control itself. Drag & drop means that your application allows the user to drag data from one control to another.
For example, you may want to drag a row from a grid to an input field, or within the grid to change its position, or you may want to drag a node from a tree control to another.
Drag & drop in Wisej.NET works exactly the same as in a desktop application: set AllowDrag on the control that should initiate the drag operation and set AllowDrop on the control that can receive the dropped data.
When the user starts dragging, the control will fire the DragStart event. You must handle this event and call the DoDragDrop() method, otherwise the drag operation doesn't start.
A common mistake is to call this.DoDragDrop() instead of this.[control].DoDragDrop() when handling the event in a parent container. Make sure to call DoDragDrop() on the correct target.
The code above starts a drag operation using an array of selected row indexes as the payload, the user is basically dragging an array of integers. In addition to the payload, the call above also indicates that the drag operation allows only 2 effects: Copy and Move. Conceptually it means that the payload can only be copied or moved. Another option is Link.
Now you need to handle the dropping side, on the controls that can accept the dragged payload. This is done using either DragEnter or DragOver or both.
The code below activates the Move drop effect when the user drags the payload over button1. It also checks if the payload is present and is an array of integers.
The last step is to receive the dropped data. You can do that by handling the DragDrop event. it is fired when the user finally releases the pointer over the target control.
The data object exposed by the DragEventArgs event data can hold any type of data and provides all sorts of functionality to check the presence of the data and extract the data.
When the target is not a simple control like a button or a field, but it may contain multiple inner parts, you may need to detect where exactly the payload was dropped. In a ListBox you want to detect the item that received the drop, in a TreeView the child node, or in a DataGridView the specific row.
You will find the exact target in the e.DropTarget property. This is different for each control.
ListBox
Item
TreeView
TreeNode
DataGridView
DataGridViewCell
ListView
ListViewItem
In addition to the DropTarget property, the event data contains the location of the pointer and the key state of the keyboard to allow your app to detect what the user is pressing while dragging, in case you want to handle different drag effects.
When dragging, Wisej.NET shows the typical drag cursor you see in a desktop application (themeable).
However, you can change the drag cursor at any time and use any image of any size simply by assigning the e.Image, or e.ImageSource and e.ImageSize properties in any of the drag & drop events.
You can check the files being dropped in the DragEnter event by retrieving the list of mime types (nothing else is available in the browser) being dropped from the data object using DataFormats.FileDrop like this:
And finally retrieve the files being dropped simply by handling the DragDrop event and using DataFormats.Files to receive an instance of the HttpFileCollection class:
It's that simple.
To enable dragging and dropping entire folders, enable the "allow.drop.folders" option in Default.json: options:{"allow.drop.folders": true}.
Common VB.NET extension methods to basic objects.
VB.NET developers may be used to the Microsoft.VisualBasic namespace for VB specific extensions. Wisej.NET provides the Wisej.Web.VisualBasic namespace with the implementation of the Interaction extensions:
Add labels to editable controls.
Allows a control to display a label without having to create a separate Label control.
When dropping a control that supports the associated label, you will find the Label field in the quick actions panel. Entering the label text automatically creates the associated label using the default properties.
You can change all the Label's properties either in the control's property panel or in code by using the Control.Label object.
You can position the label to any of the four sides plus the Inside position. When the label is positioned inside, it is displayed over the editable control and automatically resized and moved up when the user enters a value or the application assigns the Text property.
The internal layout of controls with the associated label is always managed by the widget and is controlled by these properties of the Label object: Text, Position, AllowHtml, Padding, Size, MaxSize, MinSize, and SizeType.
The outer size of the control is always the size set by the application - internally the label and the control share the outer size. You can control how much of the internal space is used by the label using the SizeType and Size properties:
AutoSize (the default) means that the label occupies exactly the space it needs and the associated control uses the remaining space.
Absolute means that the label occupies the number of pixels set in the Size property.
Percent means that the label occupies the percentage of the space indicated in the Size property. Basically the Size property is either a pixel value or a percent value.
Additionally, you can constrain the size of the label by setting the MinSize and MaxSize properties, always in pixels.
When the AllowHtml property is set to true, you can use any HTML string in the label to create labels of any complexity:
To assign a mnemonic character, type a & before the character that has become the mnemonic, set UseMnemonic to true and AllowHtml to false. Wisej.NET will render the mnemonic character underlined, which is the standard in desktop apps.
Users can now immediately focus the field simply by pressing Alt + Mnemonic character.
Only the text of the label is localizable.
The properties of the Label object are not responsive. When the control is resized, the label widget will automatically adjust its internal space, but it's not capable of changing the location of the label or change any other property in conjunction with a ClientProfile.
If you need to adjust any aspect of the label in relation to a responsive profile, handle the Application.ResponsiveProfileChanged event and change the properties in code.
Controls with the associated labels, when created in the browser, are wrapped inside an instance of the wisej.web.LabelWrapper JavaScript class.
JavaScript code that needs to interact with the editor control instead of the wrapper, should call this.getEditor() to get a reference to the wrapped editor control.
Theme appearance
Source code
Allows the user to select a folder from one of the Roots.
This class provides a way to prompt the user to browse, create, and eventually select a folder. Use this class when you only want to allow the user to select folders, not files. Browsing of the folders is done through a tree control. Only folders from the file system can be selected; virtual folders cannot.
Typically, after creating a new FolderBrowserDialog
, you set the RootFolder
to the location from which to start browsing. Optionally, you can set the SelectedPath
to an absolute path of a subfolder of RootFolder
that will initially be selected. You can also optionally set the Description
property to provide additional instructions to the user. Finally, call the ShowDialog
method to display the dialog box to the user. When the dialog box is closed and the dialog box result from ShowDialog
is DialogResult.OK
, the SelectedPath
will be a string containing the path to the selected folder.
You can use the ShowNewFolderButton
property to control if the user is able to create new folders with the New Folder button.
FolderBrowserDialog
is a modal dialog box; therefore, when shown, it blocks the rest of the application until the user has chosen a folder. When a dialog box is displayed modally, no input (keyboard or mouse click) can occur except to objects on the dialog box. The program must hide or close the dialog box (usually in response to some user action) before input to the calling program can occur.
The FolderBrowserDialog component allows for setting multiple directory roots to navigate and select a file.
Directories must have the appropriate read permissions to be discoverable by the Wisej.NET application.
The FolderBrowserDialog.SelectedPath property returns the path selected by the user, which is the virtual path relative to the root. To retrieve the physical path on the server use FileBrowserDialog.MapPath().
The FolderBrowserDialog component has an optional "?" (Help) tool that allows you to process and display information to help users navigate the control.
The FolderBrowserDialog component can be customized by applying appearances to each individual control within the dialog. This includes the tree view, buttons, and bottom panel.
To customize these controls, create a new class that inherits from FolderBrowserDialogUI
, add the custom FolderBrowserDialog
constructor, and modify the controls within it:
After applying the FolderBrowserDialog's DialogTemplate
property to the new class, the resulting popup will look like this:
For instructions on how to use a custom template to offer advanced customization of the FolderBrowserDialog, see below.
The FolderBrowserDialog is fully customizable through the DialogTemplate
property. This property, when set, will provide a custom interface for allowing users to select a directory from one of the given Roots
.
To build a new custom template, create a new Inherited Window in the project.
After clicking Add, you'll be shown a list of inheritable windows. Select FolderBrowserDialogUI
and click OK.
Using a custom template requires implementing a custom constructor for processing dialog initialization.
Prompts the user to open a file from the server.
This class allows you to check whether a file exists and to open it. The ShowReadOnly
property determines whether a read-only check box appears in the dialog box. The ReadOnlyChecked
property indicates whether the read-only check box is checked.
Most of the core functionality for this class is found in the FileDialog
class.
If you want to give the user the ability to select a folder instead of a file, use FolderBrowserDialog instead.
The OpenFileDialog filters files shown to the user based on a given pattern. For example, the filter C# files|*.cs|All files|*.*
will show files ending with .cs by default. Users can modify the filter using the dropdown menu.
The FileDialog.FileName property returns the virtual path relative to the root. To get the physical path on the server, use FileDialog.MapPath().
The OpenFileDialog includes an optional "?" (Help) tool for displaying navigation assistance.
Add at least one IFileSystemProvider
to the Roots collection before showing the dialog:
The OpenFileDialog supports customization of individual controls including textboxes and pickers.
To customize these controls:
Create a class inheriting from FileDialogUI
Add the custom OpenFileDialog
constructor
Modify the controls as needed
After applying the OpenFileDialog's DialogTemplate
property to the new class, the result looks like this:
For advanced customization of the OpenFileDialog
using custom templates, see below.
Represents a common dialog box that displays available colors along with controls that enable the user to define custom colors.
This class provides a way to prompt the user to select a color. The color can be picked either through a list of preset colors or using the visual picker. Once a color is selected, the details of the new color will be shown in a GroupBox
, along with a visual comparison of the old and new color.
The ColorDialog features several ways to get the perfect color. The Hex
, RGB
, or HSB
value can be manually entered, the user can pick a value from the Preset Colors, or fine tune a value with the Visual Picker.
The ColorDialog component can be customized by applying appearances to each individual control within the dialog. This includes the textboxes, picker, and more.
To customize these controls, create a new class that inherits from ColorDialogUI
, add the custom ColorDialog
constructor, and modify the controls within it:
After applying the ColorDialog's DialogTemplate
property to the new class, the resulting popup will look like this:
For instructions on how to use a custom template to offer advanced customization of the ColorDialog
, see below.
Wisej.NET provides editor controls for user input. These typically correspond to an <input> element in the browser.
The editors come in four categories: TextBox
, UpDown
(Spinners), Pickers, and ComboBox
controls. This section covers TextBox
, UpDown
, and Pickers, while the ComboBox is documented under Lists & Grids.
All TextBox
controls derive from the TextBoxBase
class, sharing consistent properties, events, and features.
In the browser, these render as a <div> container with an <input> element inside.
All UpDown
controls derive from the UpDownBase
class. In the browser, they render as a <div>
container with an <input>
element and two +/- buttons.
Wisej.NET includes numeric, text, and time spinners.
The DateTimePicker
is the sole Picker control, inheriting directly from the Control
base class.
Represents an <input> element that can be used to edit unformatted text.
The Wisej.Web.TextBox control enables users to enter unformatted text.
The TextBox
control accepts a single line of text. Enable the Multiline
property to allow multiple lines of text input.
The TextBox
control supports the inline Label property. This allows setting a label in relation to a TextBox
control without creating an additional Label
control.
Data binding supports formatting and value conversion through the default data binding infrastructure. The default data property is Text
.
Enable the browser's built-in spell checking by setting the SpellCheck
property to true
.
This functionality relies on the browser's language and spell checking support. Third-party spell checking is possible but outside Wisej.NET functionality.
A key Wisej.NET feature available in most controls. The Tools property enables adding internal buttons aligned left or right, with user clicks handled through the ToolClicked
event.
Some TextBox
events fire only when a handler is attached. This prevents unnecessary browser requests unless explicitly subscribed.
The KeyDown
event is a Lazy Event, preventing ajax requests for each character typed.
When extending a control class and overriding On[EventName] for a lazy event without attaching a handler, the code won't execute unless a handler is attached.
All Wisej.NET editable controls include the Watermark
property, displaying background text in empty fields.
Wisej.NET renders the watermark using the placeholder HTML attribute when supported, otherwise creating an overlaid label managed by the Wisej.NET JavaScript library.
Set the PasswordChar
property to any character or the InputType
to Password
for a password input field. The PasswordChar
value always converts to "*" as browsers control password field display. This property exists for WinForms migration compatibility.
The CharacterCasing
property forces text case transformation on both client and server. Wisej.NET performs the change while typing (client) and when setting the Text property (server).
By default, Tab moves focus to the next control and Enter does nothing. For tab characters and newlines, set Multiline
to true
and enable AcceptsTab
or AcceptsReturn
.
Limit accepted characters using either:
Set the Filter
property to a regular expression
Handle the keydown event on the client with JavaScript
Server-side KeyDown
handling cannot prevent character input as the browser processes it before server communication.
Customize TextBox
appearance through:
Properties (BackColor
, ForeColor
, BorderStyle
, Font
)
Custom theme
Theme mixin
Custom styles
For specialized UI like Material-3 animated underline on focus, use theme customization or custom styles.
The image shows a TextBox
with "border-radius:20px" in CssStyle
. For shared styles, use CssClass
and add a StyleSheet file through Default.html or the StyleSheet extender.
The TextBox
supports various <input> types through the InputType
property.
The Text
property always returns a string representing the native input value. Special input types have specific behaviors:
Radio
Clicking toggles the Checked
property and fires CheckedChanged
(not TextChanged
). Checked value is "on".
Browsers don't fire events for <input type=radio>. Content localization depends on browser language.
Checkbox
Clicking toggles the Checked
property and fires CheckedChanged
(not TextChanged
). Checked value is "on".
The AutoCompleteList
property enables browser native autocomplete with a string array.
Browser filters the AutoCompleteList
as users type.
The AutoComplete
property controls this feature. When enabled, browsers may build their own suggestions.
Common AutoComplete
options include:
An email address
Username
A username or account name
NewPassword
A new password field for account creation or password changes
CurrentPassword
The user's current password
OneTimeCode
A one-time verification code
See Mozilla Developer Site for all options.
Browser implementation controls this functionality, including when to use previous values.
Wisej.NET selects all text when tabbing between fields. Clicking places the cursor at click location.
Enable SelectOnEnter
for automatic text selection on any focus method.
EnableNativeContextMenu
(default: true
) controls the browser's context menu on right-click. Disable to prevent the native menu.
Class name
"wisej.web.TextBox" or "wisej.web.TextArea" when Multiline is true
Theme appearance
Child components
Toolcontainer state
Source code
Represents a data field that displays a list of selectable and removable tags. The control recognizes tags as the user types and adds in front of the editable field.
The Wisej.NET TagTextBox
enables users to select multiple values as tags.
The TagTextBox
control automatically resizes to fit its contents, including font size changes and tag overflow.
The TagTextBox
control provides selection from preset items defined in the AutoCompleteList
property.
Configure tag limits using these properties:
MaxLength
: Maximum characters allowed in the edit control
MaxTagCount
: Maximum number of tags allowed
MaxTagWidth
: Maximum width in pixels for tag widgets
MinFieldLength
: Minimum characters that should fit in the editable portion before wrapping
Customize tag colors using the Theme Builder, a mixin, or direct code application.
The tagtextbox
appearance includes a tag
child component, customizable for different states.
Apply custom appearance using a project mixin:
Modify the theme at runtime for custom TagTextBox
appearance:
Class name
"wisej.web.TagTextBox"
Theme Appearance
"tagtextbox", inherited from "textbox"
Child components
Toolcontainer state
Source code
Prompts the user to select a location for saving a file on the server.
This class can either open and overwrite an existing file or create a new file.
Most of the functionality for this class is found in the FileDialog
class.
The SaveFileDialog filters files shown to the user based on a given pattern. For example, the filter Image Files|*.jpg|All files|*.*
will show files ending with .jpg by default. Users can modify the filter using the dropdown menu.
The FileDialog.FileName property returns the virtual path relative to the root. To get the physical path on the server, use FileDialog.MapPath().
The SaveFileDialog validates file existence before saving to disk, helping prevent accidental file overwrites.
The SaveFileDialog includes an optional "?" (Help) tool for displaying navigation assistance.
Add at least one IFileSystemProvider
to the Roots collection before showing the dialog:
The SaveFileDialog supports customization of individual controls including textboxes and pickers.
To customize these controls:
Create a class inheriting from FileDialogUI
Add the custom FileDialog
constructor
Modify the controls as needed
After applying the OpenFileDialog's DialogTemplate
property to the new class, the result looks like this:
For advanced customization of the SaveFileDialog
using custom templates, see below.
Represents a spinner control that displays string values.
A Wisej.NET DomainUpDown
control displays a single string value selected from an Object
collection by clicking the up or down buttons. Users can enter text in the control unless the ReadOnly
property is set to true
(the string must match an item in the collection). When an item is selected, the object converts to a string value for display in the spin box.
Represents a spinner control that displays TimeSpan values.
The Wisej.NET TimeUpDown
control enables users to incrementally change values in a date text box using arrow buttons. The spin box combines a text box with its associated spin control.
The TimeUpDown
control offers three preset icon alignments: Left
, Center
, and Right
.
Represents a control that allows the user to select or type a date and a time.
The Wisej.NET DateTimePicker
control enables users to select a date and time, displaying them in the specified format. The DateTimePicker
control simplifies date and time handling by managing data validation automatically.
When representing a date, the DateTimePicker
control displays two parts: a drop-down list with a date in text format, and a calendar that appears when clicking the down-arrow. The calendar resembles the MonthCalendar
control, which supports multiple date selection.
The DateTimePicker
offers several preset formats for displaying date and time including Long
, Short
, Time
, DateTime
, and custom format configuration.
Add validation to the DateTimePicker
by specifying the format and InvalidMessage
property for handling invalid user input:
The Mask
property can provide a custom input format:
Customize the DateTimePicker
appearance through properties, theme customization, or custom styles.
The appearance properties include BackColor
, ForeColor
, BorderStyle
, and Font
.
Allows the user to enter a typed value
The Wisej.NET TypedTextBox
enables defining the Value
property type for text parsing, a .NET format string (standard or custom), and format preservation settings during editing.
Override parsing and formatting using the CustomFormatChanged
, Format
, and Parse
events.
Set CustomFormat
to a .NET format string. Reference the .NET documentation:
The ValueType
determines the Value
property type: System.String
, System.DateTime
, System.Int32
, System.Int64
, System.Boolean
, System.Decimal
, System.Double
, or System.Single
.
When KeepFormatOnEnter
is true
, formatting persists when users press enter or click within the TypedTextBox
. When false
, formatting hides during editing. For currency input, consider setting KeepFormatOnEnter
to false
to avoid confusion with currency symbols during typing.
Represents a control that enables the user to select a date using a visual monthly calendar display.
The Wisej.NET MonthCalendar
control enables date selection through a visual display. Set the MinDate
and MaxDate
properties to limit selectable dates and times.
The MonthCalendar
control supports bolded dates to define one-time, monthly, and yearly events.
The MonthCalendar
control displays multiple calendars in a grid-like structure.
The TodayDate
and TodayFormat
properties enable customized date and format settings.
Uses a mask to distinguish between proper and improper user input.
The Wisej.NET MaskedTextBox
enhances the TextBox
control with declarative input validation. The Mask
property enables specifying:
Required input characters
Optional input characters
Input type expected at each mask position (digit, alphabetic, alphanumeric)
Mask literals (characters appearing directly in the MaskedTextBox
, like hyphens in phone numbers or currency symbols)
Special character processing (e.g., converting to uppercase)
The custom mask property editor provides selection from predefined, commonly used masks.
The InvalidMessage
property sets a tooltip message for invalid entries.
The TypeValidationCompleted
event handler enables custom validation behavior.
The TextMaskFormat
property determines literal and prompt character processing in the formatted string, controlling their inclusion in the Text
property. Excluded prompt characters convert to spaces.
ExcludePromptAndLiterals
: Shows only user input text
IncludeLiterals
: Shows user input and mask literal characters
IncludePrompt
: Shows user input and prompt characters
IncludePromptAndLiterals
: Shows user input, literal characters, and prompt characters
Customize text color using the ForeColor
property.
Wisej.NET applications are standard web applications that work seamlessly with load balancers.
However, Wisej.NET goes a step further and gives you additional features to manage the load across several servers. You can configure each server running a Wisej.NET application to accept a a maximum number of sessions, or to be available for the load balancer only if the CPU load is below a certain percentage and/or the memory usage is below a certain level.
Wisej.NET applications use WebSocket connections, which may require configuring your load balancer for TCP rather than HTTP routing. More details below.
Preparing Wisej.NET apps for load balancing mainly involves configuring healthcheck parameters. These determine when a server instance should return an error code signaling the load balancer to route requests elsewhere.
To configure healthcheck:
Use Add New Item and select Healthcheck from templates, or
Copy the configuration settings below, or
Place the file in your application's root folder and set "Copy to Output Directory" to "Copy if newer". The file must be in the /bin
directory to be recognized.
Wisej.NET requires client requests to route consistently to the same server instance. Configure your load balancer to use either:
Sticky Sessions
Other routing that ensures user-server instance consistency
Wisej.NET requires load balancer session affinity: each user/session must route to the same server. This typically uses:
Sticky session cookies
Client IP hash
Other consistent routing methods
Load balancers periodically verify server instance availability using a "healthcheck" URL. Options:
Custom HTML/ASPX page
healthcheck.wx
to verify Wisej.NET routing component status
Wisej.NET applications automatically respond to initial Default.html
(or subapplication URL) requests by either returning the page or returning "503 Service Unavailable" (configurable in HealthCheck.json
).
The following properties in HealthCheck.json
control server availability. Wisej.NET uses all configured properties in this order:
Maximum live sessions a Wisej.NET server can accept before refusing more. Returns "503 Service Unavailable" (or HTML page from Default.json
) to new users instead of risking server overload.
Set to 0
to disable this check.
Maximum memory percentage before returning "503 Service Unavailable". Example: Value 70
means the server returns 503 when memory usage is 70% or higher during main page request.
Set to 0
to disable this check.
Maximum CPU load percentage before returning "503 Service Unavailable". Example: Value 100
means the server returns 503 when CPU usage is 100% during main page request.
Set to 0
to disable this check.
503: The server is currently unable to handle the request due to temporary overloading or maintenance. This condition should be temporary. If known, the delay length MAY be indicated in a Retry-After header. Without Retry-After, the client SHOULD handle the response as a 500 response.
Minutes value for the Retry-After
header sent with "503 Service Unavailable" response.
Note: Most load balancers currently ignore this header.
You can install a custom static method called by the healthcheck handler. Return true
if the server should be available to the load balancer, false
to return 503 (unavailable).
The IsServerAvailable
method can check any values to determine server availability:
Another super cool feature in Wisej.NET (and only in Wisej.NET ) is the ability to drag & drop any file(s) from your desktop onto any control.
MsgBox(Prompt, Buttons, Title, CloseCallback)
Displays a message in a dialog box, waits for the user to click a button, and then returns one of MsgBoxResult indicating which button the user clicked.
MsgBoxAsync(Prompt, Buttons, Title)
Asynchronously displays a message in a dialog box, waits for the user to click a button, and then returns one of MsgBoxResult indicating which button the user clicked.
InputBox(Prompt, Title, DefaultResponse, XPos, YPos, CloseCallback)
Displays a prompt in a dialog box, waits for the user to input text or click a button, and then returns a string containing the contents of the text box.
InputBoxAsync(Prompt, Title, DefaultResponse, XPos, YPos)
Asynchronous displays a prompt in a dialog box, waits for the user to input text or click a button, and then returns a string containing the contents of the text box.
Beep(AudioBase64)
Plays a sound on the browser.
Mnemonics are another feature that is common in desktop applications and generally completely forgotten in most web frameworks, except in Wisej.NET
"label-wrapper" see
"textbox", see
"textfield" is the inner <input> widget. See
"editor", see
"textfield" is the inner <input> widget. See
"editor", see
For a full list of properties, methods and events see the
The DomainUpDown
control supports the inline property. This allows setting a label in relation to a DomainUpDown
control without creating an additional Label
control.
For a full list of properties, methods and events see the
The TimeUpDown
control supports the inline property. This allows setting a label in relation to a TimeUpDown
control without creating an additional Label
control.
For a full list of properties, methods and events see the
The DateTimePicker
control supports the inline property. This allows setting a label in relation to a DateTimePicker
control without creating an additional Label
control.
For specialized UI designs like Material-3 animated underline on focus, either create a custom , use a theme mixin, or add custom styles to the control.
The video shows a DateTimePicker
with "border-radius:10px" assigned to the CssStyle
property. For shared styles, set the CssClass
property and add a StyleSheet file (.css) to the application through Default.html or the extender.
The video also features a simple "tada" animation using the component.
For a full list of properties, methods and events see the
For a full list of properties, methods and events see the
The features described on this page may not be available for all Wisej.NET Server license editions. For more details, please review the .
Download the default
Some load balancers need TCP mode configuration for WebSocket connections. Reverse proxies like NGINX have built-in WebSocket support - see .
HTTP status code returned by /healthcheck.wx
when server can't accept new sessions. Default is 503. See .
Class name
"wisej.web.DomainUpDown"
Theme appearance
"spinner", see Themes.
Child components
"upbutton" is the up button. "downbutton" is the down button. "textfield" is the textfield.
Source code
Class name
"wisej.web.TimeUpDown"
Theme appearance
"spinner", see Themes.
Child components
"upbutton" is the up button. "downbutton" is the down button. "textfield" is the textfield.
Source code
Class name
"wisej.web.DateTimePicker" or "wisej.web.dateTimePicker.DropDown" for the drop down component.
Theme appearance
"datefield", see Themes.
Child components
"textfield" is the inner <input> widget. "button" is the button that shows the dropdown. "list" is the list of dates in the popup. "popup" is the popup frame (background). "checkbox" is the checkbox, when enabled. "upbutton" is the up button, when applicable. "downbutton" is the down button, when applicable.
Toolcontainer state
"editor", see Embedded Tools.
Source code
Class name
"wisej.web.MonthCalendar" for the base component, "wisej.web.monthCalendar.DateChooser" for the drop down component, and wisej.web.monthCalendar.Today for the label that shows today's date.
Theme appearance
"calendar", see Themes.
Child components
"datechooser" is the dropdown. "today" is the today label. "tools" is the tools container.
Toolcontainer state
"calendar", see Embedded Tools.
Source code
Class name
"wisej.web.MaskedTextBox"
Theme Appearance
"textbox"
Child components
"textfield" is the inner <input> widget. See JavaScript
Toolcontainer state
"editor", see Embedded Tools
Source code
Enables the user to choose between a range of values by sliding a small bar along another bar.
The Wisej.NET TrackBar
is a scrollable control similar to the ScrollBar
. Configure value ranges by setting the Minimum
property for the lower end and the Maximum
property for the upper end.
The LargeChange
property defines the increment to add or subtract from the Value
property when clicking either side of the scroll box. The track bar displays horizontally or vertically.
Use this control to input numeric data through the Value
property, which can be displayed in a control or used in code.
The TrackBar
control supports both horizontal and vertical orientations.
The TrackBar
control allows customization of tick mark positions and count.
Class name
"wisej.web.TrackBar"
Theme appearance
Child components
"knob" is the slider handle. "begin" is the slider up to the knob. "end" is the slider after the knob. "bubble" is the popup shown while dragging the knob.
Source code
Represents a spinner control that displays numeric values.
A Wisej.NET NumericUpDown
control contains a single numeric value that can be incremented or decremented using the up or down buttons. Users can enter values directly unless the ReadOnly
property is set to true
.
Format the numeric display using the DecimalPlaces
, Hexadecimal
, or ThousandsSeparator
properties. Set Hexadecimal
to true
to display hexadecimal values. Enable ThousandsSeparator
to display the thousands separator in decimal numbers. Set DecimalPlaces
to specify the number of digits after the decimal symbol.
The NumericUpDown
control supports the inline Label property. This allows setting a label in relation to a NumericUpDown
control without creating an additional Label
control.
The NumericUpDown
control offers several formatting properties. The Prefix
property prepends a character or string to the value. The Postfix
property appends a character or string to the value. Enable the ThousandsSeparator
property to display commas for values exceeding three digits.
Class name
"wisej.web.NumericUpDown"
Theme appearance
Child components
"upbutton" is the up button. "downbutton" is the down button. "textfield" is the textfield.
Source code
"slider", see .
"spinner", see .
Image concepts.
Wisej.NET controls can use several kinds of icons and images:
Image file
Image from an ImageList component
Image object (System.Drawing.Image)
Image from the theme or a them mixin
Image in embedded resources in an assembly
You can use any, relative or full, URL as the source of the image. The properties that can accept a URL typically end with "Source": ImageSource is the most common property.
Multiple controls in Wisej.NET can utilize the ImageList component. The ImageList component allows you to manage a collection of Image objects by index or key, instead of having an image assigned directly.
Some controls may have several image properties, all used for the same image. For example, the Button control has "Image", "ImageSource", "ImageIndex", and "ImageKey". They all refer to the same image and when setting one of the properties, the others will reset automatically.
Image properties that end with Key or Index refer to an image in an ImageList. The ImageList may be assigned to the control itself or to its container.
Image properties that don't and with Index, Key or Source and are of type System.Drawing.Image, can be assigned with any image object. Wisej.NET will return the image as a png back to the browser.
Each theme in Wisej.NET comes with a set of default theme images that are used for controls.
You can use any image from the theme, including images in theme mixins, simply by name. Assign the name to an ImageSource property and Wisej.NET will load the image from the client cache to the browser element.
Wisej.NET supports Icon Packs at runtime and design time. An Icon Pack is an assembly that embeds a collection of icons. You can deploy single assembly instead of multiple icon files.
The Design-Time Image Selector automatically discovers the Icon Pack Assemblies referenced in the project and adds them to the folder list, right below the Project Root Folder. When you select the Icon Pack, Wisej.NET lists and previews all the embedded icons in the assembly and lets you choose the icon to use, as if it was a single file.
You can build your own Icon Packs and/or download the ones that we provide.
All Wisej.NET themes use SVG monochrome icons. Their color is set either in the theme or to match the container's text color. It's the same behavior of icon fonts.
In case you need to change the color of a specific SVG icon, without having to change the color of the text of the container, you can add the color to the ImageSource name or URL (for embedded icons and icon packs) by adding: ?color=[color].\
If your SVG color is not able to be changed, it could be due to a fill or stroke value inside of the SVG. Try removing it with a Text Editor.
The size of the icons is usually set in the themes. You can change it by using an ImageList component and assigning it to the control that has the image you want to resize. The ImageList component will resize the image even if it's not in its image list.
Wisej.NET fully supports localization using .NET and Visual Studio standard localization features.
{% file src="../.gitbook/assets/wisej.localization.zip" caption="Download Wisej.Localization.zip" %}
All top-level controls in Wisej.NET support UI localization.
To enable localization features for a Form
, Page
, UserControl
, or Desktop
component:
In design mode, set the Localizable
property to true
Once enabled, you can switch languages in the designer
Use the Language
dropdown property to select the language for localization:
UI localization allows changing multiple properties per language switch, commonly:
Size
Location
Text
Colors
Images
Wisej.NET supports full localization of system resources including:
MessageBox
buttons
Calendar control labels (month/day names)
Standard numeric, percentage and currency formatting/parsing
Numeric, Percentage, Date, and Currency
Handled automatically for all supported languages worldwide.
Date Labels: Months and Day Names
Handled automatically for all supported languages worldwide.
System Resources
Wisej.NET system resources are localized in:
English
German
French
Italian
Turkish
Spanish
Portuguese
For other languages, create a Resources-[LANG].resx
file in either:
Root project folder
/Resources
folder
Add localization labels as needed. See How to: Create a Localized Resource File.
$Ok
OK Button in MessageBox/system dialogs
OK
$Cancel
Cancel Button in MessageBox/system dialogs
Cancel
$Yes
Yes Button in MessageBox/system dialogs
Yes
$No
No Button in MessageBox/system dialogs
No
$Retry
Retry Button in MessageBox/system dialogs
Retry
$Ignore
Ignore Button in MessageBox/system dialogs
Ignore
$Abort
Abort Button in MessageBox/system dialogs
Abort
$Next year
Next-year navigation tooltip in calendar controls
Next Year
$Next month
Next-month navigation tooltip in calendar controls
Next Month
$Last year
Last-year navigation tooltip in calendar controls
Last Year
$Last month
Last-month navigation tooltip in calendar controls
Last Month
$Offline
Offline connectivity loss notification
Offline
Beyond system localization, you'll likely need to localize application resources (strings, images, etc.).
Create .resx
files as needed using the approach above. See How to: Create a Localized Resource File.
Use the ResourceManager
class to retrieve localized values. Wisej.NET handles thread culture switching for client requests.
Wisej.NET automatically detects browser language and switches application/system resources accordingly.
You can force a specific language for the application (user session) by:
Setting the culture
property in Default.json
(default is "auto"). See Configuration.
Using one of these methods:
Assign Application.CurrentCulture
property
Add lang
URL parameter (e.g., http://localhost/myapp?lang=de for German)
When current culture changes from the session's initial culture, Wisej.NET raises the Application.CultureChanged
event.
Designer-localized controls update only at creation. No built-in mechanism exists to change already-created controls. To update existing controls either:
Re-create the container and call InitializeControl
Write custom code to reapply resources