← All courses
UI · Free course

Drawing & Painting in Wisej.NET

Wisej.NET gives a .NET developer four different ways to draw, and they only look alike. A control Paint handler runs on the server and ships the result to the browser as an image; DataGridView CellPaint does the same inside a single grid cell; Wisej.Web.Canvas sends drawing commands the browser executes and keeps nothing across a resize; System.Drawing.Managed produces image bytes with no control involved at all. This advanced course teaches you to choose the surface before you write the first drawing call, and to build each one properly — around Visual Operations Studio, a monitoring application in which one telemetry and topology model is rendered all four ways. Seven modules start with the rendering architecture and the decision ladder that keeps standard controls and CSS as the default, then build a reusable painted gauge control with real resource discipline and deliberate invalidation, user-painted progress and sparkline cells that still scroll well at a thousand rows, and a Canvas playground that translates browser Canvas 2D documentation into the documented Wisej C# API. From there you turn the Canvas into a topology editor with model-based hit testing that survives pan and zoom, render the same model to a PNG that runs on Linux as well as Windows with System.Drawing.Managed, and finish with a capstone that puts one model and one pure geometry layer behind all four renderers — measured, hardened and accessible. It is written for experienced .NET developers who already build Wisej.NET screens and now need custom graphics that survive data scale, browser resizing, cross-platform deployment and accessibility review.

Draw custom graphics the Wisej.NET way — control Paint, DataGridView CellPaint, Wisej.Web.Canvas and cross-platform System.Drawing.Managed.

Start this free course

Also available in: DeutschFrançaisItalianoEspañol

Curriculum

Module 1: The Wisej.NET Drawing Architecture

Module 1 of Drawing & Painting in Wisej.NET — create custom graphics with Paint, CellPaint, Canvas and cross-platform System.Drawing.Managed. Read the lesson guide and the lab / exam guide, watch the drawing architecture walkthrough, pass the knowledge check, then complete the hands-on lab in VisualOperationsStudio.

  1. ReadingLesson Guide · 14 min

    Four rendering pipelines and how to choose between them: control Paint that ships a server-rendered image, DataGridView CellPaint inside one cell, Wisej.Web.Canvas that sends browser drawing commands, and off-screen System.Drawing.Managed that produces image bytes — plus the decision ladder that keeps standard controls and CSS as the default. What this means for an experienced .NET developer who already builds Wisej.NET screens and now needs custom graphics — and how to read this module.

    Read the lesson guide (PDF)

  2. ReadingLab / Exam Guide · 10 min

    What you'll build in the hands-on lab, the suggested approach, and the required deliverables.

    Read the lesson guide (PDF)

  3. Video lessonFour surfaces, one value: where the pixels come from · 14 min

    Four surfaces, one value: where the pixels come from — a guided Module 1 walkthrough, built step by step in VisualOperationsStudio. Runs right here in the player.

    Narration transcript

    Drawing and Painting in Wisej.NET opens with a decision that comes before any drawing code: where the pixels are actually produced. In this module a single telemetry reading is shown on four different surfaces of Visual Operations Studio, so you can compare them side by side.

    Asking an application to draw a number is not one requirement but four. A dial on a dashboard, a small indicator inside a grid cell, a node on a topology map and an image written to a report file all present the same value, yet each is produced somewhere different and each sends something different to the browser.

    A Paint handler runs on the server, and the finished picture travels to the browser as an image. Cell painting does the same work, confined to the bounds of one grid cell. A Canvas behaves differently: it sends drawing commands that the browser executes for itself. Off-screen rendering produces image bytes that no control ever displays.

    In the page, all four surfaces read one telemetry sample field, so none of them owns the value. One button changes that field and refreshes each surface in its own way: the label and the progress bar simply read it, the painted panel is invalidated so the server repaints it, the Canvas scene method runs again, and a fresh off-screen image is produced.

    Custom painting belongs at the end of a decision ladder, not the beginning. Reach for a standard control first, then ordinary markup, and only then a Paint handler, a painted cell or a Canvas. Off-screen rendering follows those, and a drawing loop running in the browser is reserved for the cases where the frame rate genuinely matters.

    Redrawing a Canvas means clearing it and rebuilding the whole scene from the model, because the browser's copy is not something the server can depend on. The off-screen renderer sits at the opposite extreme: a bitmap, and a graphics surface created over it, are enough to produce an image with no control involved at all.

    Run the page and press New reading. The same number appears in all four places at once, which makes it look like a single operation. It is not. Each surface has just put something quite different on the network to arrive there, and that difference is what this module is really about.

    Now resize the browser window. Three of the surfaces return on their own, because the server still owns what they display. The Canvas comes back empty, and stays empty until the redraw method reconstructs it from the telemetry sample the server kept. That asymmetry is the practical consequence of the boundary.

    In the first lab you build this page yourself: one model behind four surfaces, a single button that refreshes all of them, and a short note recording what crosses the network for each surface and which visuals survive a resize.

  4. ReadingAI Coding Exercise · 20 min

    Build this module's VisualOperationsStudio sample with ChatGPT or Claude from a ready-made prompt that points the model at this module's specification, then review, run and extend what it gives you.

    Read the lesson guide (PDF)

  5. Knowledge checkModule 1 Knowledge Check · 10 min · Pass mark 80%
  6. Hands-on labLab — One Value, Four Rendering Surfaces · 45 min

    Objective: Build the VisualOperationsStudio shell and render one telemetry reading on four surfaces at once. Create a VisualOperationsPage holding a single TelemetrySample model instance, then present its value as (1) a plain Label plus ProgressBar, (2) a Panel with a Paint handler that draws a bar from PaintEventArgs.Graphics and e.ClipRectangle, (3) a Wisej.Web.Canvas whose Redraw handler rebuilds the same bar from the model, and (4) an off-screen Bitmap rendered with Graphics.FromImage and shown in a PictureBox. Wire a button that changes the model value and refreshes all four surfaces through Invalidate() and a Canvas redraw, then resize the browser and record which surfaces survive and which have to be reconstructed. Deliverables: VisualOperationsPage holding one TelemetrySample model that every surface reads from; Paint handler drawing from PaintEventArgs.Graphics inside e.ClipRectangle; Canvas Redraw handler that rebuilds the whole scene from the model after a resize; Off-screen Bitmap rendered with Graphics.FromImage and displayed in the page; SurfaceNotes.md recording what crosses the network per surface and which visuals survive a resize.

Module 2: Mastering the Control Paint Event

Module 2 of Drawing & Painting in Wisej.NET — create custom graphics with Paint, CellPaint, Canvas and cross-platform System.Drawing.Managed. Read the lesson guide and the lab / exam guide, watch the painted gauge walkthrough, pass the knowledge check, then complete the hands-on lab in VisualOperationsStudio.

  1. ReadingLesson Guide · 14 min

    Server-painted controls done properly: PaintEventArgs.Graphics and ClipRectangle, geometry separated from drawing, disposing every pen, brush and font you create, property setters that call Invalidate() exactly once, and the paint cost budget that decides when a themed control is the better answer. What this means for an experienced .NET developer who already builds Wisej.NET screens and now needs custom graphics — and how to read this module.

    Read the lesson guide (PDF)

  2. ReadingLab / Exam Guide · 10 min

    What you'll build in the hands-on lab, the suggested approach, and the required deliverables.

    Read the lesson guide (PDF)

  3. Video lessonBuild a painted gauge that repaints only when it must · 14 min

    Build a painted gauge that repaints only when it must — a guided Module 2 walkthrough, built step by step in VisualOperationsStudio. Runs right here in the player.

    Narration transcript

    This module builds a painted control properly. The telemetry gauge draws a ring, its threshold zones, a needle and a numeric reading, and every one of its public properties clamps what it is given before deciding whether a repaint is needed at all.

    Your paint code runs on the server, and the browser receives the resulting image. That is convenient, and it is also why a handler copied into six panels is expensive: six pictures are produced, six sets of drawing objects are created, and repaints happen that nobody asked for.

    So measure first, then draw. The geometry helper takes a rectangle and returns the ring bounds, the sweep angles, the needle points and the rectangle the label sits in. It is ordinary arithmetic with no drawing in it, which means you can test the hard part without ever creating a control.

    Every property setter follows one recipe: clamp the incoming value, compare it with the current one, return immediately when nothing has changed, assign it, and invalidate exactly once. The same line of code refreshes the accessible description, so the reading stays available as text and not only as pixels.

    The handler guards against a zero-sized clip rectangle, calls the measuring step once, and then draws. Five using declarations cover the five objects this code creates and therefore owns. The graphics surface handed to you in the event arguments is not one of them, and disposing it would be a mistake.

    Ownership settles most of the awkward questions. Framework brushes and pens are shared and must be left alone, a static pen of your own is unsafe once several sessions paint at the same time, and a database call, a font load or a timer has no business inside a paint path.

    Watch it run. One reading moves, so one gauge invalidates and one picture is produced. The other two setters compared their values and returned early, which is the whole point. A resize then rebuilds each picture from the new clip rectangle, at the new size.

    Then comes the budget: processor time on the server, memory for the temporary bitmap, and the bytes sent for every repaint. When those numbers stop justifying the pixels, a themed control is the better answer. Either way, the values themselves must stay readable as text.

    In the second lab you build the gauge and its pure geometry helper, guard a zero size and an inverted range, publish the reading through the accessible description, and record the cost of a repaint in your own notes.

  4. ReadingAI Coding Exercise · 20 min

    Build this module's VisualOperationsStudio sample with ChatGPT or Claude from a ready-made prompt that points the model at this module's specification, then review, run and extend what it gives you.

    Read the lesson guide (PDF)

  5. Knowledge checkModule 2 Knowledge Check · 10 min · Pass mark 80%
  6. Hands-on labLab — A Reusable Painted Telemetry Gauge · 45 min

    Objective: Add a reusable TelemetryGauge control to VisualOperationsStudio that paints a ring, coloured threshold zones, a needle, a numeric value and a caption. Give it Value, Minimum, Maximum, WarningThreshold and CriticalThreshold properties whose setters clamp the input, return early when nothing changed and call Invalidate() once. Put the coordinate maths in a pure GaugeGeometry helper that takes a Rectangle and returns the ring bounds, sweep angles, needle points and label rectangle, then draw from those values with using-scoped pens, brushes and a GraphicsPath, leaving the supplied Graphics alone. Handle a zero-sized control, an inverted range and a value outside the range without throwing, and expose the reading through AccessibleDescription so it is not pixels-only. Deliverables: TelemetryGauge control with clamping Value, Minimum, Maximum and threshold properties that Invalidate() once per real change; Pure GaugeGeometry helper returning ring bounds, sweep angles, needle points and the label rectangle; Paint handler that disposes every pen, brush, font and path it creates and never disposes e.Graphics; Guards for zero size, inverted range and out-of-range values, with an AccessibleDescription carrying the reading; PaintCost.md noting the repaint size, how often it repaints and when a themed control would be cheaper.

Module 3: DataGridView Cell Painting

Module 3 of Drawing & Painting in Wisej.NET — create custom graphics with Paint, CellPaint, Canvas and cross-platform System.Drawing.Managed. Read the lesson guide and the lab / exam guide, watch the DataGridView cell painting walkthrough, pass the knowledge check, then complete the hands-on lab in VisualOperationsStudio.

  1. ReadingLesson Guide · 14 min

    Painting inside the grid: UserPaint at cell or column scope, DataGridViewCellPaintEventArgs with RowIndex and ColumnIndex, progress and sparkline cells that read rows cheaply, and the honest comparison against AllowHtml cell content on a grid with a thousand rows. What this means for an experienced .NET developer who already builds Wisej.NET screens and now needs custom graphics — and how to read this module.

    Read the lesson guide (PDF)

  2. ReadingLab / Exam Guide · 10 min

    What you'll build in the hands-on lab, the suggested approach, and the required deliverables.

    Read the lesson guide (PDF)

  3. Video lessonSparklines and gauges inside grid cells, at scale · 14 min

    Sparklines and gauges inside grid cells, at scale — a guided Module 3 walkthrough, built step by step in VisualOperationsStudio. Runs right here in the player.

    Narration transcript

    In this module the grid does the drawing. Visual Operations Studio is now showing a thousand machines, and two of its columns have to be readable at a glance rather than one number at a time.

    There are three ways to get there. A bound number that nobody scans is honest but useless. A gauge control in every row is readable and ruinous, because that is a thousand server-side controls alive in one session. The third option is a cell that paints itself, and only while it is actually visible.

    User painting always comes before cell painting: a cell or an entire column is switched into user-painted mode, and only then does the grid raise its cell paint event for it. The event arguments derive from the ordinary paint arguments, so they carry the graphics surface and the clip rectangle, and they add the row and column indexes you need for routing.

    One difference matters more than the rest. The Wisej.NET event arguments carry no helpers for painting the background or the content, so your handler is responsible for everything that appears in that cell. Copying a Windows Forms example straight across will not work. Subscribe once on the grid and switch on the two columns you own.

    Guard before you draw. A negative row index is a header rather than a data row, and a column you do not own returns immediately. Only then take the geometry from the clip rectangle and read the values you need, in a single step, from the object the row is already bound to.

    Running it, six visible rows produce twelve calls into the handler: a threshold-coloured bar for health, and a small line chart for the trend. The selected row is drawn with its own colours, because a painted cell that ignores selection looks broken the moment somebody clicks it.

    Now scroll through the thousand rows. Every newly visible cell calls the handler again, which turns the handler into a hot path. That is why there is no file or database access in it, no fonts or images created per cell, and why reading a row's values must stay a constant-time step.

    Then make the honest comparison. Cell markup wins for text, icons and accessibility. Painting wins for geometry that markup cannot express. And a real cell type wins whenever the user has to interact with the cell rather than only read it.

    In the third lab you build two painted columns behind one guarded handler, read each row's values in a single step, then build the same status indicator again as a markup cell and write down which of the two you would actually ship.

  4. ReadingAI Coding Exercise · 20 min

    Build this module's VisualOperationsStudio sample with ChatGPT or Claude from a ready-made prompt that points the model at this module's specification, then review, run and extend what it gives you.

    Read the lesson guide (PDF)

  5. Knowledge checkModule 3 Knowledge Check · 10 min · Pass mark 80%
  6. Hands-on labLab — User-Painted Progress and Sparkline Cells · 45 min

    Objective: Give VisualOperationsStudio an operations grid with two user-painted columns. Add explicit columns to gridOperations, set UserPaint = true on the Health and Trend columns only, and handle CellPaint once: return immediately when e.RowIndex is negative or e.ColumnIndex is not one of the two targets, then draw a threshold-coloured progress bar for Health and a polyline sparkline for Trend inside e.ClipRectangle. Read each row's values from the bound MachineStatus object rather than searching a list inside the handler, respect the selected row's colours, and keep the handler free of side effects. Bind 1,000 generated rows, scroll, and then build the same status indicator a second time as an AllowHtml cell so you can state in writing which one you would ship. Deliverables: gridOperations with explicit columns and UserPaint = true on only the Health and Trend columns; One CellPaint handler that guards e.RowIndex and e.ColumnIndex before drawing anything; Threshold-coloured progress cell and a polyline sparkline cell drawn inside e.ClipRectangle; Row values read from the bound MachineStatus object with no per-cell lookup, allocation or control creation; An AllowHtml status column built alongside, plus a note comparing both on a 1,000-row scroll.

Module 4: Wisej.Web.Canvas and the HTML5 Canvas 2D Model

Module 4 of Drawing & Painting in Wisej.NET — create custom graphics with Paint, CellPaint, Canvas and cross-platform System.Drawing.Managed. Read the lesson guide and the lab / exam guide, watch the Canvas 2D walkthrough, pass the knowledge check, then complete the hands-on lab in VisualOperationsStudio.

  1. ReadingLesson Guide · 14 min

    Reading browser Canvas 2D documentation and writing the Wisej.NET equivalent: PascalCase members on Wisej.Web.Canvas, degree-based angles where the browser uses radians, Save and Restore around transforms, gradients, patterns, shadows and clipping, and Redraw as the one place a scene is reconstructed. What this means for an experienced .NET developer who already builds Wisej.NET screens and now needs custom graphics — and how to read this module.

    Read the lesson guide (PDF)

  2. ReadingLab / Exam Guide · 10 min

    What you'll build in the hands-on lab, the suggested approach, and the required deliverables.

    Read the lesson guide (PDF)

  3. Video lessonTranslate a browser canvas example into Wisej C# · 14 min

    Translate a browser canvas example into Wisej C# — a guided Module 4 walkthrough, built step by step in VisualOperationsStudio. Runs right here in the player.

    Narration transcript

    Visual Operations Studio now needs a real drawing surface. The Wisej.NET Canvas gives you the browser's two-dimensional drawing context from C#, with one condition attached: it remembers nothing for you.

    Paint and cell painting both send a finished image, and the server knows what that image contains. A Canvas sends drawing commands that the browser carries out instead. Nothing is retained on the server, and a resize can wipe the result, so the scene has to exist somewhere you control.

    Translating a browser example takes three passes. Adjust the casing, because the members are the familiar ones in the C# convention. Replace the style strings with .NET types such as colours and fonts. Convert angles from radians to degrees. Then confirm the member actually exists, rather than assuming everything from the browser was carried over.

    The redraw event calls exactly one method. That method opens by clearing the whole surface, and every shape begins a new path before it draws. Skip that step and a later stroke drags the previous outline along with it, which is one of the most common ways a translated example goes wrong.

    Text is positioned with the alignment and baseline properties rather than measured, because the measuring call from the browser is not part of the documented surface. Gradients are objects in their own right: you build one, then assign it as the fill style, instead of describing it inline each time.

    Every transform sits between a save and a restore. So does the clipping region, so does the transparency, and so do the dash pattern and the shadow, because all of them are Canvas state rather than arguments to a single call. Bracketing them keeps one section from leaking into the next.

    Five sections are issued together in one update, because live update stays off by default. Turn it on only when a long server-side operation should reveal its progress as it works. It is not a way to animate, and a request for every frame is the wrong architecture.

    Two failures are worth seeing deliberately. Resize the surface and it goes blank until the redraw rebuilds it from the model. Remove one restore call and everything drawn afterwards drifts out of place. Neither of them shows up in the designer, which is exactly why they cost so much time.

    In the fourth lab you draw the entire playground from one method called by redraw, bracket every transform, add a clip, a transparency section, a dash and a shadow, and port a browser example measured in radians to the degrees the Wisej.NET rotate call expects.

  4. ReadingAI Coding Exercise · 20 min

    Build this module's VisualOperationsStudio sample with ChatGPT or Claude from a ready-made prompt that points the model at this module's specification, then review, run and extend what it gives you.

    Read the lesson guide (PDF)

  5. Knowledge checkModule 4 Knowledge Check · 10 min · Pass mark 80%
  6. Hands-on labLab — A Canvas Playground Rebuilt by Redraw · 45 min

    Objective: Build a Canvas playground page in VisualOperationsStudio that ports a set of browser Canvas 2D examples to the documented Wisej.Web.Canvas API. Drive everything from a DrawPlayground method called by the Canvas Redraw event so the scene returns after a resize, and start it with ClearRect over the full surface. Render a stroked path, filled rectangles, a placed caption, a linear gradient and a radial gradient, then wrap each transformed section in Save() and Restore() and demonstrate Translate, Scale, Rotate and SetTransform. Add a clipped region, an alpha section, a dashed line and a shadow, port one browser example that rotates by Math.PI / 4 into the degree value Wisej expects, and keep LiveUpdate off for the main render while showing it in one small progressive example. Deliverables: Canvas playground whose entire scene is drawn by a DrawPlayground method called from Redraw; Paths, rectangles, a placed caption, a linear gradient and a radial gradient using documented Wisej.Web.Canvas members only; Save() and Restore() around every Translate, Scale, Rotate and SetTransform section; Clipping, alpha, a dashed line and a shadow, plus one radians-to-degrees port written out in a comment; A LiveUpdate demonstration kept separate from the main render, with a note on when it is appropriate.

Module 5: Interactive Canvas: State, Input, Hit Testing and Performance

Module 5 of Drawing & Painting in Wisej.NET — create custom graphics with Paint, CellPaint, Canvas and cross-platform System.Drawing.Managed. Read the lesson guide and the lab / exam guide, watch the interactive canvas walkthrough, pass the knowledge check, then complete the hands-on lab in VisualOperationsStudio.

  1. ReadingLesson Guide · 14 min

    Turning a Canvas into an editor: the Model, Input, State, Render loop, pointer and touch events from Control, screen-to-world conversion so hit testing survives pan and zoom, per-session scene state instead of statics, viewport culling, and the point where a client-side loop replaces server round trips. What this means for an experienced .NET developer who already builds Wisej.NET screens and now needs custom graphics — and how to read this module.

    Read the lesson guide (PDF)

  2. ReadingLab / Exam Guide · 10 min

    What you'll build in the hands-on lab, the suggested approach, and the required deliverables.

    Read the lesson guide (PDF)

  3. Video lessonSelection, drag, pan and zoom without losing the scene · 14 min

    Selection, drag, pan and zoom without losing the scene — a guided Module 5 walkthrough, built step by step in VisualOperationsStudio. Runs right here in the player.

    Narration transcript

    The Canvas forgets, and the model must not. In this module the playground from the previous module becomes a topology editor with selection, dragging, panning and zooming, and every one of those gestures has to survive a redraw.

    A rectangle in the browser is not a pump. The meaning lives in the scene object on the server: the nodes, the edges, which one is selected, where the viewport sits. Input changes that state, and a single render method turns the state into drawing calls. The renderer never decides anything.

    Rendering converts world coordinates to screen coordinates by applying the zoom and then the pan offset. Hit testing has to run that conversion backwards, taking the pointer position back into world coordinates before comparing it with a node. The Canvas offers no point-in-path test to lean on, so this arithmetic is yours.

    Start from the model. Nodes and edges carry stable identifiers and their own geometry, and the scene that holds them lives per session, never in a mutable static field that every user would share. The hit test walks the list backwards, so the node drawn last, and therefore on top, is the one the user gets.

    The three pointer handlers do very little. Mouse down converts and hit-tests, mouse move drags the selection or pans the viewport, mouse up ends the gesture. Each of them changes state and then calls the one render method. The redraw event calls that same method, which is why a resize simply rebuilds the scene.

    When redrawing costs too much, work down a ladder: fewer primitives first, then skip what is off-screen, then simplify the geometry, then cache the layers that rarely change. Moving the loop into the browser is the last step, not the first, and live update stays off for the main render.

    In the browser the click is converted into world coordinates, finds the second pump, marks it selected and renders. Watch the request counter climb while you drag. That number is what a server-side drag genuinely costs, and it is the measurement that tells you when to stop.

    Zoom about the pointer and selection still lands on the right node, because the inverse conversion accounts for the new zoom. Nodes outside the visible rectangle are skipped entirely. And the tab key with the arrow keys reaches every node, so the editor does not require a mouse to be usable.

    In the fifth lab you build the per-session scene, hit-test in world coordinates, keep all three handlers calling one render method, cull what is off-screen, add the keyboard path, and record the point at which you would move the interaction into the browser.

  4. ReadingAI Coding Exercise · 20 min

    Build this module's VisualOperationsStudio sample with ChatGPT or Claude from a ready-made prompt that points the model at this module's specification, then review, run and extend what it gives you.

    Read the lesson guide (PDF)

  5. Knowledge checkModule 5 Knowledge Check · 10 min · Pass mark 80%
  6. Hands-on labLab — A Topology Editor with Model-Based Hit Testing · 45 min

    Objective: Turn the Canvas playground into a topology editor for VisualOperationsStudio. Create NodeModel and EdgeModel classes with stable IDs and world-space geometry, hold the scene in a TopologyScene object stored per session rather than in a static field, and keep RenderScene as the only method that draws. Add ToWorld and ToScreen conversions for the current pan offset and zoom factor, then handle MouseDown to hit-test node bounds in world coordinates and set Selected, MouseMove to drag the selected node or pan the viewport, and MouseUp to end the gesture — each of them changing state and then calling RenderScene. Add wheel or button zoom about the pointer, skip nodes outside the visible rectangle when rendering, give keyboard users a way to select and nudge a node, and record the request traffic a drag produces plus the point at which you would move the loop to client JavaScript. Deliverables: NodeModel, EdgeModel and a per-session TopologyScene with stable IDs and no mutable static state; ToWorld and ToScreen conversions used for hit testing so selection stays correct after pan and zoom; MouseDown, MouseMove and MouseUp handlers that change state and then call the single RenderScene method; Viewport culling that skips nodes outside the visible rectangle, plus a keyboard path for selecting and nudging; InteractionNotes.md with the request traffic measured during a drag and the client-side cutoff you would apply.

Module 6: System.Drawing.Managed Across Windows, Linux, macOS, iOS and Android

Module 6 of Drawing & Painting in Wisej.NET — create custom graphics with Paint, CellPaint, Canvas and cross-platform System.Drawing.Managed. Read the lesson guide and the lab / exam guide, watch the cross-platform managed drawing walkthrough, pass the knowledge check, then complete the hands-on lab in VisualOperationsStudio.

  1. ReadingLesson Guide · 14 min

    Off-screen rendering that runs everywhere: why System.Drawing.Common is Windows-only on modern .NET, what the Managed.System.Drawing package and System.Drawing.Managed assembly actually are, the Wisej.NET 4 font and graphics matrix, deterministic font policy, and choosing between it, ImageSharp, SkiaSharp, Aspose.Drawing and Microsoft.Maui.Graphics by use case. What this means for an experienced .NET developer who already builds Wisej.NET screens and now needs custom graphics — and how to read this module.

    Read the lesson guide (PDF)

  2. ReadingLab / Exam Guide · 10 min

    What you'll build in the hands-on lab, the suggested approach, and the required deliverables.

    Read the lesson guide (PDF)

  3. Video lessonRender a PNG on the server that also runs on Linux · 14 min

    Render a PNG on the server that also runs on Linux — a guided Module 6 walkthrough, built step by step in VisualOperationsStudio. Runs right here in the player.

    Narration transcript

    This module produces a file rather than a screen. Operations want the same topology as an image they can keep, generated on a server that has no graphics subsystem of the traditional kind underneath it.

    None of the previous three surfaces can do that, because each needs a live control and a live session. The obvious library is ruled out as well: Microsoft made its classic drawing package Windows-specific from .NET 6, and the switch that re-enabled other systems was removed in .NET 7.

    Three names describe one thing, and keeping them straight saves an afternoon. The package you reference is the managed distribution, the assembly on disk is the managed drawing library, and the namespace your code uses is the familiar one. It is a managed rendering engine, not a wrapper over the platform's own graphics layer.

    The renderer takes a scene and an output size and returns bytes. It creates a bitmap, obtains a graphics surface over it, draws the edges, the nodes and the labels with pens, brushes and a path, and saves the result into a memory stream as a portable network graphic. No control appears anywhere in it.

    The platform matrix is worth memorising. Font measurement is managed everywhere. Drawing is managed on modern .NET on every operating system, and falls back to the platform layer on the .NET Framework and inside the designer build. Never pin a cross-platform deployment to a Windows-only target framework to make a drawing problem go away.

    Two decisions then determine whether this survives deployment. Resolve the font through a chain that ends in something you ship yourself, rather than assuming a font exists on the host. And keep exactly one drawing implementation in the reference graph, because two of them resolving the same type names is a problem you will not enjoy diagnosing.

    Run it. The export renders off-screen in about thirty-four milliseconds with no control involved, and the bytes are handed to the browser as a download. Bound the requested size, though: a bitmap four thousand pixels wide by three thousand high costs roughly forty-eight megabytes before you have drawn anything.

    Now the container. The same test passes on Linux, nothing is linked against the platform's native graphics library, and the two images come out byte for byte identical, because the font was shipped with the application rather than borrowed from the host.

    In the sixth lab you build the control-free renderer, give it a font fallback chain, download the image from the page, check the references for a second drawing implementation, and record your Windows and Linux evidence along with what it implies for the mobile and desktop targets.

  4. ReadingAI Coding Exercise · 20 min

    Build this module's VisualOperationsStudio sample with ChatGPT or Claude from a ready-made prompt that points the model at this module's specification, then review, run and extend what it gives you.

    Read the lesson guide (PDF)

  5. Knowledge checkModule 6 Knowledge Check · 10 min · Pass mark 80%
  6. Hands-on labLab — An Off-Screen PNG Renderer That Travels · 45 min

    Objective: Add a TopologyImageRenderer to VisualOperationsStudio that turns the topology model into a PNG without touching a Wisej control. Give it a Render method taking the scene and an output size, create the Bitmap, obtain its Graphics with Graphics.FromImage, draw nodes, edges, labels and a legend with pens, brushes and a GraphicsPath, and dispose everything it owns while leaving the caller's objects alone. Resolve its Font through a ResolveFont method that tries an application-supplied family and falls back to a known-present one instead of assuming a system font exists, save to a MemoryStream as PNG and hand the bytes to the page for download. Then check the project references to confirm you are not adding System.Drawing.Common alongside Wisej's managed implementation, run or stage the renderer on Windows and in a Linux container, and write up how the same code behaves on iOS, Android and macOS Hybrid targets. Deliverables: TopologyImageRenderer with no dependency on a Wisej control, rendering through Graphics.FromImage into a Bitmap; ResolveFont method with an explicit fallback chain instead of an assumed system font; PNG written to a MemoryStream and downloaded from the page, with every owned graphics object disposed; Reference check confirming Managed.System.Drawing is in use and System.Drawing.Common is not being added alongside it; CrossPlatform.md with Windows plus Linux container evidence and the iOS, Android and macOS implications.

Module 7: Production Drawing Architecture, Performance and Capstone

Module 7 of Drawing & Painting in Wisej.NET — create custom graphics with Paint, CellPaint, Canvas and cross-platform System.Drawing.Managed. Read the lesson guide and the lab / exam guide, watch the production architecture and capstone walkthrough, pass the knowledge check, then complete the hands-on lab in VisualOperationsStudio.

  1. ReadingLesson Guide · 14 min

    Making drawing code shippable: one visual model with a pure geometry layer and separate renderers per surface, instrumentation for render time and payload size, profiling a painted path against an off-screen path, resize, theme, empty-data and missing-font behaviour, an accessible textual equivalent, and the Visual Operations Studio capstone. What this means for an experienced .NET developer who already builds Wisej.NET screens and now needs custom graphics — and how to read this module.

    Read the lesson guide (PDF)

  2. ReadingLab / Exam Guide · 10 min

    What you'll build in the hands-on lab, the suggested approach, and the required deliverables.

    Read the lesson guide (PDF)

  3. Video lessonOne model, four renderers, measured and shipped · 14 min

    One model, four renderers, measured and shipped — a guided Module 7 walkthrough, built step by step in VisualOperationsStudio. Runs right here in the player.

    Narration transcript

    This is the capstone. Six modules have built four rendering surfaces in Visual Operations Studio, each one correct on its own. Shipping them means making them agree with each other, and proving that they do.

    At the moment every surface keeps its own thresholds, its own colours and its own idea of where things sit. Move the warning line once and the exported image quietly contradicts the screen it was generated from. That is not a rendering bug; it is four copies of the same business rule.

    The remedy is three layers. A visual model holds semantic state: values, statuses, selection. A geometry layer turns that state and a size into shapes, and it is pure arithmetic. Then one renderer per surface, each keeping the primitives that suit it, because forcing them through a shared interface helps nobody.

    Next, agree on numbers before you optimise anything. A painted control should stay under about five milliseconds. A full Canvas redraw belongs in the range of sixteen to fifty milliseconds. An export is allowed to be slower than either, provided it never blocks another user's session while it runs.

    The geometry call takes the model and a size and returns shapes, and both renderers call it, so neither can drift. Around them, a small metrics helper records how long a render took, how large the output was, and how many scene objects were actually drawn. Without those three numbers, tuning is guesswork.

    Then draw the bad states deliberately. Empty data, a surface with no size, a range whose minimum exceeds its maximum, a font that is missing: each one should degrade to something readable rather than throw. And a failed export should reach the user as a message, not as a blank space where a picture was expected.

    One value changes and all four surfaces follow it: the painted gauge, the painted cells, the Canvas topology and the exported image. Beside them sits a plain table listing every reading, which is what makes the information available to somebody who cannot use the graphics at all.

    Finally the evidence. The painted gauge came down from about eleven milliseconds to four, the export from roughly three hundred and ten milliseconds to a hundred and twenty-eight, and the test matrix covers Windows, Linux, the hybrid targets and three browsers. A measured decision not to optimise counts too, as long as it is written down.

    The final lab is the capstone: one model behind all four surfaces, a metrics helper, one optimisation you measured before and after, four degraded paths that fail gracefully, and the notes that explain the architecture and the boundary it respects.

  4. ReadingAI Coding Exercise · 20 min

    Build this module's VisualOperationsStudio sample with ChatGPT or Claude from a ready-made prompt that points the model at this module's specification, then review, run and extend what it gives you.

    Read the lesson guide (PDF)

  5. Knowledge checkModule 7 Knowledge Check · 10 min · Pass mark 80%
  6. Hands-on labLab — Capstone: Visual Operations Studio · 45 min

    Objective: Complete the VisualOperationsStudio capstone by putting one model behind all four surfaces. Restructure the project into Models, Geometry, Renderers and Wisej adapter folders so the painted gauge, the user-painted grid cells, the Canvas topology and the PNG export all read the same OperationsModel and share the pure geometry layer, with no business state duplicated per renderer. Add a RenderMetrics helper that records render duration, output bitmap size and the number of scene objects drawn, and use it to compare the server-painted gauge against the off-screen renderer before and after one optimisation you choose and justify. Exercise the failure paths — empty data, a zero-sized surface, an invalid range, a missing font — so each degrades to a readable placeholder rather than an exception, add an accessible table that lists every value the graphics show, and write the capstone notes covering the architecture, the browser/server boundary and the test matrix. Deliverables: Models, Geometry, Renderers and adapter layers with one OperationsModel driving all four surfaces; RenderMetrics helper recording render duration, bitmap size and drawn object count per surface; Before-and-after measurements for one optimisation, with the reasoning for choosing it; Failure paths for empty data, zero size, invalid range and a missing font that degrade instead of throwing; CapstoneNotes.md with the architecture, the server/browser boundary, the test matrix and an accessible data table.