Project.Preview#

Applies hypothetical changes to a copy of the solved baseline of a Project and schedules the copy. The project isn't modified. Use it to show what an edit would do before committing it with Apply.

Signature#

public ScheduleResult Preview(SchedulingChanges changes, PreviewOptions options)

Synchronous and CPU-only. Reads the project without changing it. Project isn't thread-safe, so don't call Preview on one instance from several threads at once.

Parameters#

Name Type Description
changes SchedulingChanges The edits to try
options PreviewOptions Subtree, analytics, reasons, baseline check and an optional load profile

Behavior#

  • Updates are relative to the baseline. An empty change set gives empty Updates.
  • The result's BaselineId is the baseline the preview read, so a following Preview accepts it.
  • The change set is all or nothing: one rejected operation fails the whole call.
  • options.BaselineId and changes.BaselineId are checked separately. null skips a check.
  • An explicit start on non-working time is kept unsnapped when the task has no predecessor. The end is computed forward from it on the working calendar.

Returns#

A ScheduleResult for the previewed state.

Errors#

Error When
ProjectException with Code == ProjectError.NoBaseline The project is unsolved, including after Apply
ProjectException with Code == ProjectError.StaleBaseline options.BaselineId or changes.BaselineId doesn't name the current baseline
InputException An operation in changes is rejected (Path and Message describe the first one), or the Profile query is invalid (To <= From or too many buckets at to, an unknown resource at resources)
ArgumentNullException changes or options is null

Example#

Preview a drag of task b, then check that the project keeps its dates.

using Plen;

static Moment Day(int day) =>
    Moment.FromYmdHm(2026, 1, day, 0, 0) ?? throw new InvalidOperationException("invalid date");

var data = new ProjectData
{
    Tasks = [new TaskData("b") { StartDate = Day(1), Duration = 1.0 }],
};
data.Config.UseCalendars = false;

var project = new Project();
var solved = project.Solve(data, new SolveOptions());

var drag = new SchedulingChanges();
drag.Tasks.Update.Add(new TaskUpdate("b") { StartDate = Day(5) });

var preview = project.Preview(drag, new PreviewOptions { BaselineId = solved.BaselineId });
foreach (var update in preview.Updates)
    Console.WriteLine($"task {update.Id}: {update.StartDate} .. {update.EndDate}");
// task b: 2026-01-05 00:00 .. 2026-01-06 00:00

// The project is unchanged: an empty preview reports no updates.
var unchanged = project.Preview(new SchedulingChanges(), new PreviewOptions());
Console.WriteLine(unchanged.Updates.Count); // 0