by Joche Ojeda | Mar 2, 2025 | C#, System Theory
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
by Joche Ojeda | Feb 7, 2025 | Uncategorized
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 )))
by Joche Ojeda | Jan 22, 2025 | ADO.NET, C#, Data Synchronization, Database, DevExpress, XPO, XPO Database Replication
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! ?
by Joche Ojeda | Jan 9, 2025 | dotnet
While researching useful features in .NET 9 that could benefit XAF/XPO developers, I discovered something particularly interesting: Version 7 GUIDs (RFC 9562 specification). These new GUIDs offer a crucial feature – they’re sortable.
This discovery brought me back to an issue I encountered two years ago while working on the SyncFramework. We faced a peculiar problem where Deltas were correctly generated but processed in the wrong order in production environments. The occurrences seemed random, and no clear pattern emerged. Initially, I thought using Delta primary keys (GUIDs) to sort the Deltas would ensure they were processed in their generation order. However, this assumption proved incorrect. Through testing, I discovered that GUID generation couldn’t be trusted to be sequential. This issue affected multiple components of the SyncFramework. Whether generating GUIDs in C# or at the database level, there was no guarantee of sequential ordering. Different database engines could sort GUIDs differently. To address this, I implemented a sequence service as a solution.Enter .NET 9 with its Version 7 GUIDs (conforming to RFC 9562 specification). These new GUIDs are genuinely sequential, making them reliable for sorting operations.
To demonstrate this improvement, I created a test solution for XAF with a custom base object. The key implementation occurs in the OnSaving method:
protected override void OnSaving()
{
base.OnSaving();
if (!(Session is NestedUnitOfWork) && Session.IsNewObject(this) && oid.Equals(Guid.Empty))
{
oid = Guid.CreateVersion7();
}
}
Notice the use of CreateVersion7()
instead of the traditional NewGuid()
. For comparison, I also created another domain object using the traditional GUID generation:
protected override void OnSaving()
{
base.OnSaving();
if (!(Session is NestedUnitOfWork) && Session.IsNewObject(this) && oid.Equals(Guid.Empty))
{
oid = Guid.NewGuid();
}
}
When creating multiple instances of the traditional GUID domain object, you’ll notice that the greater the time interval between instance creation, the less likely the GUIDs will maintain sequential ordering.
GUID Version 7

GUID Old Version

This new feature in .NET 9 could significantly simplify scenarios where sequential ordering is crucial, eliminating the need for additional sequence services in many cases. Here is the repo on GitHubHappy coding until next time!
Related article
On my GUID, common problems using GUID identifiers | Joche Ojeda
by Joche Ojeda | Dec 2, 2024 | Blazor
Over time, I transitioned to using the first versions of my beloved framework, XAF. As you might know, XAF generates a polished and functional UI out of the box. Using XAF made me more of a backend developer since most of the development work wasn’t visual—especially in the early versions, where the model designer was rudimentary (it’s much better now).
Eventually, I moved on to developing .NET libraries and NuGet packages, diving deep into SOLID design principles. Fun fact: I actually learned about SOLID from DevExpress TV. Yes, there was a time before YouTube when DevExpress posted videos on technical tasks!
Nowadays, I feel confident creating and publishing my own libraries as NuGet packages. However, my “old monster” was still lurking in the shadows: UI components. I finally decided it was time to conquer it, but first, I needed to choose a platform. Here were my options:
- Windows Forms: A robust and mature platform but limited to desktop applications.
- WPF: A great option with some excellent UI frameworks that I love, but it still feels a bit “Windows Forms-ish” to me.
- Xamarin/Maui: I’m a big fan of Xamarin Forms and Xamarin/Maui XAML, but they’re primarily focused on device-specific applications.
- Blazor: This was the clear winner because it allows me to create desktop applications using Electron, embed components into Windows Forms, or even integrate with MAUI.
Recently, I’ve been helping my brother with a project in Blazor. (He’s not a programmer, but I am.) This gave me an opportunity to experiment with design patterns to get the most out of my components, which started as plain HTML5 pages.
Without further ado, here are the key insights I’ve gained so far.
Building high-quality Blazor components requires attention to both the C# implementation and Razor markup patterns. This guide combines architectural best practices with practical implementation patterns to create robust, reusable components.
1. Component Architecture and Organization
Parameter Organization
Start by organizing parameters into logical groups for better maintainability:
public class CustomForm : ComponentBase
{
// Layout Parameters
[Parameter] public string Width { get; set; }
[Parameter] public string Margin { get; set; }
[Parameter] public string Padding { get; set; }
// Validation Parameters
[Parameter] public bool EnableValidation { get; set; }
[Parameter] public string ValidationMessage { get; set; }
// Event Callbacks
[Parameter] public EventCallback<bool> OnValidationComplete { get; set; }
[Parameter] public EventCallback<string> OnSubmit { get; set; }
}
Corresponding Razor Template
<div class="form-container" style="width: @Width; margin: @Margin; padding: @Padding">
<form @onsubmit="HandleSubmit">
@if (EnableValidation)
{
<div class="validation-message">
@ValidationMessage
</div>
}
@ChildContent
</form>
</div>
2. Smart Default Values and Template Composition
Component Implementation
public class DataTable<T> : ComponentBase
{
[Parameter] public int PageSize { get; set; } = 10;
[Parameter] public bool ShowPagination { get; set; } = true;
[Parameter] public string EmptyMessage { get; set; } = "No data available";
[Parameter] public IEnumerable<T> Items { get; set; } = Array.Empty<T>();
[Parameter] public RenderFragment HeaderTemplate { get; set; }
[Parameter] public RenderFragment<T> RowTemplate { get; set; }
[Parameter] public RenderFragment FooterTemplate { get; set; }
}
Razor Implementation
<div class="table-container">
@if (HeaderTemplate != null)
{
<header class="table-header">
@HeaderTemplate
</header>
}
<div class="table-content">
@if (!Items.Any())
{
<div class="empty-state">@EmptyMessage</div>
}
else
{
@foreach (var item in Items)
{
@RowTemplate(item)
}
}
</div>
@if (ShowPagination)
{
<div class="pagination">
<!-- Pagination implementation -->
</div>
}
</div>
3. Accessibility and Unique IDs
Component Implementation
public class FormField : ComponentBase
{
private string fieldId = $"field-{Guid.NewGuid():N}";
private string labelId = $"label-{Guid.NewGuid():N}";
private string errorId = $"error-{Guid.NewGuid():N}";
[Parameter] public string Label { get; set; }
[Parameter] public string Error { get; set; }
[Parameter] public bool Required { get; set; }
}
Razor Implementation
<div class="form-field">
<label id="@labelId" for="@fieldId">
@Label
@if (Required)
{
<span class="required" aria-label="required">*</span>
}
</label>
<input id="@fieldId"
aria-labelledby="@labelId"
aria-describedby="@errorId"
aria-required="@Required" />
@if (!string.IsNullOrEmpty(Error))
{
<div id="@errorId" class="error-message" role="alert">
@Error
</div>
}
</div>
4. Virtualization and Performance
Component Implementation
public class VirtualizedList<T> : ComponentBase
{
[Parameter] public IEnumerable<T> Items { get; set; }
[Parameter] public RenderFragment<T> ItemTemplate { get; set; }
[Parameter] public int ItemHeight { get; set; } = 50;
[Parameter] public Func<ItemsProviderRequest, ValueTask<ItemsProviderResult<T>>> ItemsProvider { get; set; }
}
Razor Implementation
<div class="virtualized-container" style="height: 500px; overflow-y: auto;">
<Virtualize Items="@Items"
ItemSize="@ItemHeight"
ItemsProvider="@ItemsProvider"
Context="item">
<ItemContent>
<div class="list-item" style="height: @(ItemHeight)px">
@ItemTemplate(item)
</div>
</ItemContent>
<Placeholder>
<div class="loading-placeholder" style="height: @(ItemHeight)px">
<div class="loading-animation"></div>
</div>
</Placeholder>
</Virtualize>
</div>
Best Practices Summary
1. Parameter Organization
- Group related parameters with clear comments
- Provide meaningful default values
- Use parameter validation where appropriate
2. Template Composition
- Use RenderFragment for customizable sections
- Provide default templates when needed
- Enable granular control over component appearance
3. Accessibility
- Generate unique IDs for form elements
- Include proper ARIA attributes
- Support keyboard navigation
4. Performance
- Implement virtualization for large datasets
- Use loading states and placeholders
- Optimize rendering with appropriate conditions
Conclusion
Building effective Blazor components requires attention to both the C# implementation and Razor markup. By following these patterns and practices, you can create components that are:
- Highly reusable
- Performant
- Accessible
- Easy to maintain
- Flexible for different use cases
Remember to adapt these practices to your specific needs while maintaining clean component design principles.