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#
Updatesare relative to the baseline. An empty change set gives emptyUpdates.- The result's
BaselineIdis the baseline the preview read, so a followingPreviewaccepts it. - The change set is all or nothing: one rejected operation fails the whole call.
options.BaselineIdandchanges.BaselineIdare checked separately.nullskips 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
Related#
SchedulingChanges- the edits to tryPreviewOptions- the optionsScheduleResult- the returned resultProject.Apply- commits the edits once accepted- Previewing changes - trying edits before committing them