Skip to content

Commit 154e55a

Browse files
Merge pull request #2 from SyncfusionExamples/MAUI-978225-ReadMeFile
MAUI-978225 - [Others] Updated README file
2 parents 61bbf1d + 51438c0 commit 154e55a

1 file changed

Lines changed: 220 additions & 2 deletions

File tree

README.md

Lines changed: 220 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,220 @@
1-
# Leveraging-AI-with-Syncfusion-MAUI-DataGrid-A-Step-by-Step-Guide-to-Predictive-Data-Integration.
2-
This demo shows how to leveraging AI with Syncfusion MAUI DataGrid: A Step-by-Step Guide to Predictive Data Integration
1+
# Leveraging-AI-with-Syncfusion-MAUI-DataGrid-A-Step-by-Step-Guide-to-Predictive-Data-Integration
2+
This guide explains how the sample integrates AI-powered anomaly detection into a Syncfusion .NET MAUI DataGrid (SfDataGrid). It walks through the XAML layout, the C# logic that gathers grid data, sends it to an AI service, and augments the grid with a new Anomaly Description column.
3+
4+
## xaml
5+
It defines the SfDataGrid bound to MachineDataCollection in the view model, customizes grid cell/header styles, and includes an ActivityIndicator to show progress while AI analysis runs. A tappable Frame triggers the anomaly detection workflow.
6+
7+
```
8+
<ContentPage.BindingContext>
9+
<ViewModel:MachineDataRepository x:Name="viewModel"/>
10+
</ContentPage.BindingContext>
11+
<ContentPage.Resources>
12+
<local:ColorConverter x:Key="converter"/>
13+
<Style TargetType="syncfusion:DataGridCell">
14+
<Setter Property="Background" Value="{Binding Source={RelativeSource Mode=Self}, Converter={StaticResource Key=converter}}"/>
15+
<Setter Property="FontSize"
16+
Value="14" />
17+
</Style>
18+
<Style TargetType="syncfusion:DataGridHeaderCell">
19+
<Setter Property="FontFamily"
20+
Value="Roboto-Medium" />
21+
<Setter Property="FontSize"
22+
Value="14" />
23+
</Style>
24+
25+
</ContentPage.Resources>
26+
<Grid>
27+
<Grid.RowDefinitions>
28+
<RowDefinition Height="56" />
29+
<RowDefinition Height="*" />
30+
</Grid.RowDefinitions>
31+
32+
<HorizontalStackLayout HeightRequest="65"
33+
Margin="10">
34+
35+
<Frame HeightRequest="40"
36+
WidthRequest="137"
37+
HasShadow="False"
38+
Padding="0"
39+
Margin="5"
40+
Background="Transparent"
41+
HorizontalOptions="Center"
42+
VerticalOptions="Center"
43+
BorderColor="Gray"
44+
CornerRadius="20">
45+
<Frame.GestureRecognizers>
46+
<TapGestureRecognizer NumberOfTapsRequired="1"
47+
Tapped="Button_Clicked" />
48+
</Frame.GestureRecognizers>
49+
<Grid x:Name="myGrid"
50+
ColumnDefinitions="150"
51+
RowDefinitions="40">
52+
53+
<Label Grid.Column="0"
54+
Text="Detect anomoly data"
55+
FontSize="13"
56+
HeightRequest="20"
57+
WidthRequest="800"
58+
Padding="3"
59+
HorizontalTextAlignment="Start"
60+
VerticalTextAlignment="Center" />
61+
</Grid>
62+
63+
</Frame>
64+
65+
66+
</HorizontalStackLayout>
67+
68+
<!--<Button Clicked="Button_Clicked" Margin="5" Text="Detect Anomoly Data" Height="25" Width="100" HorizontalOptions="Start"/>-->
69+
70+
<syncfusion:SfDataGrid x:Name="dataGrid"
71+
Grid.Row="1"
72+
HeaderRowHeight="52"
73+
HorizontalScrollBarVisibility="Always"
74+
VerticalScrollBarVisibility="Always"
75+
Margin="5"
76+
ColumnWidthMode="Fill"
77+
AutoGenerateColumnsMode="None"
78+
ItemsSource="{Binding MachineDataCollection}">
79+
<syncfusion:SfDataGrid.Columns>
80+
<syncfusion:DataGridTextColumn HeaderText="Machine ID" MinimumWidth="120" MappingName="MachineID" />
81+
<syncfusion:DataGridTextColumn HeaderText="Temperature" MinimumWidth="120" MappingName="Temperature" />
82+
<syncfusion:DataGridTextColumn HeaderText="Pressure" MinimumWidth="120" MappingName="Pressure" />
83+
<syncfusion:DataGridTextColumn HeaderText="Voltage" MinimumWidth="120" MappingName="Voltage" />
84+
<syncfusion:DataGridTextColumn HeaderText="Motor Speed" MinimumWidth="120" MappingName="MotorSpeed" />
85+
<syncfusion:DataGridTextColumn HeaderText="Production Rate" MinimumWidth="140" MappingName="ProductionRate" />
86+
87+
</syncfusion:SfDataGrid.Columns>
88+
</syncfusion:SfDataGrid>
89+
<ActivityIndicator IsRunning="False"
90+
x:Name="Indicator"
91+
Grid.Row="1"
92+
93+
VerticalOptions="Center"
94+
HorizontalOptions="Center"
95+
Color="Black" />
96+
97+
</Grid>
98+
```
99+
100+
## C#
101+
The code-behind assembles a GridReport from the grid’s ItemsSource, serializes it, and builds a natural-language prompt. It then calls an Azure OpenAI deployment to get anomaly results. When results arrive, the code dynamically adds a new column (Anomaly Description) and updates the bound data rows to show the AI-generated explanation. If AI is unavailable, a fallback path computes the max values for several metrics and flags the corresponding row with a sensible default message.
102+
103+
Key parts from MainPage.xaml.cs:
104+
105+
```
106+
async private void Button_Clicked(object sender, EventArgs e)
107+
{
108+
Indicator.IsRunning = true;
109+
110+
gridReport = new GridReport()
111+
{
112+
DataSource = (this.dataGrid.BindingContext as MachineDataRepository)!.MachineDataCollection,
113+
};
114+
115+
var gridReportJson = JsonConvert.SerializeObject(gridReport);
116+
string userInput = ValidateAndGeneratePrompt(gridReportJson);
117+
var result = await openAi.GetResponseFromOpenAI(userInput);
118+
119+
if (result != null)
120+
{
121+
result = result.Replace("```json", "").Replace("```", "").Trim();
122+
var deserializeResult = JsonConvert.DeserializeObject<GridReport>(result)!;
123+
124+
// Add the anomaly column dynamically
125+
var anomalyColumn = new DataGridTextColumn
126+
{
127+
HeaderText = "Anomaly Description",
128+
MappingName = "AnomalyDescription",
129+
ColumnWidthMode = ColumnWidthMode.Auto
130+
};
131+
this.dataGrid.Columns.Add(anomalyColumn);
132+
133+
// Update the source with AI-provided text
134+
var ids = deserializeResult.DataSource.Select(x => x.MachineID).ToArray();
135+
int index = -1;
136+
foreach (var row in gridReport.DataSource)
137+
{
138+
if (ids.Contains(row.MachineID))
139+
{
140+
index++;
141+
row.AnomalyDescription = deserializeResult.DataSource[index].AnomalyDescription;
142+
}
143+
}
144+
}
145+
else
146+
{
147+
// Fallback: flag max Temperature/Voltage/MotorSpeed/Pressure
148+
// and add an AnomalyDescription column if missing
149+
var des = new DataGridTextColumn
150+
{
151+
HeaderText = "AnomalyDescription",
152+
MappingName = "AnomalyDescription",
153+
MinimumWidth = 250
154+
};
155+
this.dataGrid.Columns.Add(des);
156+
// ... set AnomalyDescription based on max values
157+
}
158+
159+
Indicator.IsRunning = false;
160+
}
161+
```
162+
163+
The page also introduces a ColorConverter that inspects the current cell context and the AnomalyDescription text to color suspicious values. Cells in columns such as Temperature, Voltage, Pressure, or MotorSpeed are highlighted when the description mentions that metric; the AnomalyDescription column itself is marked red for flagged rows.
164+
165+
```
166+
public class ColorConverter : IValueConverter
167+
{
168+
static string[] data;
169+
public void GetString(string[] Data) => data = Data;
170+
171+
object IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo info)
172+
{
173+
var gridCell = value as DataGridCell;
174+
if (gridCell != null && data != null)
175+
{
176+
var rowData = (gridCell.DataColumn!.RowData as MachineData)!.AnomalyDescription;
177+
var mappingName = gridCell.DataColumn!.DataGridColumn!.MappingName;
178+
179+
if (mappingName == "AnomalyDescription")
180+
{
181+
return rowData != null && data.Contains(rowData)
182+
? Colors.IndianRed
183+
: Colors.LightGreen;
184+
}
185+
186+
var keywords = new Dictionary<string, string>
187+
{
188+
{ "Temperature", "temperature" },
189+
{ "Voltage", "voltage" },
190+
{ "Pressure", "pressure" },
191+
{ "MotorSpeed", "motor speed" }
192+
};
193+
194+
if (keywords.TryGetValue(mappingName, out var k) && rowData.Contains(k))
195+
return Colors.IndianRed;
196+
}
197+
return Colors.White;
198+
}
199+
200+
public object ConvertBack(object value, Type t, object p, CultureInfo c) => throw new NotImplementedException();
201+
}
202+
```
203+
204+
## How the AI integration works
205+
- Serialize the grid’s data (GridReport) to JSON and craft a descriptive prompt that instructs the model to return only JSON.
206+
- Call Azure OpenAI using the provided deployment name. The response is normalized by removing markdown code fences and then deserialized back into the same GridReport shape.
207+
- Dynamically add a DataGridTextColumn to display AnomalyDescription and hydrate the bound items with the AI results.
208+
- Use ColorConverter to visually flag anomalous cells and the description column for quick scanning.
209+
- If the AI call fails, the fallback path finds extreme values and sets a reasonable default AnomalyDescription for one or more rows.
210+
211+
Note on secrets: do not hard-code keys in source. Replace any placeholder/API key with a secure configuration (environment variables, user secrets, or secure storage). Example in OpenAi.cs should be adapted before publishing.
212+
213+
##### Conclusion
214+
215+
I hope you enjoyed learning about how to leveraging AI with .NET MAUI DataGrid (SfDataGrid).
216+
217+
You can refer to our [.NET MAUI DataGrid’s feature tour](https://www.syncfusion.com/maui-controls/maui-datagrid) page to learn about its other groundbreaking feature representations. You can also explore our [.NET MAUI DataGrid Documentation](https://help.syncfusion.com/maui/datagrid/getting-started) to understand how to present and manipulate data.
218+
For current customers, you can check out our .NET MAUI components on the [License and Downloads](https://www.syncfusion.com/sales/teamlicense) page. If you are new to Syncfusion, you can try our 30-day [free trial](https://www.syncfusion.com/downloads/maui) to explore our .NET MAUI DataGrid and other .NET MAUI components.
219+
220+
If you have any queries or require clarifications, please let us know in the comments below. You can also contact us through our [support forums](https://www.syncfusion.com/forums), [Direct-Trac](https://support.syncfusion.com/create) or [feedback portal](https://www.syncfusion.com/feedback/maui?control=sfdatagrid), or the feedback portal. We are always happy to assist you!

0 commit comments

Comments
 (0)