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...
Allow controls to adjust their size to fit their content.
Many Wisej 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 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 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.
You can mix AutoSize, MaximumSize, and AutoScroll to allow a container to grow to fit its content until it reaches the maximum size and then to show the scrollbars.
All Wisej 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 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().
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 has basic accessibility support built-in and provides a WebARIA extension to support most of the WAI-ARIA properties.
The WebARIA extension is provided with source code to enable developers to extend it and adapt it to their requirements.
All Wisej 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.
Adjusts the size of a container and all its children when the font size changes.
All Wisej 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 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 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.
When in design mode and AutoScroll is true, both scrollbars are always visible regardless of the ScrollBars property.
The browser will always scroll a widget into view when it receives the focus, regardless of the scrollbar settings.
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 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 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 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.
If the user touches the scroll bar, the scrolling system will NOT process the touch and inertial scrolling and will instead move the scrollbar as the user drags the scrolling knob.
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.
Color and font concepts.
All controls in Wisej 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 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.
When adding a font to the browser, also make sure that the same font is installed on the servers and development machines or Wisej will calculate the size of AutoSize controls incorrectly.
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.
Represent a Wisej 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
Different web servers add different server variables. Don't expect all the server variables to be always present.
There are many global events exposed by the Application class. They let your code receive all sorts of notifications from the Wisej infrastructure.
In addition to the regular exception handling that you have in your code, Wisej lets you handle any unhandled exception through the Application.ThreadException event.
Exceptions are suppressed simply by handling the Application.ThreadException event. Once you attach a handler, it is up to your code to log, show, do nothing, or rethrow the exception.
There are three events that are relevant to the session management system in Wisej:
Use Application.ThreadBegin and Application.ThreadEnd to receive a notification every time Wisej 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 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 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 from dispatching it any further, or return false to let Wisej continue dispatching the event.
Event filters are invoked in the same order they are added.
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 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 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 at startup. It allows a web application to save and send custom data to the Wisej 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 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 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 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:
Wisej 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.
The Beep() VB.NET extension uses Application.Play() with a predefined base64 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 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.
If you make changes to a file that you loaded using LoadPackages() or LoadPackagesAsync(), make sure to clear the browser cache so that the correct version of the file is used at runtime.
Touch events compatibility and emulation.
Wisej 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 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.
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.
Add small buttons inside a control adding custom functionality.
Several controls in Wisej 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:
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.
Event routing concepts.
Event routing is a cornerstone of the Wisej architecture. Wisej 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 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 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 Real-Time features.
When creating new Wisej 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 widget:
The example above shows how to fire JavaScript events back to the server.
The example below shows how to register a Wisej 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 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.
Name | Description |
---|---|
Wisej is indeed magic
Storage | Description |
---|---|
Event handling for these events is activated only if there is an event handler attached. See .
Control | State |
---|
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 will show the built-in SessionTimeoutForm.
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.
Form | "caption" |
Panels | "panel" |
Editors | "editor" |
ListBox | "listbox" |
DataGridView | "datagrid" |
MonthCalendar | "calendar" |
ListView | "listview" |
TreeView | "treeview" |
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 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.
The same mnemonic functionality is supported in the independent Label control. However, in the Label control case, the control that gains the focus when the mnemonic is pressed is the next focusable control in the tab order.
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.
Tooltip concepts.
All Wisej controls can be associated to a tooltip text through the ToolTipText property or the ToolTip extender.
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.
Check out also the HelpTip Extender for a different kind of "tooltips".
Both tooltips can be styled in a custom theme or theme mixin, or using the ToolTip extender on the top level container.
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.
The ToolTip property provided by the ToolTip Extender is not bindable.
You can control several aspects of the tooltip widget using the ToolTip extender 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.
Image concepts.
Wisej 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 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.
The biggest advantages of using the "ImageList" component are that: it can be shared among multiple controls, and you can change an image without changing the controls that reference, effectively creating a level of indirection.
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 will return the image as a png back to the browser.
Each theme in Wisej 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 will load the image from the client cache to the browser element.
Theme images are all preloaded on the client at once.
Wisej 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 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 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.
Labels use the original size of the image. To set the size of the images used in labels, either use a png or a gif image already sized to the desired dimensions, or use the ImageList component.
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.
Wisej.NET provides several tools and methods for creating and managing data bindings, including the DataBindings editor and the BindingSource component.
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 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 manages a list of Binding objects.
Each Wisej 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 Form, there is a single CurrencyManager or PropertyManager. Because there may be multiple data sources associated with a Wisej 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.
Custom painting and drawing in the browser.
All Wisej 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 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.
The Canvas control allow you to build very sophisticated custom controls using the <canvas> element and drawing the control entirely in .NET.
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 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.
Shared features and properties among all Wisej controls.
All Wisej 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.
Retrieve the default appearance name by casting the control to Wisej.Core.IWisejControl, like this: ((Wisej.Core.IWisejControl)this).AppearanceKey;
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.
Mnemonics are another feature that is common in desktop applications and generally completely forgotten in most web frameworks, except in Wisej
Class name | wisej.web.LabelWrapper |
---|---|
Class name | wisej.web.extender.ToolTip |
---|---|
In addition to being able to paint any control, Wisej 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 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.
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 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 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.
Theme appearance
"label-wrapper" see Themes
Source code
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 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 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 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.
Drag & drop data is not limited to one format; you can create a DataObject, assign multiple data with different formats and use it in the call to DoDragDrop().
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.
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 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}.
Control | DropTarget |
---|---|
Another super cool feature in Wisej (and only in Wisej ) is the ability to drag & drop any file(s) from your desktop onto any control.
ListBox
Item
TreeView
TreeNode
DataGridView
DataGridViewCell
ListView
ListViewItem
Common VB.NET extension methods to basic objects.
VB.NET developers may be used to the Microsoft.VisualBasic namespace for VB specific extensions. Wisej provides the Wisej.Web.VisualBasic namespace with the implementation of the Interaction extensions:
You can still use Microsoft.VisualBasic non UI methods in Wisej.
Method | Description | Microsoft |
---|---|---|
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.