State Machines and Wizard Components: A Clean Implementation Approach

State Machines and Wizard Components: A Clean Implementation Approach

This past week, I have been working on a prototype for a wizard component. As you might know, in computer interfaces, wizard components (or multi-step forms) allow users to navigate through a finite number of steps or pages until they reach the end. Wizards are particularly useful because they don’t overwhelm users with too many choices at once, effectively minimizing the number of decisions a user needs to make at any specific moment.

The current prototype is created using XAF from DevExpress. If you follow this blog, you probably know that I’m a DevExpress MVP, and I wanted to use their tools to create this prototype.

I’ve built wizard components before, but mostly in a rush. Those previous implementations had the wizard logic hardcoded directly inside the UI components, with no separation between the UI and the underlying logic. While they worked, they were quite messy. This time, I wanted to take a more structured approach to creating a wizard component, so here are a few of my findings. Most of this might seem obvious, but sometimes it’s hard to see the forest for the trees when you’re sitting in front of the computer writing code.

Understanding the Core Concept: State Machines

To create an effective wizard component, you need to understand several underlying concepts. The idea of a wizard is actually rooted in system theory and computer science—it’s essentially an implementation of what’s called a state machine or finite state machine.

Theory of a State Machine

A state machine is the same as a finite state machine (FSM). Both terms refer to a computational model that describes a system existing in one of a finite number of states at any given time.

A state machine (or FSM) consists of:

  • States: Distinct conditions the system can be in
  • Transitions: Rules for moving between states
  • Events/Inputs: Triggers that cause transitions
  • Actions: Operations performed when entering/exiting states or during transitions

The term “finite” emphasizes that there’s a limited, countable number of possible states. This finite nature is crucial as it makes the system predictable and analyzable.

State machines come in several variants:

  • Deterministic FSMs (one transition per input)
  • Non-deterministic FSMs (multiple possible transitions per input)
  • Mealy machines (outputs depend on state and input)
  • Moore machines (outputs depend only on state)

They’re widely used in software development, hardware design, linguistics, and many other fields because they make complex behavior easier to visualize, implement, and debug. Common examples include traffic lights, UI workflows, network protocols, and parsers.

In practical usage, when someone refers to a “state machine,” they’re almost always talking about a finite state machine.

Implementing a Wizard State Machine

Here’s an implementation of a wizard state machine that separates the logic from the UI:

public class WizardStateMachineBase
{
    readonly List<WizardPage> _pages;
    int _currentIndex;

    public WizardStateMachineBase(IEnumerable<WizardPage> pages)
    {
        _pages = pages.OrderBy(p => p.Index).ToList();
        _currentIndex = 0;
    }

    public event EventHandler<StateTransitionEventArgs> StateTransition;

    public WizardPage CurrentPage => _pages[_currentIndex];

    public virtual bool MoveNext()
    {
        if (_currentIndex < _pages.Count - 1) { var args = new StateTransitionEventArgs(CurrentPage, _pages[_currentIndex + 1]); OnStateTransition(args); if (!args.Cancel) { _currentIndex++; return true; } } return false; } public virtual bool MovePrevious() { if (_currentIndex > 0)
        {
            var args = new StateTransitionEventArgs(CurrentPage, _pages[_currentIndex - 1]);
            OnStateTransition(args);

            if (!args.Cancel)
            {
                _currentIndex--;
                return true;
            }
        }
        return false;
    }

    protected virtual void OnStateTransition(StateTransitionEventArgs e)
    {
        StateTransition?.Invoke(this, e);
    }
}

public class StateTransitionEventArgs : EventArgs
{
    public WizardPage CurrentPage { get; }
    public WizardPage NextPage { get; }
    public bool Cancel { get; set; }

    public StateTransitionEventArgs(WizardPage currentPage, WizardPage nextPage)
    {
        CurrentPage = currentPage;
        NextPage = nextPage;
        Cancel = false;
    }
}

public class WizardPage
{
    public int Index { get; set; }
    public string Title { get; set; }
    public string Description { get; set; }
    public bool IsRequired { get; set; } = true;
    public bool IsCompleted { get; set; }
    
    // Additional properties specific to your wizard implementation
    public object Content { get; set; }
    
    public WizardPage(int index, string title)
    {
        Index = index;
        Title = title;
    }
    
    public virtual bool Validate()
    {
        // Default implementation assumes page is valid
        // Override this method in derived classes to provide specific validation logic
        return true;
    }
}

Benefits of This Approach

As you can see, by defining a state machine, you significantly narrow down the implementation possibilities. You solve the problem of “too many parts to consider” – questions like “How do I start?”, “How do I control the state?”, “Should the state be in the UI or a separate class?”, and so on. These problems can become really complicated, especially if you don’t centralize the state control.

This simple implementation of a wizard state machine shows how to centralize control of the component’s state. By separating the state management from the UI components, we create a cleaner, more maintainable architecture.

The WizardStateMachineBase class manages the collection of pages and handles navigation between them, while the StateTransitionEventArgs class provides a mechanism to cancel transitions if needed (for example, if validation fails). The newly added WizardPage class encapsulates all the information needed for each step in the wizard.

What’s Next?

The next step will be to control how the visual components react to the state of the machine – essentially connecting our state machine to the UI layer. This will include handling the display of the current page content, updating navigation buttons (previous/next/finish), and possibly showing progress indicators. I’ll cover this UI integration in my next post.

By following this pattern, you can create wizard interfaces that are not only user-friendly but also maintainable and extensible from a development perspective.

Source Code

egarim/WizardStateMachineTest

About US

YouTube

https://www.youtube.com/c/JocheOjedaXAFXAMARINC

Our sites

https://www.bitframeworks.com

https://www.xari.io

https://www.xafers.training

Let’s discuss your XAF Support needs together! This 1-hour call/zoom will give you the opportunity to define the roadblocks in your current XAF solution

Schedule a meeting with us on this link

Bridging Traditional Development using XAF and AI: Training Sessions in Cairo

Bridging Traditional Development using XAF and AI: Training Sessions in Cairo

I recently had the privilege of conducting a training session in Cairo, Egypt, focusing on modern application development approaches. The session covered two key areas that are transforming how we build business applications: application frameworks and AI integration.

Streamlining Development with Application Frameworks

One of the highlights was demonstrating DevExpress’s eXpressApp Framework (XAF). The students were particularly impressed by how quickly we could build fully-functional Line of Business (LOB) applications. XAF’s approach eliminates much of the repetitive coding typically associated with business application development:

  • Automatic CRUD operations
  • Built-in security system
  • Consistent UI across different platforms
  • Rapid prototyping capabilities

Seamless Integration: XAF Meets Microsoft Semantic Kernel

What made this training unique was demonstrating how XAF’s capabilities extend into AI territory. We built the entire AI interface using XAF itself, showcasing how a traditional LOB framework can seamlessly incorporate advanced AI features. The audience, coming primarily from JavaScript backgrounds with Angular and React experience, was particularly impressed by how this approach simplified the integration of AI into business applications.

During the demonstrations, we explored practical implementations using Microsoft Semantic Kernel. The students were fascinated by practical demonstrations of:

  • Natural language processing for document analysis
  • Automated content generation for business documentation
  • Intelligent decision support systems
  • Context-aware data processing

Student Engagement and Outcomes

The response from the students, most of whom came from JavaScript development backgrounds, was overwhelmingly positive. As experienced frontend developers using Angular and React, they were initially skeptical about a different approach to application development. However, their enthusiasm peaked when they saw how these technologies could solve real business challenges they face daily. The combination of XAF’s rapid development capabilities and Semantic Kernel’s AI features, all integrated into a cohesive development experience, opened their eyes to new possibilities in application development.

Looking Forward

This training session in Cairo demonstrated the growing appetite for modern development approaches in the region. The intersection of efficient application frameworks and AI capabilities is proving to be a powerful combination for next-generation business applications.

And last, but not least, some pictures )))

 

 

SyncFramework for XPO: Updated for .NET 8 & 9  and DevExpress 24.2.3!

SyncFramework for XPO: Updated for .NET 8 & 9 and DevExpress 24.2.3!

SyncFramework for XPO is a specialized implementation of our delta encoding synchronization library, designed specifically for DevExpress XPO users. It enables efficient data synchronization by tracking and transmitting only the changes between data versions, optimizing both bandwidth usage and processing time.

What’s New

  • Base target framework updated to .NET 8.0
  • Added compatibility with .NET 9.0
  • Updated DevExpress XPO dependencies to 24.2.3
  • Continued support for delta encoding synchronization
  • Various performance improvements and bug fixes

Framework Compatibility

  • Primary Target: .NET 8.0
  • Additional Support: .NET 9.0

Our XPO implementation continues to serve the DevExpress community.

Key Features

  • Seamless integration with DevExpress XPO
  • Efficient delta-based synchronization
  • Support for multiple database providers
  • Cross-platform compatibility
  • Easy integration with existing XPO and XAF applications

As always, if you own a license, you can compile the source code yourself from our GitHub repository. The framework maintains its commitment to providing reliable data synchronization for XPO applications.

Happy Delta Encoding! ?

 

SyncFramework Update: Now Supporting .NET 9 and EfCore 9!

SyncFramework Update: Now Supporting .NET 9 and EfCore 9!

SyncFramework Update: Now Supporting .NET 9!

SyncFramework is a C# library that simplifies data synchronization using delta encoding technology. Instead of transferring entire datasets, it efficiently synchronizes by tracking and transmitting only the changes between data versions, significantly reducing bandwidth and processing overhead.

What’s New

  • All packages now target .NET 9
  • BIT.Data.Sync packages updated to support the latest framework
  • Entity Framework Core packages upgraded to EF Core 9
  • Various minor fixes and improvements

Available Implementations

  • SyncFramework for XPO: For DevExpress XPO users
  • SyncFramework for Entity Framework Core: For EF Core users

Package Statistics

Our packages have been serving the community well, with steady adoption:

  • BIT.Data.Sync: 2,142 downloads
  • BIT.Data.Sync.AspNetCore: 1,064 downloads
  • BIT.Data.Sync.AspNetCore.Xpo: 521 downloads
  • BIT.Data.Sync.EfCore: 1,691 downloads
  • BIT.Data.Sync.EfCore.Npgsql: 1,120 downloads
  • BIT.Data.Sync.EfCore.Pomelo.MySql: 1,172 downloads
  • BIT.Data.Sync.EfCore.Sqlite: 887 downloads
  • BIT.Data.Sync.EfCore.SqlServer: 982 downloads

Resources

NuGet Packages
Source Code

As always, you can compile the source code yourself from our GitHub repository. The framework continues to provide reliable data synchronization across different platforms and databases.

Happy Delta Encoding! ?

Back to the Future of Dev Tools: DevExpress CLI templates

Back to the Future of Dev Tools: DevExpress CLI templates

My mom used to say that fashion is cyclical – whatever you do will eventually come back around. I’ve come to realize the same principle applies to technology. Many technologies have come and gone, only to resurface again in new forms.

Take Command Line Interface (CLI) commands, for example. For years, the industry pushed to move away from CLI towards graphical interfaces, promising a more user-friendly experience. Yet here we are in 2025, witnessing a remarkable return to CLI-based tools, especially in software development.

As a programmer, efficiency is key – particularly when dealing with repetitive tasks. This became evident when my business partner Javier and I decided to create our own application templates for Visual Studio. The process was challenging, mainly because Visual Studio’s template infrastructure isn’t well maintained. Documentation was sparse, and the whole process felt cryptic.

Our first major project was creating a template for Xamarin.Forms (now .NET MAUI), aiming to build a multi-target application template that could work across Android, iOS, and Windows. We relied heavily on James Montemagno’s excellent resources and videos to navigate this complex territory.

The task became significantly easier with the introduction of the new SDK-style projects. Compared to the older MSBuild project types, which were notoriously complex to template, the new format makes creating custom project templates much more straightforward.

In today’s development landscape, most application templates are distributed as NuGet packages, making them easier to share and implement. Interestingly, these packages are primarily designed for CLI use rather than Visual Studio’s graphical interface – a perfect example of technology coming full circle.

Following this trend, DevExpress has developed a new set of application templates that work cross-platform using the CLI. These templates leverage SkiaSharp for UI rendering, enabling true multi-IDE and multi-OS compatibility. While they’re not yet compatible with Apple Silicon, that support is likely coming in future updates.

The templates utilize CLI under the hood to generate new project structures. When you install these templates in Visual Studio Code or Visual Studio, they become available through both the CLI and the graphical interface, offering developers the best of both worlds.

Here is the official DevExpress blog post for the new application templates

https://www.devexpress.com/subscriptions/whats-new/#project-template-gallery-net8

Templates for Visual Studio

DevExpress Template Kit for Visual Studio – Visual Studio Marketplace

Templates for VS Code

DevExpress Template Kit for VS Code – Visual Studio Marketplace

If you want to see the list of the new installed DevExpress templates, you can use the following command on the terminal

dotnet new list dx

 

I’d love to hear your thoughts on this technological cycle. Which approach do you prefer for creating new projects – CLI or graphical interface? Let me know in the comments below!