Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 102 additions & 0 deletions .github/workflows/build-code-snippets.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
name: Build WinForms Solutions

on:
push:
paths:
- '**/*.md'
- 'snippets/**'
pull_request:
paths:
- '**/*.md'
- 'snippets/**'
workflow_dispatch:

jobs:
build:
runs-on: windows-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Detect snippet or folder changes
id: snippet_check
shell: pwsh
run: |
git fetch --no-tags --prune --depth=0 origin
# Determine comparison base (works for push + PR)
if ("${{ github.event_name }}" -eq "pull_request") {
$base = "${{ github.event.pull_request.base.sha }}"
} else {
$base = "${{ github.event.before }}"
}
Write-Host "Comparing against $base"
$changedFiles = git diff --name-only $base HEAD
if (-not $changedFiles) {
echo "should_build=false" >> $env:GITHUB_OUTPUT
exit 0
}
$shouldBuild = $false
foreach ($file in $changedFiles) {
Write-Host "Changed: $file"
# CONDITION 1:
# Any change inside /snippets folder
if ($file -like "snippets/*") {
Write-Host "Change inside snippets folder detected."
$shouldBuild = $true
break
}
# CONDITION 2:
# .md file with snippet tag added/modified
if ($file -like "*.md") {
$diff = git diff $base HEAD -- $file
if ($diff -match "<snippet") {
Write-Host "Snippet tag change detected in markdown."
$shouldBuild = $true
break
}
}
}
echo "should_build=$shouldBuild" >> $env:GITHUB_OUTPUT
- name: Setup .NET 10
if: steps.snippet_check.outputs.should_build == 'true'
uses: actions/setup-dotnet@v4
with:
dotnet-version: '10.0.x'

- name: Add Telerik NuGet source
if: steps.snippet_check.outputs.should_build == 'true'
shell: pwsh
run: |
dotnet nuget add source "https://nuget.telerik.com/v3/index.json" --name "Telerik NuGet Server" --username "api-key" --password $env:TELERIK_API_KEY --store-password-in-clear-text
env:
TELERIK_API_KEY: ${{ secrets.TELERIK_API_KEY }}

- name: Debug Telerik NuGet
if: steps.snippet_check.outputs.should_build == 'true'
shell: pwsh
run: |
Write-Host "TELERIK_API_KEY length: $($env:TELERIK_API_KEY.Length)"
dotnet nuget list source
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This step logs information about the Telerik API key (its length) and enumerates NuGet sources. Even though the key value is masked, this is unnecessary secret-adjacent logging for CI; consider removing this debug output (or gating it behind an explicit debug flag).

Suggested change
- name: Debug Telerik NuGet
if: steps.snippet_check.outputs.should_build == 'true'
shell: pwsh
run: |
Write-Host "TELERIK_API_KEY length: $($env:TELERIK_API_KEY.Length)"
dotnet nuget list source

Copilot uses AI. Check for mistakes.
- name: Restore & Build all solutions
if: steps.snippet_check.outputs.should_build == 'true'
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On pull_request events from forks, TELERIK_API_KEY will be unavailable, and dotnet nuget add source ... --password $env:TELERIK_API_KEY will fail, causing the workflow to fail even though the change may be valid. Consider guarding this step (and subsequent restore/build) so it only runs when the secret is present, or provide a fallback behavior for fork PRs.

Suggested change
- name: Add Telerik NuGet source
if: steps.snippet_check.outputs.should_build == 'true'
shell: pwsh
run: |
dotnet nuget add source "https://nuget.telerik.com/v3/index.json" --name "Telerik NuGet Server" --username "api-key" --password $env:TELERIK_API_KEY --store-password-in-clear-text
env:
TELERIK_API_KEY: ${{ secrets.TELERIK_API_KEY }}
- name: Debug Telerik NuGet
if: steps.snippet_check.outputs.should_build == 'true'
shell: pwsh
run: |
Write-Host "TELERIK_API_KEY length: $($env:TELERIK_API_KEY.Length)"
dotnet nuget list source
- name: Restore & Build all solutions
if: steps.snippet_check.outputs.should_build == 'true'
- name: Check Telerik API key availability
if: steps.snippet_check.outputs.should_build == 'true'
id: telerik_key_check
shell: pwsh
run: |
if ([string]::IsNullOrWhiteSpace($env:TELERIK_API_KEY)) {
echo "has_telerik_key=false" >> $env:GITHUB_OUTPUT
} else {
echo "has_telerik_key=true" >> $env:GITHUB_OUTPUT
}
env:
TELERIK_API_KEY: ${{ secrets.TELERIK_API_KEY }}
- name: Add Telerik NuGet source
if: steps.snippet_check.outputs.should_build == 'true' && steps.telerik_key_check.outputs.has_telerik_key == 'true'
shell: pwsh
run: |
dotnet nuget add source "https://nuget.telerik.com/v3/index.json" --name "Telerik NuGet Server" --username "api-key" --password $env:TELERIK_API_KEY --store-password-in-clear-text
env:
TELERIK_API_KEY: ${{ secrets.TELERIK_API_KEY }}
- name: Debug Telerik NuGet
if: steps.snippet_check.outputs.should_build == 'true' && steps.telerik_key_check.outputs.has_telerik_key == 'true'
shell: pwsh
run: |
Write-Host "TELERIK_API_KEY length: $($env:TELERIK_API_KEY.Length)"
dotnet nuget list source
env:
TELERIK_API_KEY: ${{ secrets.TELERIK_API_KEY }}
- name: Skip Telerik-dependent build when API key is unavailable
if: steps.snippet_check.outputs.should_build == 'true' && steps.telerik_key_check.outputs.has_telerik_key != 'true'
shell: pwsh
run: |
Write-Host "Snippet changes detected, but TELERIK_API_KEY is unavailable for this workflow run."
Write-Host "Skipping Telerik NuGet setup and solution restore/build (for example, this is expected on pull_request events from forks)."
- name: Restore & Build all solutions
if: steps.snippet_check.outputs.should_build == 'true' && steps.telerik_key_check.outputs.has_telerik_key == 'true'

Copilot uses AI. Check for mistakes.
shell: pwsh
run: |
# Find both .sln and .slnx files
$solutions = Get-ChildItem "./snippets" -Recurse -Include *.sln,*.slnx -File
if (-not $solutions) {
Write-Error "No solution files (.sln or .slnx) found!"
exit 1
}
foreach ($sln in $solutions) {
Write-Host ""
Write-Host "=============================="
Write-Host "Building $($sln.FullName)"
Write-Host "=============================="
dotnet restore "$($sln.FullName)"
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
dotnet build "$($sln.FullName)" `
--configuration Release `
--no-restore
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
}
8 changes: 7 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,10 @@ SlugLog.log
start-docs.sh
start-docs.sh
watch.sh
watch.sh
watch.sh
.suo
.baml
**/bin/
**/obj/
**/.vs/
**.csproj.user
13 changes: 2 additions & 11 deletions controls/aiprompt/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,8 @@ Follow the steps:
You can create a new __AIPromptOutputItem__ instance and fill it with returned response from the AI model. Then, you can populate the __OutputItems__ collection of RadAIPrompt. This will create a new AIPromptOutputVisualItem in the Output view where you can interact with the response.

````C#
private void RadAIPrompt1_PromptRequest(object sender, Telerik.WinControls.UI.AIPrompt.PromptRequestEventArgs e)
{
AIPromptOutputItem responseAIPromptOutputItemModel = new AIPromptOutputItem()
{
Title = "Response from your AI model",
InputText = e.InputText,
ResponseText = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", // Here you can set the string value returned from your AI model
};

this.radAIPrompt1.OutputItems.Add(responseAIPromptOutputItemModel);
}

<snippet id='aiprompt-getting-started-promptrequest' />

````
````VB.NET
Expand Down
1 change: 1 addition & 0 deletions docs-builder.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ img-max-width: 100%
center-images: false
table-layout: fixed
enable-tabbed-code-blocks: true
external-snippets-path: ./snippets
pdf-cover-png-path: ./images/pdf-cover.png
gitLastCommitDateEnabled: true
search-provider: nuclia
Expand Down
15 changes: 15 additions & 0 deletions snippets/Telerik.WinControls.UI.Snippets/Common/Common.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net10.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<UseWindowsForms>true</UseWindowsForms>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="UI.for.WinForms.Common" Version="2026.1.210" />
</ItemGroup>

</Project>
59 changes: 59 additions & 0 deletions snippets/Telerik.WinControls.UI.Snippets/Common/Form1.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 26 additions & 0 deletions snippets/Telerik.WinControls.UI.Snippets/Common/Form1.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using Telerik.WinControls.UI.AIPrompt;

namespace Common
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

// >> aiprompt-getting-started-promptrequest
private void RadAIPrompt1_PromptRequest(object sender, Telerik.WinControls.UI.AIPrompt.PromptRequestEventArgs e)
{
AIPromptOutputItem responseAIPromptOutputItemModel = new AIPromptOutputItem()
{
Title = "Response from your AI model",
InputText = e.InputText,
ResponseText = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", // Here you can set the string value returned from your AI model
};

this.radaiPrompt1.OutputItems.Add(responseAIPromptOutputItemModel);
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This snippet currently references this.radaiPrompt1, which will flow into the docs snippet output. If the intended instance name is radAIPrompt1 (as used elsewhere in the docs), rename the control field and update this reference so the extracted snippet matches the documented naming.

Suggested change
this.radaiPrompt1.OutputItems.Add(responseAIPromptOutputItemModel);
this.radAIPrompt1.OutputItems.Add(responseAIPromptOutputItemModel);

Copilot uses AI. Check for mistakes.
}
// << aiprompt-getting-started-promptrequest
}
}
120 changes: 120 additions & 0 deletions snippets/Telerik.WinControls.UI.Snippets/Common/Form1.resx
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema

Version 2.0

The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.

Example:

... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>

There are any number of "resheader" rows that contain simple
name/value pairs.

Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.

The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:

Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.

mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.

mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.

mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
17 changes: 17 additions & 0 deletions snippets/Telerik.WinControls.UI.Snippets/Common/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
namespace Common
{
internal static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
// To customize application configuration such as set high DPI settings or default font,
// see https://aka.ms/applicationconfiguration.
ApplicationConfiguration.Initialize();
Application.Run(new Form1());
}
}
}
8 changes: 8 additions & 0 deletions snippets/Telerik.WinControls.UI.Snippets/NuGet.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="Telerik NuGet Server" value="https://nuget.telerik.com/v3/index.json" />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
<add key="Microsoft Visual Studio Offline Packages" value="C:\Program Files (x86)\Microsoft SDKs\NuGetPackages\" />
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 'Microsoft Visual Studio Offline Packages' source is a machine-local Windows path that won't exist for many developers/CI environments and can introduce restore warnings/failures. Consider removing this source from the repo NuGet.config (or generating it locally instead of committing it).

Suggested change
<add key="Microsoft Visual Studio Offline Packages" value="C:\Program Files (x86)\Microsoft SDKs\NuGetPackages\" />

Copilot uses AI. Check for mistakes.
</packageSources>
</configuration>
Loading
Loading