KOD
sgcUI w oknie Avalonia 12
Każdy fragment jest skopiowany z przykładu AvaloniaProAlternative, aplikacji Avalonia 12 na net8.0 ze skompilowanymi powiązaniami i FluentTheme, która kompiluje się w Release dla edycji Registered i Community z 0 ostrzeżeń w demo i przechodzi swój autotest. Nie ma tu żadnego kodu Avalonia Pro: ta strona pokazuje wyłącznie kod, który został skompilowany.
Jeden prefiks XAML dla wszystkich produktów
Każdy zestaw sgcUI Avalonia mapuje swoje kontrolki na jeden URI przestrzeni nazw, więc jeden prefiks sgc obejmuje je wszystkie, obok domyślnej przestrzeni nazw 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">
Nie wymieniono na stronie Avalonia Pro: harmonogram i Kanban na tej samej liście zadań
Oba widoki wiążą się z tą samą kolekcją Tasks modelu widoku. TsgcAvaloniaPlannerItemFields mapuje członków Twojej własnej klasy zadania, a przeciągnięcie w którymkolwiek widoku zapisuje z powrotem Begin, End lub Stage w zadaniu:
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>
Gdy zastępujesz równoważną kontrolkę, zmienia się widok, a model widoku zostaje. Siatka z zadeklarowanymi kolumnami i dwukierunkowym SelectedItem:
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>
Wykres liniowy na osi daty i godziny:
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>
Przeglądarka PDF z miniaturami, powiązana z TsgcPDFDocument w modelu widoku:
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"/>
Model widoku buduje dokument za pomocą sgcPDF, zapisuje go w pamięci i wczytuje z powrotem, tak jak robi to dokument odczytany z pliku, zanim trafi do przeglądarki:
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;
}
Edytor tekstu sformatowanego, powiązany jako tekst Markdown (sgcRichEdit jest dostępny tylko w edycji 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"); }
}
}
Motyw pozostaje na miejscu
Aplikacja zachowuje FluentTheme. Kontrolki sgcUI podążają za jego wariantem motywu, jasnym, ciemnym lub ustawieniem systemu operacyjnego, i przełączają się na żywo razem z kontrolkami 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;
}
}