# Format Painter in ASP.NET Core: Building Custom Text Formatting with TX Text Control

> This article demonstrates how to build a Format Painter feature using the TX Text Control Document Editor, implementing format detection, copy and paste operations, and custom style handling through the JavaScript API.

- **Author:** Deepika Kathiravan
- **Published:** 2025-09-09
- **Modified:** 2025-11-16
- **Description:** This article demonstrates how to build a Format Painter feature using the TX Text Control Document Editor, implementing format detection, copy and paste operations, and custom style handling through the JavaScript API.
- **7 min read** (1288 words)
- **Tags:**
  - ASP.NET Core
  - Document Editor
  - Format Painter
  - JavaScript
- **Web URL:** https://www.textcontrol.com/blog/2025/09/09/format-painter-in-asp-dotnet-core-building-custom-text-formatting-with-tx-text-control/
- **LLMs URL:** https://www.textcontrol.com/blog/2025/09/09/format-painter-in-asp-dotnet-core-building-custom-text-formatting-with-tx-text-control/llms.txt
- **LLMs-Full URL:** https://www.textcontrol.com/blog/2025/09/09/format-painter-in-asp-dotnet-core-building-custom-text-formatting-with-tx-text-control/llms-full.txt
- **GitHub Repository:** https://github.com/TextControl/TXTextControl.Web.JS.FormatPainter

---

Anyone who has spent time in Microsoft Word knows the magic of the Format Painter: a feature that lets you copy formatting from one piece of text and apply it to another with a single click. Although Format Painter functionality exists in common web editors, developers creating custom document applications require more sophisticated formatting controls. The TX Text Control rich text editor enables developers to implement custom formatting programmatically. This article demonstrates how to build a Format Painter feature using the TX Text Control Document Editor, implementing format detection, copy and paste operations, and custom style handling through the JavaScript API.

### Understanding Uniform Formatting Detection

Building a reliable Format Painter feature starts with solving one key challenge: how do you know if the selected text has consistent formatting? When users select text with mixed fonts, colors, or styles, copying that formatting creates inconsistent results. TX Text Control's isCommonSelectionValueSelected Method solves this by checking if formatting is uniform across any selection. It returns true only when all selected text shares the same formatting attributes, preventing formatting errors before they happen.

> **Getting Started**
> 
> Learn how to create the TX Text Control rich text editor with ASP.NET Core using this guide:
> 
> [Getting Started: Document Editor with ASP.NET Core ](https://www.textcontrol.com/blog/2023/09/13/getting-started-document-editor-with-aspnet-core/llms-full.txt)

The ASP.NET Core application with TX Text Control provides rich text editing with comprehensive functionality. The JavaScript API enables further customization and integration with specialized features, such as the Format Painter. For demonstration purposes, this implementation utilizes dedicated buttons to showcase the Format Painter functionality. The complete source code for this implementation is available on the TX Text Control [GitHub](https://github.com/TextControl) repository. The project includes all the code examples, along with the complete ASP.NET Core setup and JavaScript integration.

### Implementing Asynchronous Format Detection

Since TX Text Control uses callback-based APIs for asynchronous operations, the implementation converts these to Promise wrappers for cleaner async/await syntax. The *isCommonValueSelectedAsync* function specifically handles format validation using the isCommonSelectionValueSelected Method. The implementation works as follows:

```
// Global variables 
let copiedFormat = null; 
let styleCounter = 1; 
let customStyles = {}; 

// Promise wrappers for TX Text Control API 
const get = (method) => 
    new Promise((resolve, reject) => 
        TXTextControl.selection[method](v => resolve(v), e => reject(e)) 
    ); 
 
const set = (method, val) => 
    new Promise((resolve, reject) => 
        TXTextControl.selection[method](val, () => resolve(), e => reject(e)) 
    ); 
 
const getLength = () => 
    new Promise((resolve, reject) => 
        TXTextControl.selection.getLength(v => resolve(v), e => reject(e)) 
    ); 
 
const selectWord = () => 
    new Promise((resolve, reject) => 
        TXTextControl.selectWord(() => resolve(), e => reject(e)) 
    ); 

// Utility function to check if selected text has uniform formatting 

function isCommonValueSelectedAsync(selection, attr) { 

  return new Promise((resolve, reject) => { 

    selection.isCommonSelectionValueSelected( 

      attr, 

      (result) => { 

        resolve(result); // true/false 

      }, 

      reject 

    ); 

  }); 

}
```

### Copying Formatting From Text Selection

The event handler shown below validates the text selection and captures its formatting attributes only if the text selection has uniform formatting:

```
// Main event handler - runs when TX Text Control is fully loaded 

TXTextControl.addEventListener("textControlLoaded", () => { 

  

  // Get references to all UI elements 

  const copyFormatButton = document.getElementById("copyFormatButton"); 

  const pasteFormatButton = document.getElementById("pasteFormatButton"); 

  const createStyleButton = document.getElementById("createStyleButton"); 

  const customStylesDropdown = document.getElementById("customStylesDropdown"); 

  const applyStyleButton = document.getElementById("applyStyleButton"); 

  

  // Copy formatting from selected text 

  copyFormatButton.addEventListener("click", async () => { 

    // Validate that selection has uniform formatting 

    const isUniform = await isCommonValueSelectedAsync( 

      TXTextControl.selection, 

      TXTextControl.Selection.Attribute.All 

    ); 

  

    if (isUniform) { 

      // Capture all formatting attributes from current selection 

      copiedFormat = { 

        baseline: await get("getBaseline"), 

        bold: await get("getBold"), 

        fontName: await get("getFontName"), 

        fontSize: await get("getFontSize"), 

        foreColor: await get("getForeColor"), 

        italic: await get("getItalic"), 

        strikeout: await get("getStrikeout"), 

        textBackColor: await get("getTextBackColor"), 

        underline: await get("getUnderline") 

      }; 

  

      pasteFormatButton.disabled = false; 

      console.log("Format copied successfully."); 

    } else { 

      alert("Please select text with uniform formatting to copy the format."); 

    } 

  });
```

### Applying Formatting to Text Selections

The paste handler applies the previously copied formatting to the target selection with all the captured attributes, as shown in this code:

```
// Apply previously copied formatting to current selection 

pasteFormatButton.addEventListener("click", async () => { 

  if (!copiedFormat) { 

      pasteFormatButton.disabled = true; 

      return; 

  } 

  

  try { 

    // Apply all captured formatting attributes to current selection 

    await set("setBaseline", copiedFormat.baseline); 

    await set("setBold", copiedFormat.bold); 

    await set("setFontName", copiedFormat.fontName); 

    await set("setFontSize", copiedFormat.fontSize); 

    await set("setForeColor", copiedFormat.foreColor); 

    await set("setItalic", copiedFormat.italic); 

    await set("setStrikeout", copiedFormat.strikeout); 

    await set("setTextBackColor", copiedFormat.textBackColor); 

    await set("setUnderline", copiedFormat.underline); 

  

    console.log("Format pasted successfully."); 

  } catch (err) { 

    alert("Paste failed: " + err.message); 

    console.error(err); 

  } 

});
```

![Copying and applying formatting](https://s1-www.textcontrol.com/assets/dist/blog/2025/09/09/a/assets/copy_paste.gif "Copying and applying formatting")

### Creating Custom Styles and Adding Them to TX Text Control's Style Collection

This section shows how to create reusable styles that become part of TX Text Control's style collection. Unlike the copy and paste formatting covered earlier, creating custom styles defines **inline** or **paragraph** formatting rules that can be reapplied across the document or in future editing sessions. The created custom styles are added to the Document Editor's **"Styles"** dropdown in the ribbon.

TX Text Control supports both inline and paragraph styles, which serve different formatting purposes:

- **Paragraph styles** apply formatting to entire paragraphs.
- **Inline styles** apply character-level formatting to selected text portions within paragraphs.

This implementation uses **inline styles** because the format painter feature captures character-level formatting properties. Formatting is applied to selected text portions rather than entire paragraphs. The following code shows how to create styles and add them to TX Text Control's style collection:

```
// Create a reusable style from selected text formatting 

createStyleButton.addEventListener("click", async () => { 

  try { 

    // Validate uniform formatting before creating style 

    const isUniform = await isCommonValueSelectedAsync( 

      TXTextControl.selection, 

      TXTextControl.Selection.Attribute.All 

    ); 

  

    if (!isUniform) { 

      alert("Please select text with uniform formatting to create a style."); 

      return; 

    } 

  

    // Capture current selection's formatting 

    const currentFormat = { 

      baseline: await get("getBaseline"), 

      bold: await get("getBold"), 

      fontName: await get("getFontName"), 

      fontSize: await get("getFontSize"), 

      foreColor: await get("getForeColor"), 

      italic: await get("getItalic"), 

      strikeout: await get("getStrikeout"), 

      textBackColor: await get("getTextBackColor"), 

      underline: await get("getUnderline") 

    }; 

  

    // Generate unique style name and create the style 

    const styleName = "CustomStyle" + styleCounter++; 

    // Add the created style in TX Text Control's inline styles collection 

    const addedStyle = await addStyle(styleName, currentFormat, "inline"); 

  

    if (addedStyle) { 

      // Store for dropdown usage and add to UI 

      customStyles[styleName] = { ...currentFormat }; 

      addStyleToDropdown(styleName); 

  

    } 

  

    alert(`Custom style '${styleName}' created successfully!`); 

  } catch (err) { 

    alert("Style creation failed: " + err.message); 

    console.error(err); 

  } 

});
```

**Note:** TX Text Control's *FormattingStyle.setFontSize* Method requires font sizes in twips (1/20th of a point). The *ptToTwips* helper function converts point values to twips, ensuring programmatically created styles display at the correct font size.

```
// Convert font size from points to twips (required by TX Text Control) 

function ptToTwips(pt) { 

  return pt * 20; 

} 

  

// Function to create a new inline style in TX Text Control's style collection 

function addStyle(styleName, format) { 

    return new Promise((resolve, reject) => { 

        TXTextControl.inlineStyles.add( 

            styleName, 

            (style) => { 

                // Apply formatting values to the new style 

                style.setFontName(format.fontName); 

                style.setFontSize(ptToTwips(format.fontSize)); // Convert to twips 

                style.setForeColor(format.foreColor); 

                style.setBold(format.bold); 

                style.setItalic(format.italic); 

                style.setUnderline(format.underline); 

                style.setStrikeout(format.strikeout); 

                style.setBaseline(format.baseline); 

                style.setTextBackColor(format.textBackColor); 

                resolve(style); 

            }, 

            (error) => reject(error) 

        ); 

    }); 

}
```

![Creating custom styles](https://s1-www.textcontrol.com/assets/dist/blog/2025/09/09/a/assets/custom_style.gif "Creating custom styles")

![TX Text Control Style Collection](https://s1-www.textcontrol.com/assets/dist/blog/2025/09/09/a/assets/tx_styles.webp "TX Text Control Style Collection")

### Conclusion

This article demonstrates how to build a professional Format Painter feature for ASP.NET applications using TX Text Control's JavaScript API. The implementation uses the **isCommonSelectionValueSelected** Method to ensure uniform formatting detection. It also includes complete functionality for copying and pasting formats, creating custom styles, and adding them to the TX Text Control style collection using **inline styles**. This approach provides developers with a practical foundation for implementing sophisticated text formatting in web-based applications.

---

## About Deepika Kathiravan

Deepika Kathiravan is a developer marketing professional, currently Developer Experience Marketing Lead at Text Control. Before moving into marketing, she had almost eight years of experience in various software industry roles. Following her passion for digital media, Deepika relocated to Germany and earned a Master's in Digital Media from the University of Bremen. She now enjoys blending her technical and marketing expertise by creating developer-centered content and driving strategic growth for the brand.

- [LinkedIn](https://www.linkedin.com/in/deepikakathiravan/)

---

## Related Posts

- [Build a Custom Backstage View in ASP.NET Core with TX Text Control](https://www.textcontrol.com/blog/2026/02/17/build-a-custom-backstage-view-in-aspnet-core-with-tx-text-control/llms.txt)
- [Observe When the Reporting Preview Tab is Active Using MutationObserver](https://www.textcontrol.com/blog/2024/07/23/observe-when-the-reporting-preview-tab-is-active-using-mutationobserver/llms.txt)
- [Building an ASP.NET Core Backend Application to Host the Document Editor and Document Viewer](https://www.textcontrol.com/blog/2024/03/14/building-an-asp-net-core-backend-application-to-host-the-document-editor-and-document-viewer/llms.txt)
- [Getting Started: Document Editor with JavaScript](https://www.textcontrol.com/blog/2023/09/15/getting-started-document-editor-with-javascript/llms.txt)
- [5 Layout Patterns for Integrating the TX Text Control Document Editor in ASP.NET Core C#](https://www.textcontrol.com/blog/2026/04/09/5-layout-patterns-for-integrating-the-tx-text-control-document-editor-in-aspnet-core-csharp/llms.txt)
- [Introducing Text Control Agent Skills](https://www.textcontrol.com/blog/2026/03/27/introducing-text-control-agent-skills/llms.txt)
- [Deploying the TX Text Control Document Editor from the Private NuGet Feed to Azure App Services (Linux and Windows)](https://www.textcontrol.com/blog/2026/03/25/deploying-the-tx-text-control-document-editor-from-the-private-nuget-feed-to-azure-app-services-linux-and-windows/llms.txt)
- [ASP.NET Core Document Editor with Backend via the Text Control Private NuGet Feed](https://www.textcontrol.com/blog/2026/02/09/aspnet-core-document-editor-private-nuget-feed/llms.txt)
- [5 Document Workflows You Can Automate With JavaScript Rich Text Editor](https://www.textcontrol.com/blog/2026/01/14/five-document-workflows-you-can-automate-with-javascript-rich-text-editor/llms.txt)
- [Why Document Processing Libraries Require a Document Editor](https://www.textcontrol.com/blog/2025/12/04/why-document-processing-libraries-require-a-document-editor/llms.txt)
- [Getting Started Video Tutorial: Document Editor in ASP.NET Core C# on Linux](https://www.textcontrol.com/blog/2025/07/29/getting-started-video-tutorial-document-editor-aspnet-core-csharp-linux/llms.txt)
- [Add JavaScript to PDFs with TX Text Control in C# .NET: Time-Based Alerts Made Easy](https://www.textcontrol.com/blog/2025/06/13/add-javascript-to-pdfs-with-tx-text-control-in-c-dot-net-time-based-alerts-made-easy/llms.txt)
- [Deploying the TX Text Control Document Editor in an ASP.NET Core Web App to Azure App Services](https://www.textcontrol.com/blog/2025/03/26/deploying-the-tx-text-control-document-editor-in-an-asp-net-core-web-app-to-azure-app-services/llms.txt)
- [Building an ASP.NET Core Backend (Linux and Windows) for the Document Editor and Viewer](https://www.textcontrol.com/blog/2025/03/26/building-an-asp-net-core-backend-for-the-document-editor-and-viewer/llms.txt)
- [TX Text Control for Blazor: Mail Merge Integration Tutorial](https://www.textcontrol.com/blog/2025/03/25/tx-text-control-for-blazor-mail-merge-integration-tutorial/llms.txt)
- [TX Text Control Document Editor and Viewer for Blazor Released](https://www.textcontrol.com/blog/2025/03/25/tx-text-control-document-editor-and-viewer-for-blazor-released/llms.txt)
- [Getting Started: Document Editor for Blazor in ASP.NET Core](https://www.textcontrol.com/blog/2025/03/25/getting-started-document-editor-for-blazor-in-asp-net-core/llms.txt)
- [Getting Started: Document Editor Version 33.0 with Angular CLI 19.0](https://www.textcontrol.com/blog/2025/03/18/getting-started-document-editor-version-33-0-with-angular-cli-19-0/llms.txt)
- [Introducing TXTextControl.Web.Server.Core: A Cross-Platform Backend for TX Text Control Document Editor](https://www.textcontrol.com/blog/2025/03/13/introducing-txtextcontrol-web-server-core-a-cross-platform-backend-for-tx-text-control-document-editor/llms.txt)
- [Getting Started: Document Editor with ASP.NET Core and Docker Support with Linux Containers](https://www.textcontrol.com/blog/2025/03/12/getting-started-document-editor-with-asp-net-core-and-docker-support-with-linux-containers/llms.txt)
- [Getting Started: Document Editor with ASP.NET Core and Linux WSL Support](https://www.textcontrol.com/blog/2025/03/12/getting-started-document-editor-with-asp-net-core-and-linux-wsl-support/llms.txt)
- [Changing the Language in the Angular Document Editor Using the Resource Kit](https://www.textcontrol.com/blog/2025/03/05/changing-the-language-in-the-angular-document-editor-using-the-resource-kit/llms.txt)
- [Announcing Our Work on a Blazor Component for Document Editing and Viewing](https://www.textcontrol.com/blog/2025/01/24/announcing-our-work-on-a-blazor-component-for-document-editing-and-viewing/llms.txt)
- [Preparing Documents for E-Signing for Multiple Signers in .NET C#](https://www.textcontrol.com/blog/2024/11/13/preparing-documents-for-e-signing-for-multiple-signers-in-net-c-sharp/llms.txt)
- [ASP.NET Core: Use the Document Editor and Viewer in the Same Razor View](https://www.textcontrol.com/blog/2024/11/08/asp-net-core-use-the-document-editor-and-viewer-in-the-same-razor-view/llms.txt)
