windowsforms-405152-ai-powered-extensions-smart-paste.md
SmartPaste is an AI-powered feature that transforms the traditional copy-and-paste process into a smarter, more efficient tool. Designed to improve productivity, SmartPaste analyzes the content you copy and intelligently assigns the correct values to the appropriate fields or row cells in the DevExpress Data Grid and LayoutControl-driven forms.
DevExpress UI controls seamlessly integrate SmartPaste. When SmartPaste is activated, the “Smart Paste” command is automatically added to a control’s popup menu.
When you copy data from a source (such as a spreadsheet, document, web page, or image) and paste it into a data grid, scheduler, or LayoutControl-driven form, SmartPaste automatically interprets the content and maps the data to the correct data fields or cells. In addition to text-based content, Smart Paste can analyze images copied to the clipboard.
Play the following animation to see a demonstration:
Tip
You can also specify a shortcut key to invoke SmartPaste.
See the following section in this help topic for an example: Invoke SmartPaste Using a Shortcut.
DevExpress.AIIntegration.WinFormsDevExpress.Win.Design (enables design-time features for DevExpress UI controls)See the following help topics for information on how to obtain the DevExpress NuGet Feed and install DevExpress NuGet packages:
See the following help topic for information on required NuGet packages and system requirements: Register an AI Client.
The following code snippet registers the Azure OpenAI client:
using Microsoft.Extensions.AI;
using DevExpress.AIIntegration;
internal static class Program {
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
IChatClient azureChatClient = new Azure.AI.OpenAI.AzureOpenAIClient(new Uri(AzureOpenAIEndpoint),
new System.ClientModel.ApiKeyCredential(AzureOpenAIKey))
.GetChatClient(ModelId).AsIChatClient();
AIExtensionsContainerDesktop.Default.RegisterChatClient(azureChatClient);
// Uncomment the following line if your project targets the .NET Framework and
// you create AI-powered behaviors in code.
// DevExpress.AIIntegration.WinForms.BehaviorInitializer.Initialize();
Application.Run(new Form1());
}
static string AzureOpenAIEndpoint { get { return Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT"); } }
static string AzureOpenAIKey { get { return Environment.GetEnvironmentVariable("AZURE_OPENAI_APIKEY"); } }
static string ModelId { get { return "MODEL_NAME"; } }
}
Imports Microsoft.Extensions.AI
Imports DevExpress.AIIntegration
Friend Module Program
<STAThread>
Sub Main()
Application.EnableVisualStyles()
Application.SetCompatibleTextRenderingDefault(False)
' Register Azure.OpenAI
Dim azureChatClient As IChatClient = New Azure.AI.OpenAI.AzureOpenAIClient(New Uri(AzureOpenAIEndpoint),
New System.ClientModel.ApiKeyCredential(AzureOpenAIKey)).
GetChatClient(ModelId).AsIChatClient()
AIExtensionsContainerDesktop.Default.RegisterChatClient(azureChatClient)
' Uncomment the following line if your project targets the .NET Framework and
' you create AI-powered behaviors in code.
' DevExpress.AIIntegration.WinForms.BehaviorInitializer.Initialize()
Application.Run(New Form1())
End Sub
Private ReadOnly Property AzureOpenAIEndpoint() As String
Get
Return Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT")
End Get
End Property
Private ReadOnly Property AzureOpenAIKey() As String
Get
Return Environment.GetEnvironmentVariable("AZURE_OPENAI_APIKEY")
End Get
End Property
Private ReadOnly Property ModelId As String
Get
Return "MODEL_NAME"
End Get
End Property
End Module
Drop the BehaviorManager component from the Toolbox onto a Form.
For GridControl, LayoutControl, or DataLayoutControl, add a SmartPasteBehavior, configure its settings, and attach the behavior to a control. You can do this at design time or in code:
For SchedulerControl, add a SmartPasteSchedulerBehavior, configure its settings, and attach the behavior to the control.
Note
Call the BehaviorInitializer.Initialize() method at application startup if your project targets the .NET Framework and you create AI-powered behaviors in code. Otherwise, an exception is thrown.
internal static class Program {
[STAThread]
static void Main() {
//...
// The Initialize() method forcibly initializes the behavior manager in .NET Framework apps.
DevExpress.AIIntegration.WinForms.BehaviorInitializer.Initialize();
Application.Run(new Form1());
}
}
The animation below shows how SmartPaste works in the DevExpress Grid Control:
Tip
Use SmartPasteRequest to manually initiate a Smart Paste request:
string rawData = "your text-based content";
var response = await defaultAIExtensionsContainer.SmartPasteAsync(
new SmartPasteRequest(rawData, new List<SmartPasteRequest.ItemInfo>() {
new SmartPasteRequest.ItemInfo("product", "Product Name"),
new SmartPasteRequest.ItemInfo("weight", "Weight")
})
);
Smart Paste from Image :
string filePath = @"C:\Media\example.png";
byte[] dataContent = File.ReadAllBytes(filePath);
var response = await defaultAIExtensionsContainer.SmartPasteAsync(
new SmartPasteRequest(string.Empty, new List<SmartPasteRequest.ItemInfo>() {
new SmartPasteRequest.ItemInfo("product", "Product Name"),
new SmartPasteRequest.ItemInfo("price", "Price")
}, dataContent, "image/png")
);
Once you attach the SmartPasteBehavior to a control, you should describe items so that SmartPaste can assign the correct values to appropriate items. In the context of SmartPaste, an item refers to a LayoutControlItem when working with a LayoutControl, or a GridColumn when working with a GridControl.
Note
Item descriptions are optional if an item’s text or caption is specified (for example, a grid column’s Caption property or layout item’s Text property is set to a non-empty string). Although SmartPaste attempts to determine the correct value for an item based on the item’s text/caption, we recommend that you also describe items for improved accuracy.
Use the SmartPasteBehavior.Properties.ItemDescriptions collection property to add descriptions (AIItemDescription) for certain items. Each AIItemDescription object in the collection has two properties:
AIItemDescription.Item: A component that will receive the pasted data (GridColumn or LayoutControlItem).AIItemDescription.Description: A string that describes the expected content and/or data format for the item.If you want to exclude a specific item from SmartPaste, you can add this item to the ExcludedItems collection. You can exclude grid columns or data fields from being affected by SmartPaste, ensuring that they remain unchanged.
Enable the ProcessClipboardImage option to analyze images copied to the clipboard. SmartPaste checks whether the clipboard contains an image and attempts to extract structured data from it using AI.
You can specify additional instructions that modify the default prompt before processing. Prompt augmentation improves the relevance and accuracy of the AI’s response. Use the PromptAugmentation property to specify additional instructions.
The following code snippet registers a SmartPasteBehavior and assigns it to an AdvBandedGridView. It uses the AI-powered SmartPaste extension to analyze clipboard content (text or image data) and automatically fill grid columns with structured data. The extension is configured to always return results in English.
public Form1() {
InitializeComponent();
behaviorManager1.Attach<SmartPasteBehavior>(advBandedGridView1, behavior => {
behavior.Properties.PromptAugmentation = "Always translate the result into English.";
behavior.Properties.ItemDescriptions.AddRange(new List<AIItemDescription>() {
new AIItemDescription(advBandedGridView1.Columns["ProductName"], "Official name or product name."),
new AIItemDescription(advBandedGridView1.Columns["ShippingWeight"], "Weight of the product when packaged for shipping (in lbs or kg)."),
new AIItemDescription(advBandedGridView1.Columns["ProductDimensions"], "Physical size of TV without stand, typically in length, width, and height (in inches or mm)."),
new AIItemDescription(advBandedGridView1.Columns["ShippingDimensions"], "Physical size of shipping package, typically in length, width, and height (in inches or mm)."),
new AIItemDescription(advBandedGridView1.Columns["Warranty"], "Information related to the product warranty (in years or months)."),
}
);
behavior.Properties.ExcludedItems.Add(advBandedGridView1.Columns["Notes"]);
behavior.Properties.ProcessClipboardImage = DevExpress.Utils.DefaultBoolean.True;
});
}
Public Sub New()
InitializeComponent()
behaviorManager1.Attach(Of SmartPasteBehavior)(advBandedGridView1, Sub(behavior)
behavior.Properties.PromptAugmentation = "Always translate the result into English."
behavior.Properties.ItemDescriptions.AddRange(New List(Of AIItemDescription)() From {
New AIItemDescription(advBandedGridView1.Columns("ProductName"), "Official name or product name."),
New AIItemDescription(advBandedGridView1.Columns("ShippingWeight"), "Weight of the product when packaged for shipping (in lbs or kg)."),
New AIItemDescription(advBandedGridView1.Columns("ProductDimensions"), "Physical size of TV without stand, typically in length, width, and height (in inches or mm)."),
New AIItemDescription(advBandedGridView1.Columns("ShippingDimensions"), "Physical size of shipping package, typically in length, width, and height (in inches or mm)."),
New AIItemDescription(advBandedGridView1.Columns("Warranty"), "Information related to the product warranty (in years or months).")
})
behavior.Properties.ExcludedItems.Add(advBandedGridView1.Columns("Notes"))
behavior.Properties.ProcessClipboardImage = DevExpress.Utils.DefaultBoolean.True
End Sub)
End Sub
The following code snippet handles the GridView’s KeyDown event to invoke SmartPaste when a user presses Alt+P:
async void AdvBandedGridView1_KeyDown(object sender, KeyEventArgs e) {
if (e.KeyCode == Keys.P && e.Modifiers == Keys.Alt)
await behaviorManager1.GetBehavior<SmartPasteBehavior>(gridView1).SmartPasteAsync();
}
Async Sub AdvBandedGridView1_KeyDown(ByVal sender As Object, ByVal e As KeyEventArgs)
If e.KeyCode = Keys.P AndAlso e.Modifiers = Keys.Alt Then
Await behaviorManager1.GetBehavior(Of SmartPasteBehavior)(gridView1).SmartPasteAsync()
End If
End Sub
When pasting into data fields of basic data types (such as Boolean, date-time, numeric, string), SmartPaste automatically appends default formatting prompts to item descriptions. You can also specify custom formatting prompts as needed.
For example, if your data source designates Boolean values as 1 and -1, you can specify the following item description: “If 1 use True. If -1 use False.”
behaviorManager1.Attach<SmartPasteBehavior>(layoutControl1, behavior => {
behavior.Properties.ItemDescriptions.AddRange(new List<AIItemDescription>() {
new AIItemDescription(itemInStock, "If 1 use True. If -1 use False.")
}
);
});
behaviorManager1.Attach(Of SmartPasteBehavior)(layoutControl1, Sub(behavior)
behavior.Properties.ItemDescriptions.AddRange(New List(Of AIItemDescription)() From {New AIItemDescription(itemInStock, "If 1 use True. If -1 use False.")})
End Sub)
You can validate a SmartPaste result to ensure that the data adheres to predefined rules or formats required by your application. Use built-in APIs of DevExpress controls to analyze, and if necessary, modify the data returned by SmartPaste.
For data editors, handle the EditValueChanging event to analyze and modify SmartPaste results. This event is triggered whenever the EditValue property of a control is about to change and allows you to modify the value before it is finalized.
The following example handles the Lookup’s EditValueChanging event to specify the EditValue based on the value (display text) returned by SmartPaste:
public Formatting() {
InitializeComponent();
InitLookup();
SmartPasteLayoutBehaviorSource.Register();
behaviorManager1.Attach<SmartPasteBehavior>(layoutControl1, behavior => {
behavior.Properties.ItemDescriptions.AddRange(new List<AIItemDescription>() {
new AIItemDescription(itemSeller, "The name of the individual or company selling the product.")
}
);
});
}
void LookUpEdit1_EditValueChanging(object sender, ChangingEventArgs e) {
List<DataItemSeller> list = (sender as LookUpEdit).Properties.DataSource as List<DataItemSeller>;
var item = list.Find(item => item.Seller == e.NewValue.ToString());
if (item != null)
e.NewValue = item.ID;
else
e.Cancel = true;
}
void InitLookup() {
lookUpEdit1.Properties.DataSource = new List<DataItemSeller>() {
new DataItemSeller(){ Seller = "Seller A", Rating = 4.6 },
new DataItemSeller(){ Seller = "Seller B", Rating = 4.7 },
new DataItemSeller(){ Seller = "Seller C", Rating = 4.8 },
};
lookUpEdit1.Properties.DisplayMember = "Seller";
lookUpEdit1.Properties.ValueMember = "ID";
lookUpEdit1.EditValueChanging += LookUpEdit1_EditValueChanging;
}
public class DataItemSeller {
Guid id;
public DataItemSeller(){
id = Guid.NewGuid();
}
public Guid ID { get { return id; } }
public string Seller { get; set; }
public double Rating { get; set; }
}
Public Sub New()
InitializeComponent()
InitLookup()
SmartPasteLayoutBehaviorSource.Register()
behaviorManager1.Attach(Of SmartPasteBehavior)(layoutControl1, Sub(behavior)
behavior.Properties.ItemDescriptions.AddRange(New List(Of AIItemDescription)() From {New AIItemDescription(itemSeller, "The name of the individual or company selling the product.")})
End Sub)
End Sub
Private Sub LookUpEdit1_EditValueChanging(ByVal sender As Object, ByVal e As ChangingEventArgs)
Dim list As List(Of DataItemSeller) = TryCast((TryCast(sender, LookUpEdit)).Properties.DataSource, List(Of DataItemSeller))
Dim item = list.Find(Function(item) item.Seller = e.NewValue.ToString())
If item IsNot Nothing Then
e.NewValue = item.ID
Else
e.Cancel = True
End If
End Sub
Private Sub InitLookup()
lookUpEdit1.Properties.DataSource = New List(Of DataItemSeller)() From {
New DataItemSeller() With {
.Seller = "Seller A",
.Rating = 4.6
},
New DataItemSeller() With {
.Seller = "Seller B",
.Rating = 4.7
},
New DataItemSeller() With {
.Seller = "Seller C",
.Rating = 4.8
}
}
lookUpEdit1.Properties.DisplayMember = "Seller"
lookUpEdit1.Properties.ValueMember = "ID"
AddHandler lookUpEdit1.EditValueChanging, AddressOf LookUpEdit1_EditValueChanging
End Sub
Public Class DataItemSeller
Private id_Renamed As Guid
Public Sub New()
id_Renamed = Guid.NewGuid()
End Sub
Public ReadOnly Property ID() As Guid
Get
Return id_Renamed
End Get
End Property
Public Property Seller() As String
Public Property Rating() As Double
End Class
See the following help topic for additional information and examples on how to validate changes in the Data Grid control: Validate User Input in Data Grid.
GridView, BandedGridView, and AdvBandedGridView, a user can right-click a data row or new item row and invoke a popup menu with the “Smart Paste” command.Grid column requirements include:
Values are pasted into grid cells as strings. The grid automatically converts string values to appropriate data types, which include:
int, uint, short, ushort, float, double, decimal, etc.DateTime, DateOnly, TimeOnly.Layout items support SmartPaste if they meet the following requirements:
The following data editors automatically convert SmartPaste results before they are assigned to the EditValue property:
For editors that do not support built-in conversion, handle the EditValueChanging event to manually convert string values as needed.
SmartPaste allows you to create appointments in the WinForms Scheduler by pasting text content directly from the clipboard. SmartPaste recognizes common appointment-specific data (subject, dates, times, location, agenda) and fills corresponding fields in the Scheduler’s appointment editor.
SmartPaste can detect and configure the following settings:
See Also