skills/kashiash/xaf-skills/xaf-winforms-ui

xaf-winforms-ui

SKILL.md

XAF: WinForms UI Platform

Application Setup

// Program.cs
[STAThread]
static void Main() {
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);

    var winApplication = new MyWinApplication();
    winApplication.Setup();
    winApplication.Start();
}
// WinApplication.cs
public class MyWinApplication : WinApplication {
    public MyWinApplication() {
        DatabaseUpdateMode = DatabaseUpdateMode.UpdateDatabaseAlways;
        CheckCompatibilityType = CheckCompatibilityType.DatabaseSchema;
    }

    protected override void OnSetupStarted() {
        base.OnSetupStarted();
        ConnectionString = ConfigurationManager.ConnectionStrings["Default"].ConnectionString;
    }
}

Ribbon vs Standard Toolbar

Switch to Ribbon

// In WinApplication.cs constructor
UseOldTemplates = false; // uses Ribbon template by default

// Or explicitly set in Model Editor:
// Application > Options > FormStyle = Ribbon

Customize Ribbon Categories

// Via Application Model:
// ActionDesign > ActionToContainerMapping > ActionCategory → ContainerName
// NavigationItems > ... > Caption

Custom Ribbon Button from Controller

public class CustomRibbonController : WindowController {
    private SimpleAction customAction;

    public CustomRibbonController() {
        customAction = new SimpleAction(this, "CustomAction", "CustomCategory") {
            Caption = "Custom",
            ImageName = "Action_New",
            PaintStyle = ActionItemPaintStyle.CaptionAndImage
        };
        customAction.Execute += CustomAction_Execute;
    }
}

WinForms-Specific Editors

Data Type WinForms Editor DevExpress Control
string StringPropertyEditor TextEdit
int/decimal IntPropertyEditor SpinEdit
DateTime DateTimePropertyEditor DateEdit
bool BooleanPropertyEditor CheckEdit
enum EnumPropertyEditor ComboBoxEdit
reference LookupPropertyEditor LookupEdit
image ImagePropertyEditor PictureEdit
color ColorPropertyEditor ColorEdit
rich text RichTextPropertyEditor RichEditControl
file FileDataPropertyEditor custom with OpenFileDialog

Accessing DevExpress WinForms Controls

using DevExpress.ExpressApp.Win.Editors;
using DevExpress.XtraGrid.Views.Grid;
using DevExpress.XtraEditors;

public class CustomizeWinFormsController : ObjectViewController<ListView, MyObject> {
    protected override void OnViewControlsCreated() {
        base.OnViewControlsCreated();

        // Access GridListEditor's underlying XtraGrid
        if (View.Editor is GridListEditor gridEditor) {
            GridView gridView = gridEditor.GridView;
            gridView.OptionsView.ShowGroupPanel = false;
            gridView.OptionsView.ShowFooter = true;

            // Configure column summaries
            foreach (GridColumn col in gridView.Columns) {
                if (col.FieldName == "Amount") {
                    col.Summary.Add(SummaryItemType.Sum, "Amount", "{0:C2}");
                }
            }
        }
    }
}

// Access DetailView editor control
public class DetailViewController : ObjectViewController<DetailView, MyObject> {
    protected override void OnViewControlsCreated() {
        base.OnViewControlsCreated();

        var nameEditor = View.FindItem("Name") as StringPropertyEditor;
        if (nameEditor?.Control is TextEdit textEdit) {
            textEdit.Properties.CharacterCasing = CharacterCasing.Upper;
        }
    }
}

Layout Customization

Via Model Editor (preferred)

Path: Views > <ClassName>_DetailView > Layout

Drag-and-drop property editors into groups, tabs, and columns.

Programmatic Layout (from Controller)

using DevExpress.ExpressApp.Win.Layout;
using DevExpress.XtraLayout;

public class LayoutController : ObjectViewController<DetailView, MyObject> {
    protected override void OnViewControlsCreated() {
        base.OnViewControlsCreated();

        // Access LayoutControl
        if (View.Control is DevExpress.ExpressApp.Win.Layout.XafLayoutControl layoutControl) {
            var root = layoutControl.Root;
            // Modify layout items, groups, visibility
        }
    }
}

Background Workers (Thread Safety)

public class LongOperationController : ViewController {
    private SimpleAction longAction;

    public LongOperationController() {
        longAction = new SimpleAction(this, "LongOp", PredefinedCategory.View) {
            Caption = "Run Long Operation"
        };
        longAction.Execute += LongAction_Execute;
    }

    private void LongAction_Execute(object sender, SimpleActionExecuteEventArgs e) {
        var worker = new BackgroundWorker { WorkerReportsProgress = true };

        // Run on background thread
        worker.DoWork += (s, args) => {
            // Long-running work — NO access to UI or XAF objects here
            Thread.Sleep(3000);
            args.Result = "Done";
        };

        // Update UI on UI thread after completion
        worker.RunWorkerCompleted += (s, args) => {
            if (args.Error != null)
                throw new UserFriendlyException(args.Error.Message);

            View.ObjectSpace.Refresh();
            Application.ShowViewStrategy.ShowMessage(args.Result.ToString());
        };

        worker.RunWorkerAsync();
    }
}

IMPORTANT: Never access IObjectSpace, View, Frame, or XAF objects from the DoWork handler — they are not thread-safe.


Splash Screen

// Custom splash screen class
public class MySplashScreen : ISplashScreen {
    private SplashScreenForm form;

    public void Start() {
        form = new SplashScreenForm();
        form.Show();
    }

    public void Stop() {
        form?.Invoke(() => form.Close());
        form = null;
    }

    public void SetDisplayText(string displayText) {
        form?.Invoke(() => form.UpdateStatus(displayText));
    }
}

// Register in WinApplication.cs
protected override void CreateDefaultObjectSpaceProvider(CreateCustomObjectSpaceProviderEventArgs args) {
    base.CreateDefaultObjectSpaceProvider(args);
    SplashScreen = new MySplashScreen();
}

WinForms Navigation

// Default: NavigationFrame with accordion/tree navigation
// To change navigation style in Application Model:
// Application > Options > NavigationStyle = Tree | Accordion | NavBar

// Programmatic navigation from controller:
var detailView = Application.CreateDetailView(objectSpace, targetObject);
Application.ShowViewStrategy.ShowView(
    new ShowViewParameters(detailView), new ShowViewSource(Frame, null));

Printing / Print Preview

using DevExpress.ExpressApp.ReportsV2;

// Built-in print via XtraReports:
var reportController = Frame.GetController<ReportServiceController>();
reportController.ShowPreviewAction.DoExecute(reportData);

// Direct XtraGrid printing:
if (View.Editor is GridListEditor editor) {
    editor.GridView.ShowPrintPreview();
}

Source Links

Weekly Installs
6
GitHub Stars
2
First Seen
6 days ago
Installed on
opencode6
github-copilot6
codex6
kimi-cli6
amp6
cline6