PreviewOptions#

Options for Project.Preview. They set which part of the project is scheduled, which extra data the ScheduleResult carries, and which baseline the preview expects. new PreviewOptions() schedules the whole project and returns only the changed tasks.

Declaration#

public sealed class PreviewOptions : IDeepCloneable<PreviewOptions>
{
    public Subtree? Subtree { get; set; }
    public AnalyticsOptions Analytics { get; set; } = new();
    public bool Reasons { get; set; }
    public string? BaselineId { get; set; }
    public ProfileQuery? Profile { get; set; }

    public PreviewOptions DeepClone();
}

Set the properties you need with an object initializer: new PreviewOptions { Reasons = true }. PreviewOptions doesn't implement IEquatable<T>, so two instances compare by reference.

Properties#

Property Type Default Description
Subtree Subtree? null Schedules only one task's subtree and the tasks that depend on it. null schedules the whole project.
Analytics AnalyticsOptions new() (no analytics) Requests critical path and slack. Fills ScheduleResult.Analytics.
Reasons bool false Fills Mutation.Reason on each update with the Reason the task moved.
BaselineId string? null The baseline the preview expects. null skips the check.
Profile ProfileQuery? null Requests a load profile of the previewed dates. Fills ScheduleResult.Profile.

Subtree#

public Subtree? Subtree { get; set; }

Limits scheduling to the scope the Subtree value describes. Build the value with new Subtree(id).

Analytics#

public AnalyticsOptions Analytics { get; set; } = new();

Turns on AnalyticsOptions.Slack and AnalyticsOptions.CriticalPath for the previewed dates. With both flags false (the default), ScheduleResult.Analytics is null. With either flag set, it holds an Analytics value; check its Status before reading the data.

Reasons#

public bool Reasons { get; set; }

When true, each Mutation in Updates carries a Reason in its Reason property. When false, Reason is always null.

BaselineId#

public string? BaselineId { get; set; }

A baseline token taken from the latest ScheduleResult.BaselineId. When it isn't null and doesn't name the project's current baseline, Project.Preview throws a ProjectException with Code == ProjectError.StaleBaseline. Use it to stop a preview from running over a baseline that changed underneath the UI.

SchedulingChanges.BaselineId is checked the same way, independently of this property.

Profile#

public ProfileQuery? Profile { get; set; }

When set, ScheduleResult.Profile holds the LoadProfile of the previewed dates over the range and resources the ProfileQuery describes. When null, ScheduleResult.Profile is null. An invalid query makes Project.Preview throw an InputException.

Methods#

DeepClone#

public PreviewOptions DeepClone()

Returns a copy that shares no nested object (Subtree, Analytics, Profile) with this one.

Example#

using Plen;

var monday = Moment.FromYmdHm(2026, 1, 5, 8, 0) ?? throw new InvalidOperationException("invalid date");
var wednesday = Moment.FromYmdHm(2026, 1, 7, 8, 0) ?? throw new InvalidOperationException("invalid date");
var nextMonday = Moment.FromYmdHm(2026, 1, 12, 8, 0) ?? throw new InvalidOperationException("invalid date");

var data = new ProjectData
{
    Tasks =
    [
        new TaskData("design") { StartDate = monday, Duration = 2.0 },
        new TaskData("build") { StartDate = monday, Duration = 3.0 },
    ],
    Links = [new LinkData { Id = "l1", Source = "design", Target = "build" }],
};

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

// The user drags "design" to Wednesday.
var changes = new SchedulingChanges();
changes.Tasks.Update.Add(new TaskUpdate("design") { StartDate = wednesday });

var preview = project.Preview(changes, new PreviewOptions
{
    Reasons = true,
    BaselineId = solved.BaselineId,
    Profile = new ProfileQuery(monday, nextMonday),
});

foreach (var update in preview.Updates)
    Console.WriteLine($"{update.Id}: {update.StartDate} - {update.EndDate} ({update.Reason})");