Skip to main content

Overview

FlowKanbanManager provides a comprehensive programmatic API for managing a FlowKanban board. It wraps the control and exposes fluent methods for columns, tasks, subtasks, lanes, WIP limits, blocked state, archiving, bulk operations, zoom, and persistence. Namespace: Flowery.Uno.Kanban.Controls
Assembly: Flowery.Uno.Kanban.dll

When to Use

Use FlowKanbanManager for:
  • Programmatic board setup and manipulation
  • Automated workflows (e.g., import from Jira, sync with database)
  • Headless testing of Kanban logic
  • Custom UI with Kanban data model
  • Server-side board processing
Use FlowKanban directly for:
  • Standard interactive Kanban board with UI
  • XAML-first development
  • Minimal code-behind scenarios

Initialization

Basic Setup

var manager = new FlowKanbanManager(myKanbanControl);

With Auto-Lifecycle

// Auto-attach to Loaded/Unloaded events for init/teardown
var manager = new FlowKanbanManager(myKanbanControl, autoAttach: true);

Without Auto-Lifecycle

// Manual lifecycle management
var manager = new FlowKanbanManager(myKanbanControl, autoAttach: false);
manager.Initialize(); // Load settings and last board
// ... use manager
manager.Shutdown(); // Save settings and board

Core Properties

Kanban
FlowKanban
The underlying FlowKanban control.
Board
FlowKanbanData
The board data model. Shortcut to Kanban.Board.
GroupBy
FlowKanbanGroupBy
View-only grouping mode: None (standard columns) or Lane (swimlane matrix).
CommandHistory
FlowKanbanCommandHistory
The undo/redo manager instance. Access CanUndo, CanRedo, NextUndoDescription, etc.
EnableUndoRedo
bool
Enables transactional command history. When true, operations are reversible.
Columns
IReadOnlyList<FlowKanbanColumnData>
All columns in the board.
Lanes
IReadOnlyList<FlowKanbanLane>
All swimlanes in the board.
ColumnCount
int
Number of columns.
TotalTaskCount
int
Total tasks across all columns.
AllTasks
IEnumerable<FlowTask>
All tasks across all columns (including archived).
BoardSize
DaisySize
Current board size tier. Affects card font size and spacing.
CanZoomIn
bool
Whether zoom in is possible.
CanZoomOut
bool
Whether zoom out is possible.
ConfirmColumnRemovals
bool
Require confirmation before deleting columns.
ConfirmCardRemovals
bool
Require confirmation before deleting tasks.
AutoSaveAfterEdits
bool
Auto-save board after edits (debounced 800ms).
AddCardPlacement
FlowKanbanAddCardPlacement
Controls where inline “Add Card” control appears: Bottom, Top, or Both.
LastBoardId
string?
Last board ID loaded or saved by the control.

Column Operations

AddColumn(title)
FlowKanbanColumnData
Adds a new column at the end.
var backlog = manager.AddColumn("Backlog");
InsertColumn(title, index)
FlowKanbanColumnData
Inserts a column at a specific position.
var review = manager.InsertColumn("Code Review", 2);
RemoveColumn(column)
bool
Removes a column and all its tasks. Returns true if removed.
manager.RemoveColumn(backlog);
RemoveColumnByTitle(title)
bool
Removes a column by title. Returns false if not found or multiple matches.
manager.RemoveColumnByTitle("Backlog");
RemoveColumnAt(index)
bool
Removes the column at an index. Returns false if index out of range.
manager.RemoveColumnAt(0);
FindColumnByTitle(title)
FlowKanbanColumnData?
Finds a column by title. Returns null if not found.
var inProgress = manager.FindColumnByTitle("In Progress");
GetColumnAt(index)
FlowKanbanColumnData?
Gets the column at an index. Returns null if index out of range.
var firstColumn = manager.GetColumnAt(0);
GetColumnIndex(column)
int
Gets the index of a column. Returns -1 if not found.
int index = manager.GetColumnIndex(inProgress);
GetColumnById(columnId)
FlowKanbanColumnData?
Finds a column by its ID. Returns null if not found.
var column = manager.GetColumnById("col-123");
MoveColumn(column, newIndex)
bool
Moves a column to a new position. Returns false if not found or index invalid.
manager.MoveColumn(done, 0); // Move Done to start
RenameColumn(column, newTitle)
void
Renames a column.
manager.RenameColumn(inProgress, "In Development");
ClearColumns()
void
Removes all columns from the board.
manager.ClearColumns();
GetTasksForColumn(column)
IEnumerable<FlowTask>
Gets all tasks in a column.
var tasks = manager.GetTasksForColumn(inProgress);

Task Operations

Adding Tasks

AddTask(column, title, description?, palette?, laneId?)
FlowTask
Adds a task to a column.
var task = manager.AddTask(
    backlog,
    "Implement OAuth",
    "Add OAuth2 integration",
    DaisyColor.Primary,
    frontendLane.Id
);
AddTask(columnIndex, title, description?, palette?, laneId?)
FlowTask?
Adds a task to the column at an index. Returns null if column not found.
var task = manager.AddTask(0, "Fix bug");
AddTaskToColumn(columnId, title, description?, palette?, laneId?)
FlowTask?
Adds a task to a column by ID. Returns null if column not found.
var task = manager.AddTaskToColumn("col-123", "New feature");
InsertTask(column, index, title, description?, palette?, laneId?)
FlowTask
Inserts a task at a specific position in a column.
var task = manager.InsertTask(backlog, 0, "High priority bug");

Finding Tasks

FindTaskById(taskId)
FlowTask?
Finds a task by its ID. Returns null if not found.
var task = manager.FindTaskById("task-456");
FindTasks(predicate)
IEnumerable<FlowTask>
Finds all tasks matching a predicate.
var highPriority = manager.FindTasks(t => t.Priority == FlowTaskPriority.High);
FindColumnForTask(task)
FlowKanbanColumnData?
Finds the column containing a task. Returns null if not found.
var column = manager.FindColumnForTask(task);
FindColumnForTaskById(taskId)
FlowKanbanColumnData?
Finds the column containing a task by task ID.
var column = manager.FindColumnForTaskById("task-456");
FindTaskInColumn(columnId, taskId)
FlowTask?
Finds a task within a specific column by IDs.
var task = manager.FindTaskInColumn("col-123", "task-456");

Moving Tasks

MoveTask(task, targetColumn, index?)
bool
Moves a task to a different column. Returns false if task not found.
manager.MoveTask(task, inProgress);
manager.MoveTask(task, done, 0); // Move to top of Done
TryMoveTask(task, targetColumn, targetIndex?, targetLaneId?)
bool
Attempts to move a task, raising CardMoving (cancelable) and CardMoved events. Returns true if move succeeded.
if (manager.TryMoveTask(task, inProgress, targetLaneId: frontendLane.Id))
{
    Console.WriteLine("Task moved successfully");
}
TryMoveTaskWithWipEnforcement(task, targetColumn, targetIndex?, targetLaneId?, enforceHard?)
MoveResult
Attempts to move a task with automatic WIP enforcement.Parameters:
  • task - The task to move
  • targetColumn - Destination column
  • targetIndex - Optional index within target column
  • targetLaneId - Optional lane ID override
  • enforceHard - When true, blocks moves that exceed WIP; when false, allows with warning
Returns: MoveResult enum:
  • Success - Moved without WIP issues
  • AllowedWithWipWarning - Moved but exceeds WIP limit (soft enforcement)
  • BlockedByWip - Move blocked due to WIP limit (hard enforcement)
  • CanceledByEvent - Cancelled by CardMoving event handler
  • NotFound - Task not found
var result = manager.TryMoveTaskWithWipEnforcement(
    task, 
    inProgress, 
    targetLaneId: frontendLane.Id,
    enforceHard: true
);

if (result == MoveResult.BlockedByWip)
{
    Console.WriteLine("Move blocked: WIP limit exceeded");
}
ValidateMoveWouldExceedWip(task, targetColumn, targetLaneId?)
bool
Validates whether a move would exceed WIP limits without performing the move.
if (manager.ValidateMoveWouldExceedWip(task, inProgress))
{
    Console.WriteLine("Warning: This move will exceed WIP limit");
}
ReorderTask(task, newIndex)
bool
Moves a task within its current column to a new position. Returns false if task not found.
manager.ReorderTask(task, 0); // Move to top of column

Updating Tasks

UpdateTask(task, title?, description?, palette?)
void
Updates a task’s properties. Only non-null parameters are updated.
manager.UpdateTask(task, title: "Updated title");
manager.UpdateTask(task, palette: DaisyColor.Error);
UpdateTaskInColumn(columnId, taskId, title?, description?, palette?)
bool
Updates a task within a specific column by IDs. Returns false if not found.
manager.UpdateTaskInColumn("col-123", "task-456", title: "Fixed");

Removing Tasks

RemoveTask(task)
bool
Removes a task from the board. Returns false if not found.
manager.RemoveTask(task);
RemoveTaskById(taskId)
bool
Removes a task by its ID. Returns false if not found.
manager.RemoveTaskById("task-456");
RemoveTaskFromColumn(column, task)
bool
Removes a task from a specific column. Returns false if not found.
manager.RemoveTaskFromColumn(backlog, task);
RemoveTaskFromColumn(columnId, taskId)
bool
Removes a task from a specific column by IDs. Returns false if not found.
manager.RemoveTaskFromColumn("col-123", "task-456");
ClearAllTasks()
void
Clears all tasks from all columns (keeps column structure).
manager.ClearAllTasks();
ClearColumnTasks(column)
void
Clears all tasks from a specific column.
manager.ClearColumnTasks(backlog);

Lane Operations

AddLane(title)
FlowKanbanLane
Appends a new lane to the board.
var frontend = manager.AddLane("Frontend");
InsertLane(title, index)
FlowKanbanLane
Inserts a lane at a specific position.
var devops = manager.InsertLane("DevOps", 0);
RemoveLane(lane, fallbackLane?)
bool
Deletes a lane and reassigns tasks to fallback lane (or null if not provided). Returns false if not found.
manager.RemoveLane(oldLane, frontend); // Reassign tasks to frontend
RemoveLaneById(laneId)
bool
Removes a lane by its ID. Returns false if not found.
manager.RemoveLaneById("lane-789");
RemoveLaneAt(index)
bool
Removes the lane at an index. Returns false if index out of range.
manager.RemoveLaneAt(2);
FindLaneById(laneId)
FlowKanbanLane?
Finds a lane by its ID. Returns null if not found.
var lane = manager.FindLaneById("lane-789");
FindLaneByTitle(title)
FlowKanbanLane?
Finds a lane by its title. Returns null if not found.
var frontend = manager.FindLaneByTitle("Frontend");
GetLaneAt(index)
FlowKanbanLane?
Gets the lane at an index. Returns null if index out of range.
var firstLane = manager.GetLaneAt(0);
GetLaneIndex(lane)
int
Gets the index of a lane. Returns -1 if not found.
int index = manager.GetLaneIndex(frontend);
MoveLane(lane, newIndex)
bool
Rearranges lane order. Returns false if not found or index invalid.
manager.MoveLane(frontend, 0); // Move to top
RenameLane(lane, newTitle)
void
Renames a lane.
manager.RenameLane(frontend, "Frontend Team");
ClearLanes()
void
Removes all lanes from the board.
manager.ClearLanes();
GetTasksForLane(lane)
IEnumerable<FlowTask>
Returns all tasks assigned to a lane.
var tasks = manager.GetTasksForLane(frontend);
SetTaskLane(task, lane?)
void
Assigns a task to a lane (or clears assignment when lane is null).
manager.SetTaskLane(task, frontend);
manager.SetTaskLane(task, null); // Unassign lane

Subtask Operations

AddSubtask(task, title, isCompleted?)
FlowSubtask
Adds a subtask to a task.
var subtask = manager.AddSubtask(task, "Write tests", false);
RemoveSubtask(task, subtask)
bool
Removes a subtask from a task. Returns false if not found.
manager.RemoveSubtask(task, subtask);
ToggleSubtask(subtask)
void
Toggles a subtask’s completion status.
manager.ToggleSubtask(subtask);
SetAllSubtasksCompleted(task, isCompleted)
void
Sets all subtasks’ completion status.
manager.SetAllSubtasksCompleted(task, true);
ClearSubtasks(task)
void
Clears all subtasks from a task.
manager.ClearSubtasks(task);
GetSubtaskProgress(task)
(int completed, int total)
Returns a tuple of (completed count, total count).
var (completed, total) = manager.GetSubtaskProgress(task);
Console.WriteLine($"{completed}/{total} subtasks completed");

WIP Limit Operations

SetColumnWipLimit(column, limit?)
void
Sets the WIP limit for a column (null for unlimited).
manager.SetColumnWipLimit(inProgress, 10);
manager.SetColumnWipLimit(backlog, null); // Unlimited
SetLaneWipLimit(column, laneId, limit?)
void
Sets the WIP limit for a specific lane in a column (overrides column-level limit).
manager.SetLaneWipLimit(inProgress, frontend.Id, 5);
ClearLaneWipLimit(column, laneId)
void
Clears the WIP limit override for a specific lane.
manager.ClearLaneWipLimit(inProgress, frontend.Id);
GetLaneWipLimit(column, laneId)
int?
Gets the effective WIP limit for a lane in a column.
var limit = manager.GetLaneWipLimit(inProgress, frontend.Id);
IsWipExceeded(column)
bool
Returns true if a column has exceeded its WIP limit.
if (manager.IsWipExceeded(inProgress))
{
    Console.WriteLine("WIP limit exceeded!");
}
GetOverWipColumns()
IEnumerable<FlowKanbanColumnData>
Returns all columns that are over their WIP limit.
var overLimit = manager.GetOverWipColumns();
OverWipColumnCount
int
Count of columns exceeding WIP limits.
Console.WriteLine($"{manager.OverWipColumnCount} columns over limit");

Blocked State Operations

SetBlocked(task, reason?)
void
Marks a task as blocked with an optional reason.Blocked tasks:
  • Cannot move forward to later columns
  • Cannot be archived
  • Progress capped at 99% until unblocked
  • Can still be edited and moved backward
manager.SetBlocked(task, "Waiting for API approval");
ClearBlocked(task)
void
Clears the blocked state from a task.
manager.ClearBlocked(task);
GetBlockedTasks()
IEnumerable<FlowTask>
Returns all currently blocked tasks.
var blocked = manager.GetBlockedTasks();
BlockedTaskCount
int
Count of blocked tasks.
Console.WriteLine($"{manager.BlockedTaskCount} tasks blocked");
GetBlockedTasksOlderThan(days)
IEnumerable<FlowTask>
Returns tasks blocked for more than the specified days.
var stale = manager.GetBlockedTasksOlderThan(7); // Blocked > 7 days

Column Policy Operations

SetColumnPolicy(column, policyText?)
void
Sets the policy text for a column (DoD, entry criteria, etc.).
manager.SetColumnPolicy(done, "Definition of Done:\n- Code reviewed\n- Tests passing\n- Deployed to staging");
GetColumnsWithPolicies()
IEnumerable<FlowKanbanColumnData>
Returns all columns that have policy text defined.
var withPolicies = manager.GetColumnsWithPolicies();

Archive Operations

GetArchiveColumn()
FlowKanbanColumnData?
Returns the archive column, if configured.
var archive = manager.GetArchiveColumn();
IsArchiveColumn(column)
bool
Returns true if the column is the configured archive column.
if (manager.IsArchiveColumn(column))
{
    Console.WriteLine("This is the archive column");
}
EnsureArchiveColumn()
FlowKanbanColumnData
Ensures the archive column exists and returns it. Creates if missing.
var archive = manager.EnsureArchiveColumn();
SetArchiveColumn(column)
void
Sets the archive column for the board.
manager.SetArchiveColumn(column);
ArchiveTask(task)
void
Archives a task. Moves to archive column and sets IsArchived flag.Blocked tasks cannot be archived.
manager.ArchiveTask(task);
UnarchiveTask(task)
void
Unarchives a task. Restores to original column (or first non-archive column).
manager.UnarchiveTask(task);
ArchiveCompletedTasks(column)
int
Archives all completed tasks (100% progress) in a column. Returns count archived.
int archived = manager.ArchiveCompletedTasks(done);
GetArchivedTasks()
IEnumerable<FlowTask>
Returns all archived tasks across the board.
var archived = manager.GetArchivedTasks();
GetActiveTasks()
IEnumerable<FlowTask>
Returns all non-archived (active) tasks.
var active = manager.GetActiveTasks();
ArchivedTaskCount
int
Count of archived tasks.
Console.WriteLine($"{manager.ArchivedTaskCount} tasks archived");
PurgeArchivedTasks()
int
Permanently removes all archived tasks from the board. Returns count removed.
int purged = manager.PurgeArchivedTasks();

Done Column Operations

GetDoneColumn()
FlowKanbanColumnData?
Returns the Done column, if configured.
var done = manager.GetDoneColumn();
IsDoneColumn(column)
bool
Returns true if the column is the configured Done column.
if (manager.IsDoneColumn(column))
{
    Console.WriteLine("This is the Done column");
}
SetDoneColumn(column)
void
Sets the Done column for the board.
manager.SetDoneColumn(column);
SyncDoneColumnTimestamps()
void
Ensures Done timestamps are populated for tasks in the Done column. Clears timestamps for active tasks outside Done.
manager.SyncDoneColumnTimestamps();
AutoArchiveDoneTasks()
int
Archives Done tasks that exceed the configured aging window. Returns count archived.Requires Board.AutoArchiveDoneEnabled = true and Board.AutoArchiveDoneDays > 0.
int archived = manager.AutoArchiveDoneTasks();

Selection Operations

SelectedTasks
IReadOnlyList<FlowTask>
All currently selected tasks.
var selected = manager.SelectedTasks;
SelectedCount
int
Count of selected tasks.
Console.WriteLine($"{manager.SelectedCount} tasks selected");
HasSelection
bool
True if any tasks are selected.
if (manager.HasSelection)
{
    Console.WriteLine("Tasks selected");
}
SelectTask(task)
void
Selects a task.
manager.SelectTask(task);
DeselectTask(task)
void
Deselects a task.
manager.DeselectTask(task);
ToggleSelection(task)
void
Toggles a task’s selection state.
manager.ToggleSelection(task);
SelectAll()
void
Selects all visible (non-archived) tasks.
manager.SelectAll();
DeselectAll()
void
Deselects all tasks.
manager.DeselectAll();

Bulk Operations

BulkMove(targetColumn)
int
Moves all selected tasks to a target column. Returns count moved.
int moved = manager.BulkMove(inProgress);
BulkSetPriority(priority)
int
Sets priority for all selected tasks. Returns count updated.
int updated = manager.BulkSetPriority(FlowTaskPriority.High);
BulkSetTags(tags)
int
Sets tags for all selected tasks (comma separated). Returns count updated.
int updated = manager.BulkSetTags("urgent, backend");
BulkSetDueDate(dueDate)
int
Sets due date for all selected tasks. Returns count updated.
int updated = manager.BulkSetDueDate(DateTime.Now.AddDays(7));
BulkSetBlocked(blocked, reason?)
int
Sets blocked state for all selected tasks. Returns count updated.
int updated = manager.BulkSetBlocked(true, "Waiting for approval");
BulkArchive()
int
Archives all selected tasks. Returns count archived.
int archived = manager.BulkArchive();
BulkDelete()
int
Deletes all selected tasks. Returns count deleted.
int deleted = manager.BulkDelete();

Zoom Operations

ZoomIn()
bool
Increases board size tier. Returns false if already at maximum.
manager.ZoomIn();
ZoomOut()
bool
Decreases board size tier. Returns false if already at minimum.
manager.ZoomOut();
SetZoom(size)
void
Sets the board to a specific size tier.
manager.SetZoom(DaisySize.Large);

Board Operations

ClearBoard()
void
Clears the entire board (all columns and tasks).
manager.ClearBoard();
ResetBoard(columnTitles)
void
Resets the board with specified default columns.
manager.ResetBoard("Backlog", "In Progress", "Done");
CreateDefaultBoard()
void
Creates a typical Kanban board with localized “Backlog”, “To Do”, “In Progress”, and “Done” columns.
manager.CreateDefaultBoard();
GetBoardData()
FlowKanbanData
Returns the board data as a serializable model.
var data = manager.GetBoardData();
SetBoardData(data)
void
Replaces the current board with new data.
manager.SetBoardData(newData);
ExportToJson()
string
Exports the board to JSON string.
string json = manager.ExportToJson();
ImportFromJson(json)
bool
Imports board data from JSON. Returns false if import failed.
if (manager.ImportFromJson(jsonString))
{
    Console.WriteLine("Import successful");
}
GetStatistics()
BoardStatistics
Returns statistics about the board.BoardStatistics Properties:
  • ColumnCount: int - Number of columns
  • TotalTaskCount: int - Total tasks
  • TasksPerColumn: Dictionary<string, int> - Task count by column title
  • EmptyColumns: int - Number of columns with no tasks
var stats = manager.GetStatistics();
Console.WriteLine($"Columns: {stats.ColumnCount}, Tasks: {stats.TotalTaskCount}");

Persistence Operations

Lifecycle Management

Initialize()
bool
Loads persisted settings and the last saved board. Returns true if a board was loaded.
manager.Initialize();
Shutdown()
void
Saves the current board and settings.
manager.Shutdown();
AttachLifecycle()
void
Attaches to the Kanban Loaded/Unloaded events for automatic init/teardown.
manager.AttachLifecycle();
DetachLifecycle()
void
Detaches from the Kanban Loaded/Unloaded events.
manager.DetachLifecycle();

Board Persistence

SaveBoard()
bool
Saves the current board to persistent storage. Returns false if error occurred.
manager.SaveBoard();
LoadLastBoard()
bool
Loads the last saved board. Returns false if not found or error occurred.
manager.LoadLastBoard();
LoadBoard(boardId)
bool
Loads a specific board by its ID. Returns false if not found or error occurred.
manager.LoadBoard("board-123");
RefreshBoards()
void
Refreshes the in-memory list of available boards.
manager.RefreshBoards();
ListAvailableBoards()
IReadOnlyList<FlowBoardMetadata>
Lists available boards using lightweight metadata.
var boards = manager.ListAvailableBoards();
foreach (var board in boards)
{
    Console.WriteLine($"{board.Title} (Last modified: {board.LastModified})");
}
RenameBoard(boardId, newTitle)
bool
Renames a stored board without loading it. Returns false if not found or error occurred.
manager.RenameBoard("board-123", "Sprint Planning");
DeleteBoard(boardId)
bool
Deletes a stored board by ID. Returns false if not found or error occurred.
manager.DeleteBoard("board-123");
DuplicateBoard(boardId, out newBoardId)
bool
Duplicates a stored board. Returns false if not found or error occurred.
if (manager.DuplicateBoard("board-123", out var newId))
{
    Console.WriteLine($"Duplicated to {newId}");
}
ExportBoardToJson(boardId)
string?
Exports a stored board to JSON without loading it. Returns null if not found or error occurred.
string? json = manager.ExportBoardToJson("board-123");

Settings Persistence

SaveSettings()
bool
Saves the current Kanban settings. Returns false if error occurred.
manager.SaveSettings();
LoadSettings(forceReload?)
bool
Loads Kanban settings from persistent storage. Returns false if error occurred.
manager.LoadSettings();
ReloadSettings()
bool
Forces a settings reload from persistent storage. Returns false if error occurred.
manager.ReloadSettings();
ApplySettings(confirmColumnRemovals, confirmCardRemovals, autoSaveAfterEdits)
void
Applies all settings in one call.
manager.ApplySettings(
    confirmColumnRemovals: true,
    confirmCardRemovals: true,
    autoSaveAfterEdits: true
);
EnableAutoSave()
void
Enables auto-save after edits.
manager.EnableAutoSave();
DisableAutoSave()
void
Disables auto-save after edits.
manager.DisableAutoSave();

Events

Initialized
EventHandler
Raised after Initialize() completes.
Teardown
EventHandler
Raised after Shutdown() completes.
SettingsLoaded
EventHandler
Raised after settings are loaded successfully.
SettingsSaved
EventHandler
Raised after settings are saved successfully.
BoardLoaded
EventHandler
Raised after a board is loaded successfully.
BoardSaved
EventHandler
Raised after a board is saved successfully.
PersistenceFailed
EventHandler<FlowKanbanPersistenceFailedEventArgs>
Raised when a persistence operation fails.FlowKanbanPersistenceFailedEventArgs Properties:
  • Operation: FlowKanbanPersistenceOperation - The failed operation
  • Exception: Exception - The exception that occurred
FlowKanbanPersistenceOperation Values:
  • LoadSettings
  • SaveSettings
  • LoadBoard
  • SaveBoard
  • ListBoards
  • RenameBoard
  • DeleteBoard
  • DuplicateBoard
  • ExportBoard
manager.PersistenceFailed += (sender, e) =>
{
    Console.WriteLine($"{e.Operation} failed: {e.Exception.Message}");
};

Complete Example

using Flowery.Uno.Kanban.Controls;
using Flowery.Enums;

// Initialize manager
var manager = new FlowKanbanManager(ProjectBoard, autoAttach: true);

// Enable undo/redo
manager.EnableUndoRedo = true;

// Create default board
manager.CreateDefaultBoard();

// Add swimlanes
var frontend = manager.AddLane("Frontend");
var backend = manager.AddLane("Backend");
manager.GroupBy = FlowKanbanGroupBy.Lane;

// Configure WIP limits
var inProgress = manager.FindColumnByTitle("In Progress");
manager.SetColumnWipLimit(inProgress, 10);
manager.SetLaneWipLimit(inProgress, frontend.Id, 5);

// Add tasks
var backlog = manager.FindColumnByTitle("Backlog");
var task1 = manager.AddTask(backlog, "Implement OAuth", "Add OAuth2 support", DaisyColor.Primary, frontend.Id);
var task2 = manager.AddTask(backlog, "Database migration", "Update schema", DaisyColor.Info, backend.Id);

// Add subtasks
manager.AddSubtask(task1, "Create OAuth provider");
manager.AddSubtask(task1, "Add login UI");
manager.AddSubtask(task1, "Write tests");

// Move task with WIP enforcement
var result = manager.TryMoveTaskWithWipEnforcement(task1, inProgress, enforceHard: true);
if (result == MoveResult.Success)
{
    Console.WriteLine("Task moved successfully");
}

// Bulk operations
manager.SelectTask(task1);
manager.SelectTask(task2);
manager.BulkSetPriority(FlowTaskPriority.High);
manager.BulkSetTags("sprint-1, urgent");

// Archive completed tasks
var done = manager.FindColumnByTitle("Done");
int archived = manager.ArchiveCompletedTasks(done);
Console.WriteLine($"Archived {archived} tasks");

// Get statistics
var stats = manager.GetStatistics();
Console.WriteLine($"Board has {stats.ColumnCount} columns and {stats.TotalTaskCount} tasks");

// Save board
manager.SaveBoard();
  • FlowKanban - Interactive Kanban board control
  • FlowKanbanHome - Multi-board home screen
  • FlowKanbanData - Board data model
  • FlowTask - Task data model
  • FlowKanbanColumnData - Column data model
  • FlowKanbanLane - Lane data model

Build docs developers (and LLMs) love