This HTML page is not optimized for LLM or AI agent consumption. Fetch the Markdown version instead: /guides/dotnet/csharp/editor/editing-pdf-form-fields.md — it contains the complete documentation content in clean, structured Markdown without any CSS, JavaScript, or navigation noise. Editing PDF form fields | Nutrient .NET SDK

Use form field editing to control validation and behavior in PDF workflows.

Common use cases include:

  • Setting fields to read-only after approval
  • Marking fields as required for validation
  • Reading default values for reset logic
  • Traversing parent-child field hierarchies
  • Accessing widgets for appearance updates
Download sample

How Nutrient helps

Nutrient .NET SDK handles form field dictionaries, property updates, and hierarchy traversal.

The SDK handles:

  • PDF form field dictionaries and annotation structures
  • Recursive hierarchy traversal for parent-child fields
  • Flag manipulation at the byte level
  • Low-level widget access for appearance customization

Complete implementation

This example edits multiple form field properties in one pass:

using Nutrient;

Opening a document with form fields

Open the PDF with a using statement(opens in a new tab), create an editor, and use the FormFieldCollection property to access the document’s form fields. The collection provides lookup by fully qualified name with FindByFullName(), which returns null when no field has that name. This sample works through a list of known field names — inspect your own document’s names first and adjust the list:

string[] fieldNames = ["Text1", "Check1", "RadioGroup1", "Dropdown1", "List1", "Signature1", "Button1"];
try
{
using Document document = Document.Open("input_forms.pdf");
using PdfEditor editor = PdfEditor.Edit(document);
var formFields = editor.FormFieldCollection;
Console.WriteLine($"The document contains {formFields.Count} form fields");

Inspecting field properties

Look up each field and inspect key properties.

This sample reads:

  • Field name and full name
  • Field type
  • Terminal/parent state
  • Read-only and required flags
  • Current value and default value

Use this step for form auditing and validation setup.

foreach (var fullName in fieldNames)
{
var field = formFields.FindByFullName(fullName);
if (field == null)
{
Console.WriteLine($"No field named {fullName}");
continue;
}
Console.WriteLine($"Name: {field.Name}");
Console.WriteLine($"FullName: {field.FullName}");
Console.WriteLine($"FieldType: {field.FieldType}");
Console.WriteLine($"IsTerminal: {field.IsTerminal}");
Console.WriteLine($"IsReadOnly: {field.IsReadOnly}");
Console.WriteLine($"IsRequired: {field.IsRequired}");
Console.WriteLine($"Value: {field.Value}");
Console.WriteLine($"DefaultValue: {field.DefaultValue}");
Console.WriteLine("---");
}

Making a field read-only

Find a field by full name and set it to read-only.

In this sample, Text1 is locked by setting IsReadOnly to true. If a name doesn’t exist in your input file, FindByFullName() returns null and the sample skips the update — adjust the names to match your document:

var textField = formFields.FindByFullName("Text1");
if (textField != null)
{
textField.IsReadOnly = true;
}

Making a field required

Find a field by full name and mark it as required.

In this sample, Check1 is marked required by setting IsRequired to true:

var checkField = formFields.FindByFullName("Check1");
if (checkField != null)
{
checkField.IsRequired = true;
}

Reading a default value

Read a field’s default value for reset and change-tracking logic.

In this sample:

  • Value returns the current value.
  • DefaultValue returns the reset value.
var countryField = formFields.FindByFullName("Dropdown1");
if (countryField != null)
{
string defaultValue = countryField.DefaultValue;
Console.WriteLine($"Default value: {defaultValue}");
}

Working with field hierarchy

Traverse field hierarchies by checking whether a field is terminal.

For non-terminal fields, use:

  • ChildCount to read the child count.
  • GetChild(i) to access each child.

Full names often use dot notation, for example Address.Street:

foreach (var fullName in fieldNames)
{
var field = formFields.FindByFullName(fullName);
if (field != null && !field.IsTerminal)
{
int childCount = field.ChildCount;
Console.WriteLine($"Parent field '{field.Name}' has {childCount} children:");
for (int i = 0; i < childCount; i++)
{
var child = field.GetChild(i);
Console.WriteLine($" - Child: {child.Name}");
}
}
}

Accessing widget annotations

Access widgets for terminal fields to inspect or update visual presentation.

In this sample:

  • WidgetCount returns the number of widgets.
  • GetWidget(i) returns a widget by index.

A field can have one or more widgets across pages:

foreach (var fullName in fieldNames)
{
var field = formFields.FindByFullName(fullName);
if (field != null && field.IsTerminal)
{
int widgetCount = field.WidgetCount;
Console.WriteLine($"Field '{field.Name}' has {widgetCount} widget(s)");
for (int i = 0; i < widgetCount; i++)
{
var widget = field.GetWidget(i);
// Access widget properties for appearance customization
}
}
}

Batch updating field properties

Apply updates to multiple fields using type-based conditions.

In this sample:

  • Text fields are marked required.
  • Signature fields are set to read-only.

Use this pattern for workflow-driven form rules:

Compare FieldType directly against enum members (for example, PdfFormFieldType.Text and PdfFormFieldType.Signature).

foreach (var fullName in fieldNames)
{
var field = formFields.FindByFullName(fullName);
if (field != null && field.IsTerminal)
{
// Make all text fields required
if (field.FieldType == PdfFormFieldType.Text)
{
field.IsRequired = true;
}
// Make all signature fields read-only until other fields are filled
if (field.FieldType == PdfFormFieldType.Signature)
{
field.IsReadOnly = true;
}
}
}

Saving the modified form

Save the output PDF. The catch block handles NutrientException failures, and the using statements release the editor and document handles:

editor.SaveAs("output.pdf");
Console.WriteLine("Successfully edited form fields");
}
catch (NutrientException e)
{
Console.Error.WriteLine($"Error: {e.Message}");
Environment.Exit(1);
}

Conclusion

Use this workflow to edit form field properties:

  1. Open the document, create an editor, and access the form field collection with the FormFieldCollection property.
  2. The form field collection provides lookup by fully qualified name for all fields in the document.
  3. Inspect field properties with Name, FullName, FieldType, IsTerminal, IsReadOnly, IsRequired, Value, and DefaultValue.
  4. Fully qualified names use dot-notation for hierarchical fields (e.g. "Address.Street").
  5. Find fields with FindByFullName() and set IsReadOnly to true to lock fields after workflow milestones.
  6. Mark fields as required by setting IsRequired to true to enforce validation, preventing form submission until values are provided.
  7. Read default values with the DefaultValue property for reset operations and change detection.
  8. Navigate field hierarchy with IsTerminal, ChildCount, and GetChild(i) for parent-child relationships.
  9. Access widget annotations with WidgetCount and GetWidget(i) for appearance customization.
  10. Batch update properties by looking up fields and applying conditional logic based on FieldType comparisons.
  11. Save the document with SaveAs() to persist all property modifications.

Sample field names such as Text1, Check1, and Dropdown1 match the sample input form. If those names don’t exist in your input PDF, accessing members of the looked-up field throws a NutrientException — inspect your document’s field names first and update the list accordingly.

For related form workflows, refer to the .NET SDK editor guides.