IL CODICE
sgcUI in una Window di Avalonia 12
Ogni estratto è copiato dall'esempio AvaloniaProAlternative, un'app Avalonia 12 su net8.0 con binding compilati e FluentTheme, che si compila in Release per le edizioni Registered e Community con 0 avvisi nella demo e supera il proprio test automatico. Qui non c'è codice di Avalonia Pro: questa pagina mostra solo codice che è stato compilato.
Un solo prefisso XAML per ogni prodotto
Ogni assembly Avalonia di sgcUI associa i propri controlli a un solo URI di namespace, quindi un unico prefisso sgc li copre tutti, accanto al namespace predefinito di Avalonia:
MainWindow.axaml<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sgc="https://www.esegece.com/sgcui"
xmlns:vm="using:sgcUIAvaloniaPro"
x:Class="sgcUIAvaloniaPro.MainWindow"
x:DataType="vm:TMainViewModel"
Title="sgcUI next to Avalonia 12: the controls Avalonia Pro does not ship" Width="1240" Height="820">
Non elencato nella pagina di Avalonia Pro: scheduler e Kanban su un'unica lista di attività
Entrambe le viste si collegano alla stessa collezione Tasks del view model. TsgcAvaloniaPlannerItemFields associa i membri della tua classe di attività, e un trascinamento in una delle due viste riscrive Begin, End o Stage nell'attività:
MainWindow.axaml<sgc:TsgcAvaloniaScheduler x:Name="scheduler" ItemsSource="{Binding Tasks}"
ResourcesSource="{Binding People}" SelectedItem="{Binding Selected}">
<sgc:TsgcAvaloniaScheduler.ItemFields>
<sgc:TsgcAvaloniaPlannerItemFields IdField="Key" TitleField="Name" StartField="Begin"
FinishField="End" ResourcesField="Owner" StatusField="Stage"/>
</sgc:TsgcAvaloniaScheduler.ItemFields>
<sgc:TsgcAvaloniaScheduler.ResourceFields>
<sgc:TsgcAvaloniaPlannerResourceFields IdField="Code" NameField="Label"/>
</sgc:TsgcAvaloniaScheduler.ResourceFields>
</sgc:TsgcAvaloniaScheduler>
<sgc:TsgcAvaloniaKanban x:Name="kanban" Grid.Row="1" Margin="0,8,0,0" ColumnSource="pkcList"
ItemsSource="{Binding Tasks}" ResourcesSource="{Binding People}"
SelectedItem="{Binding Selected}">
<sgc:TsgcAvaloniaKanban.ItemFields>
<sgc:TsgcAvaloniaPlannerItemFields IdField="Key" TitleField="Name" StartField="Begin"
FinishField="End" ResourcesField="Owner" StatusField="Stage"/>
</sgc:TsgcAvaloniaKanban.ItemFields>
<sgc:TsgcAvaloniaKanban.ResourceFields>
<sgc:TsgcAvaloniaPlannerResourceFields IdField="Code" NameField="Label"/>
</sgc:TsgcAvaloniaKanban.ResourceFields>
<sgc:TsgcAvaloniaKanban.Columns>
<sgc:TsgcAvaloniaKanbanColumn StatusId="todo" Caption="To do"/>
<sgc:TsgcAvaloniaKanbanColumn StatusId="doing" Caption="In progress"/>
<sgc:TsgcAvaloniaKanbanColumn StatusId="done" Caption="Done"/>
</sgc:TsgcAvaloniaKanban.Columns>
</sgc:TsgcAvaloniaKanban>
Non elencato: una dashboard di schede KPI e un grafico
Tile su una griglia a 12 colonne, ciascuno con una scheda KPI o un controllo qualsiasi, collegati al view model:
MainWindow.axaml<sgc:TsgcAvaloniaDashboard x:Name="dashboard" Columns="12" RowHeight="110">
<sgc:TsgcAvaloniaDashboardTile Title="Revenue" Col="0" Row="0" ColSpan="4" RowSpan="2">
<sgc:TsgcAvaloniaKPICard x:Name="kpiRevenue" Title="Revenue this month" Value="{Binding Revenue}"
Trend="ktUp" FooterText="all channels"/>
</sgc:TsgcAvaloniaDashboardTile>
<sgc:TsgcAvaloniaDashboardTile Title="Orders" Col="4" Row="0" ColSpan="4" RowSpan="2">
<sgc:TsgcAvaloniaKPICard x:Name="kpiOrders" Title="Orders" Value="{Binding Orders}"
Trend="ktUp" FooterText="this month"/>
</sgc:TsgcAvaloniaDashboardTile>
<sgc:TsgcAvaloniaDashboardTile Title="Support" Col="8" Row="0" ColSpan="4" RowSpan="2">
<sgc:TsgcAvaloniaKPICard x:Name="kpiTickets" Title="Open tickets" Value="{Binding Tickets}"
Trend="ktDown" FooterText="help desk"/>
</sgc:TsgcAvaloniaDashboardTile>
<sgc:TsgcAvaloniaDashboardTile Title="Visits per day" Col="0" Row="2" ColSpan="12" RowSpan="3">
<sgc:TsgcAvaloniaChart x:Name="chartVisits">
<sgc:TsgcAvaloniaChartSeries ItemsSource="{Binding Visits}" XMember="Time" YMember="Value"
Title="Visits" Color="#FF16A34A"/>
<sgc:TsgcAvaloniaChart.Axes>
<sgc:TsgcAvaloniaChartAxis Name="X" AxisType="catDateTime"/>
<sgc:TsgcAvaloniaChartAxis Name="Y" Title="Visits"/>
</sgc:TsgcAvaloniaChart.Axes>
</sgc:TsgcAvaloniaChart>
</sgc:TsgcAvaloniaDashboardTile>
</sgc:TsgcAvaloniaDashboard>
Presenti anche in Avalonia Pro: griglia, grafico, visualizzatore PDF e testo ricco
Quando sostituisci un controllo sovrapposto, cambia la vista e il view model resta. La griglia con colonne dichiarate e un SelectedItem bidirezionale:
MainWindow.axaml<sgc:TsgcAvaloniaGrid x:Name="grid" x:DataType="vm:TGridViewModel" Margin="8"
ItemsSource="{Binding Customers}" SelectedItem="{Binding Selected}"
KeyMember="Id" AutoGenerateColumns="False">
<sgc:TsgcAvaloniaGridColumn FieldName="Id" Caption="Id" Width="60" DataType="gdtInteger"/>
<sgc:TsgcAvaloniaGridColumn FieldName="Name" Caption="Customer" Width="220"/>
<sgc:TsgcAvaloniaGridColumn FieldName="City" Caption="City" Width="140"/>
<sgc:TsgcAvaloniaGridColumn FieldName="Balance" Caption="Balance" Width="130" DataType="gdtFloat"
DisplayFormat="#,##0.00" Alignment="gaRight"/>
</sgc:TsgcAvaloniaGrid>
Un grafico a linee su un asse data e ora:
MainWindow.axaml<sgc:TsgcAvaloniaChart x:Name="chartPrice" x:DataType="vm:TChartViewModel" Margin="8">
<sgc:TsgcAvaloniaChartSeries ItemsSource="{Binding Prices}" XMember="Time" YMember="Value"
Title="Price" Color="#FF2563EB"/>
<sgc:TsgcAvaloniaChart.Axes>
<sgc:TsgcAvaloniaChartAxis Name="X" AxisType="catDateTime" Title="Time"/>
<sgc:TsgcAvaloniaChartAxis Name="Y" Title="Price"/>
</sgc:TsgcAvaloniaChart.Axes>
</sgc:TsgcAvaloniaChart>
Un visualizzatore PDF con miniature, collegato a un TsgcPDFDocument del view model:
MainWindow.axaml<sgc:TsgcAvaloniaPDFThumbnailView x:Name="pdfThumbs" Viewer="{Binding #pdfViewer}"/>
<sgc:TsgcAvaloniaPDFViewer x:Name="pdfViewer" Grid.Column="1" Margin="8,0,0,0"
Document="{Binding Document}" ZoomMode="zmFitWidth"/>
Il view model costruisce il documento con sgcPDF, lo salva in memoria e lo rilegge, nello stesso modo in cui un documento letto da un file arriva al visualizzatore:
ViewModels\TOverlapViewModels.cs// a three page A4 report written with sgcPDF, saved to memory and parsed back,
// the way a document read from a file or a stream reaches the viewer
private static TsgcPDFDocument DoBuild()
{
byte[] vBytes;
using (TsgcPDFDocument oWriter = new TsgcPDFDocument())
{
for (int i = 1; i <= CS_PAGES; i++)
{
TsgcPDFPage oPage = oWriter.AddPage(595, 842);
oPage.DrawRectangleFill(0, 772, 595, 70, 0.12, 0.23, 0.54);
oPage.DrawTextColor("Quarterly report, page " + i + " of " + CS_PAGES, 50, 800,
TsgcPDFStandardFont.sfHelveticaBold, 20, 1, 1, 1);
oPage.DrawText("Built in code with sgcPDF (TsgcPDFDocument) and shown by TsgcAvaloniaPDFViewer.", 50,
730, TsgcPDFStandardFont.sfHelvetica, 12);
oPage.DrawText("Search, zoom, thumbnails and text selection work on it like on any PDF file.", 50,
710, TsgcPDFStandardFont.sfHelvetica, 12);
for (int k = 0; k < 6; k++)
oPage.DrawRectangleFill(60 + k * 80, 420, 50, 40 + ((i * 3 + k * 5) % 9) * 25, 0.15, 0.39, 0.92);
oPage.DrawRectangle(40, 40, 515, 712, 1.0);
}
using (MemoryStream oStream = new MemoryStream())
{
oWriter.SaveToStream(oStream);
vBytes = oStream.ToArray();
}
}
TsgcPDFDocument vResult = new TsgcPDFDocument();
vResult.LoadFromBytes(vBytes);
return vResult;
}
L'editor di testo ricco, collegato come testo Markdown (sgcRichEdit è solo Registered):
Views\RichEditTab.axaml<sgc:TsgcAvaloniaRichEdit x:Name="richEdit" Margin="8" DocumentFormat="refMarkdown"
DocumentText="{Binding Text}"/>
ViewModels\TOverlapViewModels.cspublic sealed class TRichTextViewModel : TViewModelBase
{
private string FText =
"# Release notes\n\nThe **sgcRichEdit** control is bound to this view model through " +
"*DocumentText* in Markdown.\n\n- Styles, lists and tables\n- Links such as " +
"[www.esegece.com](https://www.esegece.com)\n- HTML, RTF, Markdown and JSON in and out\n";
/// <summary>The document as Markdown (DocumentFormat="refMarkdown"), written back on focus loss.</summary>
public string Text
{
get { return FText; }
set { DoSet(ref FText, value, "Text"); }
}
}
Il tema resta dov'è
L'applicazione mantiene FluentTheme. I controlli sgcUI seguono la sua variante di tema, chiara, scura o l'impostazione del sistema operativo, e cambiano in tempo reale insieme ai controlli Fluent:
Program.cspublic override void Initialize()
{
// the existing host theme stays: the sgcUI controls follow its theme variant
Styles.Add(new FluentTheme());
RequestedThemeVariant = ThemeVariant.Default;
}
ViewModels\TOverlapViewModels.cs/// <summary>0 Follow host (RequestedThemeVariant Default), 1 Light, 2 Dark. The sgcUI controls
/// follow the Avalonia theme variant of the FluentTheme host (ThemeFollow utfHost).</summary>
public int ModeIndex
{
get { return FModeIndex; }
set
{
if (value < 0 || value > 2 || !DoSet(ref FModeIndex, value, "ModeIndex"))
return;
sgcUIApplication.ThemeFollow = TsgcUIThemeFollow.utfHost;
sgcUIApplication.SetTheme(TsgcUITheme.utDefault);
if (Application.Current != null)
Application.Current.RequestedThemeVariant = value == 1 ? ThemeVariant.Light :
value == 2 ? ThemeVariant.Dark : ThemeVariant.Default;
}
}