20a45e06cd
SKILL.md odchudzony z 493 do 333 linii: sekcje Serwisy, Tłumaczenia i Log wyciągnięte do nowych referencji, sekcja Session skrócona do fundamentów (szczegóły w session-login.md), dodana Mapa skilla. W examples.md usunięte duplikaty z context.md i datapack-guidedrow.md, dodane spisy treści do dużych referencji. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
608 lines
21 KiB
Markdown
608 lines
21 KiB
Markdown
# Action result zwracany przez akcje (worker, extender, Command)
|
|
|
|
Akcje (metody worker, akcje extender, handlery Command, callbacki) zwracają **action result** — obiekt
|
|
sterujący tym, co stanie się w UI po wykonaniu logiki biznesowej. Typ zwróconego obiektu decyduje
|
|
o sposobie obsługi.
|
|
|
|
## Spis treści
|
|
|
|
- [Najważniejsza zasada](#najważniejsza-zasada)
|
|
- [Wartości specjalne](#wartości-specjalne) - `null`, `string`, `bool`
|
|
- [Sterowanie aktualnym formularzem](#sterowanie-aktualnym-formularzem) - close, refresh
|
|
- [Okna informacyjne i pytania do użytkownika](#okna-informacyjne-i-pytania-do-użytkownika) - MessageBox, potwierdzenia
|
|
- [Otwieranie obiektów i okien](#otwieranie-obiektów-i-okien) - edycja, podgląd
|
|
- [Nawigacja po programie](#nawigacja-po-programie) - listy, foldery, URL
|
|
- [Pliki i strumienie](#pliki-i-strumienie) - pobieranie plików, podgląd
|
|
- [Raporty](#raporty) - generowanie i parametry raportów
|
|
- [Dialogi parametrów](#dialogi-parametrów) - kreatory, dialog z ContextBase
|
|
- [Operacje klienta i bezpieczeństwo](#operacje-klienta-i-bezpieczeństwo)
|
|
- [Tabela szybkiego wyboru](#tabela-szybkiego-wyboru) - mapa typ → efekt UI
|
|
|
|
## Najważniejsza zasada
|
|
|
|
**Nie wywołuj sam UI z poziomu worker/extender.** Zamiast pokazywać MessageBox, otwierać formularz
|
|
czy generować plik — **zwróć odpowiedni action result**. Framework zrobi resztę, panując nad sesją,
|
|
transakcją i wątkiem UI.
|
|
|
|
```csharp
|
|
// ŹLE - kod biznesowy nie powinien znać UI
|
|
[Action("Sprawdź")]
|
|
public void Sprawdz() {
|
|
MessageBoxWindow.Show("Niepoprawne dane".Translate()); // <- nie tak
|
|
}
|
|
|
|
// DOBRZE - zwracamy action result
|
|
[Action("Sprawdź")]
|
|
public object Sprawdz() {
|
|
return new MessageBoxInformation("Walidacja".Translate(), "Niepoprawne dane".Translate());
|
|
}
|
|
```
|
|
|
|
## Wartości specjalne
|
|
|
|
| Zwrócona wartość | Działanie |
|
|
|---|---|
|
|
| `null` | Brak akcji. Transakcja jest commitowana. |
|
|
| `void` (metoda bez return) | Brak akcji. |
|
|
| `Task` / `Task<T>` | Framework czeka na zakończenie i obsługuje zwróconą wartość. |
|
|
| `Exception` | Pokazuje okno błędu (`MessageBoxWindow.ShowException`). Transakcja jest commitowana (rollback w wyjątku robi się wcześniej). |
|
|
|
|
## Sterowanie aktualnym formularzem
|
|
|
|
### `FormAction` (enum)
|
|
|
|
Najprostsza forma — sama wartość enum jako action result. Handler konwertuje to
|
|
do `FormActionResult` z ustawioną akcją.
|
|
|
|
| Wartość | Działanie |
|
|
|---|---|
|
|
| `None` | Brak akcji. |
|
|
| `Save` | Zapis bez zamykania, bez potwierdzeń warningów. |
|
|
| `SaveWithConfirmation` | Zapis bez zamykania, z potwierdzeniem warningów. |
|
|
| `SaveAndClose` | Zapis i zamknięcie, bez potwierdzeń. |
|
|
| `SaveAndCloseWithConfirmation` | Zapis i zamknięcie, z potwierdzeniem warningów. |
|
|
| `Refresh` | Odczyt danych formularza z bazy. |
|
|
| `RefreshOwner` | Odświeżenie formularza-rodzica. |
|
|
| `Close` | Zamknięcie bez zapisu, bez ostrzeżeń. |
|
|
|
|
```csharp
|
|
[Action("Zatwierdź")]
|
|
public FormAction Zatwierdz() {
|
|
Status = Status.Zatwierdzony;
|
|
return FormAction.SaveAndClose;
|
|
}
|
|
```
|
|
|
|
### `FormActionResult`
|
|
|
|
Rozszerzona wersja `FormAction` — pozwala dodać `EditValue` (kontynuacja po zapisie), `Context`,
|
|
`CommittedHandler` (kod wywoływany po commit transakcji).
|
|
|
|
```csharp
|
|
return new FormActionResult {
|
|
Action = FormAction.SaveAndClose,
|
|
EditValue = nowyDokument, // otwarcie kolejnego obiektu po zapisie
|
|
CommittedHandler = context => null,
|
|
};
|
|
```
|
|
|
|
## Okna informacyjne i pytania do użytkownika
|
|
|
|
### `string`
|
|
|
|
Krótki komunikat — handler konwertuje do `MessageBoxInformation` z domyślnym tytułem "Informacja".
|
|
|
|
```csharp
|
|
return "Operacja zakończona pomyślnie".Translate();
|
|
```
|
|
|
|
### `MessageBoxInformation`
|
|
|
|
Pełna kontrola nad okienkiem dialogowym. Przyciski (OK / Anuluj / Tak / Nie) pojawiają się
|
|
automatycznie na podstawie ustawionych handlerów (`OKHandler`, `CancelHandler`, `YesHandler`,
|
|
`NoHandler`). Handler każdego przycisku jest typu `Func<object>` — **może zwrócić kolejny action result**,
|
|
który zostanie obsłużony rekurencyjnie (mechanizm `DelayedHandler`).
|
|
|
|
| Property | Znaczenie |
|
|
|---|---|
|
|
| `Caption` | Tytuł okna (NULL = standardowy zależny od `Type`). |
|
|
| `Text` / `TextMarkdown` | Treść (czysty tekst lub markdown). |
|
|
| `Type` | `Information` / `Warning` / `Error` — kolorystyka. |
|
|
| `OKHandler` / `CancelHandler` / `YesHandler` / `NoHandler` | Akcje po wybraniu przycisku. |
|
|
| `IsSecondDefault` | `Enter` wywołuje drugą akcję (No/Cancel zamiast Yes/OK). |
|
|
|
|
```csharp
|
|
return new MessageBoxInformation("Potwierdzenie".Translate(), "Czy na pewno usunąć?".Translate()) {
|
|
Type = MessageBoxInformationType.Warning,
|
|
YesHandler = () => {
|
|
Usun();
|
|
return FormAction.RefreshOwner;
|
|
},
|
|
NoHandler = () => null,
|
|
};
|
|
```
|
|
|
|
## Otwieranie obiektów i okien
|
|
|
|
### Zwrócenie `Row` lub dowolnego `object`
|
|
|
|
Domyślny handler otwiera obiekt w nowym formularzu
|
|
(`ObjectWindow` w HTML). Działa to dla każdego typu nieobsługiwanego przez specyficzne handlery — w tym
|
|
`GuidedRow`, kreatorów, dialogów.
|
|
|
|
```csharp
|
|
[Action("Otwórz kontrahenta")]
|
|
public Kontrahent OtworzKontrahenta() => Wystawca;
|
|
```
|
|
|
|
## Nawigacja po programie
|
|
|
|
### `NavigationResult`
|
|
|
|
Przejście do innego folderu danych lub bazy. Działa jak kliknięcie w drzewie folderów.
|
|
|
|
| Property | Znaczenie |
|
|
|---|---|
|
|
| `Address` | Ścieżka folderu (np. `"Handel/Sprzedaż/Faktury sprzedaży"`) lub `/<DB>/<ścieżka>` dla innej bazy. |
|
|
| `Context` | Kontekst (filtry) folderu. |
|
|
| `Target` | `Self` / `NewWindow` / `NewTab`. |
|
|
| `KeepCurrentCredentials` | Logowanie do innej bazy aktualnymi danymi (JWT). |
|
|
| `KeepSessionLiving` | Przeniesienie żywej sesji do folderu docelowego (`Self` only). |
|
|
| `KeepCurrentViewInHistory` | Aktualny widok zostaje w historii nawigacji. |
|
|
|
|
Najważniejsze ścieżki do folderów aplikacji znajdują się w skill `/soneta-mcp-ui/common-folders.md`.
|
|
|
|
```csharp
|
|
return new NavigationResult("Handel/Sprzedaż/Faktury sprzedaży") {
|
|
Target = NavigationTarget.NewTab
|
|
};
|
|
```
|
|
|
|
### `HyperlinkResult`
|
|
|
|
Otwarcie URL w przeglądarce.
|
|
|
|
```csharp
|
|
return new HyperlinkResult {
|
|
Address = "https://soneta.pl",
|
|
Target = NavigationTarget.NewWindow,
|
|
};
|
|
```
|
|
|
|
### `CommandMenu`
|
|
|
|
Menu poleceń wyświetlone użytkownikowi (drop-down z opcjami). Po wybraniu wykonuje się akcja
|
|
przypisana do polecenia.
|
|
|
|
### `LoginParameters`
|
|
|
|
Wymusza przelogowanie (np. po zmianie operatora). Framework wywołuje `LoginService.Relogin`.
|
|
|
|
## Pliki i strumienie
|
|
|
|
### `NamedStream`
|
|
|
|
Pojedynczy plik do pobrania przez przeglądarkę lub ramkę SonetaFrame.
|
|
|
|
```csharp
|
|
return new NamedStream("raport.pdf", () => GenerujPdfStream());
|
|
```
|
|
|
|
### `NamedStream[]`
|
|
|
|
Tablica plików → spakowane jako ZIP (`Pliki_yyyyMMddHHmmssfff.zip`) i pobrane jako jeden plik lub zapisywane pojedynczo
|
|
przez ramkę SonetaFrame.
|
|
|
|
### `StorageFileEditor`
|
|
|
|
Edycja pliku przechowywanego w storage bazy danych (XML, DOCX, REPX, itp.)
|
|
|
|
## Raporty
|
|
|
|
### `ReportResult`
|
|
|
|
Główny action result raportu — uruchamia mechanizm wydruków. Działa w **trzech trybach**:
|
|
|
|
1. **Tryb interaktywny (menu)** — bez `TemplateFileName`, framework otwiera okno raportu i ewentualne
|
|
okno parametrów (`UseReportMenu == true`). Stosować, gdy chcemy pokazać użytkownikowi listę
|
|
dostępnych wzorców dla danego typu/ViewInfo.
|
|
2. **Tryb automatyczny (z kodu)** — z `TemplateFileName`, bez UI raportu. Wzorzec wskazany jawnie,
|
|
wydruk od razu generowany. Można dodać `OutputHandler` do przejęcia strumienia wynikowego.
|
|
3. **Tryb serwisowy (bez rezultatu)** — przez `IReportService.GenerateReport / GenerateReportStr /
|
|
PrintReport`. Stosować w testach, taskach tła i kodzie nie-UI.
|
|
|
|
#### Najważniejsze property
|
|
|
|
| Property | Znaczenie |
|
|
|---|---|
|
|
| `TemplateFileName` | Nazwa lub ścieżka wzorca (`.repx`, `.repx.cs`, `.aspx`, `.dotx`) lub XML z ustawieniami wydruku. Ustawienie wyklucza `ReportName`. |
|
|
| `TemplateFileSource` | `AspxSource.Local` (plik na dysku) / `Storage` (konfiguracja w bazie — pliki w `XtraReports/...`). |
|
|
| `ReportName` | Nazwa raportu z menu (tryb interaktywny). Wyklucza `TemplateFileName`. |
|
|
| `DataType` | Typ danych — `typeof(Towar)` (jeden obiekt), `typeof(Towary)` (cały View), `typeof(Towar[])` (zaznaczone wiersze). Steruje też ładowaniem listy dostępnych wydruków. |
|
|
| `ViewInfo` | ViewInfo źródłowego widoku (np. dla raportów listy z customowym ViewInfo). |
|
|
| `ViewNames` | Nazwy widoków, w których wyszukać raport po nazwie. |
|
|
| `Rows` | `IEnumerable` z wierszami źródłowymi (zamiast pobierania z `Context`). **Nie działa** w trybie menu. |
|
|
| `Context` | Kontekst raportu — źródło parametrów (`Context.Set(params)`), zaznaczeń, kultury. |
|
|
| `OutputFormat` | `HTML` (domyślnie) / `PDF` / `TXT`. |
|
|
| `Target` | `File` / `Preview` / `Printer`. Z `OutputHandler` traktowany jak `File`. |
|
|
| `PrinterName` | Drukarka dla `Target = Printer`. |
|
|
| `CultureInfo` | Język wydruku (nadpisuje kulturę sesji — patrz `DxReport_Generator_Dx_Zakup_English_ReportResult`). |
|
|
| `AskForParameters` | `false` = wydruk bez pytania o parametry (wymaga ustawionych parametrów w `Context`). |
|
|
| `Sign` / `VisibleSignature` / `Encrypt` | Podpis certyfikatem i hasło PDF (tylko tryb interaktywny w wersji desktop). |
|
|
| `OutputHandler` | `Func<Stream, object>` — przejmuje wygenerowany strumień, jego wynik staje się rezultatem akcji. Tylko z `TemplateFileName`. |
|
|
| `ParametersHandler` | `Action<Type, Context>` wywoływany przed pytaniem o parametry — sposób na zainicjowanie obiektów parametrów (oddzielnie dla każdego typu). |
|
|
| `Caption` | Tytuł okna. |
|
|
|
|
#### Wzorzec: wydruk z akcji (worker / extender)
|
|
|
|
```csharp
|
|
[Action("Drukuj fakturę")]
|
|
public object DrukujFV() {
|
|
Context.Set(new SprzedazSnippet.MyParametryWydruku(Context));
|
|
return new ReportResult {
|
|
TemplateFileName = "Sprzedaz.repx",
|
|
DataType = typeof(DokumentHandlowy),
|
|
Context = Context,
|
|
AskForParameters = false,
|
|
};
|
|
}
|
|
```
|
|
|
|
#### Wzorzec: wydruk z testu / taska (bez UI)
|
|
|
|
```csharp
|
|
var rs = Session.GetRequiredService<IReportService>();
|
|
|
|
Context.Set(new SprzedazSnippet.MyParametryWydruku(Context));
|
|
|
|
var rr = new ReportResult {
|
|
TemplateFileName = "Sprzedaz.repx",
|
|
DataType = typeof(DokumentHandlowy),
|
|
Context = Context,
|
|
AskForParameters = false,
|
|
};
|
|
|
|
string html = rs.GenerateReportStr(rr); // HTML jako string
|
|
// lub
|
|
using var stream = rs.GenerateReport(rr); // strumień (PDF / inny)
|
|
// lub
|
|
rs.PrintReport(rr, archive: true, archivePath: "C:\\Archive");
|
|
```
|
|
|
|
#### Wzorzec: wzorzec ze storage (XtraReports/Wzorce użytkownika)
|
|
|
|
```csharp
|
|
var rr = new ReportResult {
|
|
TemplateFileName = "XtraReports/Wzorce użytkownika/EmptyReport.repx.cs",
|
|
TemplateFileSource = AspxSource.Storage,
|
|
Context = Context,
|
|
AskForParameters = false,
|
|
};
|
|
```
|
|
|
|
#### Wzorzec: zaznaczone wiersze + custom params
|
|
|
|
```csharp
|
|
Context.Set(towary); // tablica zaznaczonych Row
|
|
Context.Set(new CennikViewInfo.CennikParams(Context));
|
|
|
|
var rr = new ReportResult {
|
|
DataType = typeof(Towar[]), // l.mn. = zaznaczone
|
|
TemplateFileName = "...",
|
|
TemplateFileSource = AspxSource.Storage,
|
|
Context = Context,
|
|
OutputFormat = ReportFormats.TXT,
|
|
AskForParameters = false,
|
|
};
|
|
```
|
|
|
|
#### Wzorzec: jeden obiekt + powiązane konteksty
|
|
|
|
```csharp
|
|
var fvNewSession = Session.Get(fv);
|
|
Context.Set(fvNewSession); // single
|
|
Context.Set(new[] { fvNewSession }); // jako tablica (dla DataType = Towar[])
|
|
Context.Set(new SprzedazSnippet.MyParametryWydruku(Context));
|
|
|
|
var rr = new ReportResult {
|
|
TemplateFileName = "Sprzedaz.repx",
|
|
DataType = typeof(DokumentHandlowy),
|
|
Context = Context,
|
|
AskForParameters = false,
|
|
};
|
|
```
|
|
|
|
#### Wzorzec: wymuszenie języka wydruku
|
|
|
|
```csharp
|
|
var rr = new ReportResult {
|
|
TemplateFileName = "Zakup.repx",
|
|
DataType = typeof(DokumentHandlowy),
|
|
Context = Context,
|
|
OutputFormat = ReportFormats.TXT,
|
|
CultureInfo = CoreTools.CultureEN,
|
|
AskForParameters = false,
|
|
};
|
|
```
|
|
|
|
#### Sprawdzenie wymaganych typów parametrów
|
|
|
|
Przykład uzupełnia context standardowymi wartościami parametrów potrzebnymi dla raportu.
|
|
|
|
```csharp
|
|
Type[] paramTypes = rs.GetParameterTypes("Sprzedaz.repx", Context);
|
|
foreach (Type t in paramTypes) {
|
|
Context.Set(Activator.CreateInstance(t, Context));
|
|
}
|
|
```
|
|
|
|
#### Deprecated property
|
|
|
|
- `TemplateType` → używać `TemplateFileName`.
|
|
- `Format` (`ReportResultFormat`) → używać `OutputFormat` (`ReportFormats`).
|
|
- `Preview` → używać `Target = ReportTargets.Preview`.
|
|
- `SilentProgress` → używać `!AskForParameters`.
|
|
|
|
### `ReportOrganizerResult`
|
|
|
|
Menedżer raportów (lista raportów dla tabeli/widoku) — okno zarządzania zestawem raportów dla
|
|
podanego typu danych.
|
|
|
|
### `ReportEditorResult`
|
|
|
|
Otwarcie edytora raportu (DOTX, DX) — w zależności od `Format` wybierany jest odpowiedni handler.
|
|
|
|
### `PdfResult`
|
|
|
|
Pojedynczy PDF (do podglądu, druku lub pobrania) sterowany przez `Action`:
|
|
`Preview` / `Print` / `Save` / `OpenInBrowser`.
|
|
|
|
### `PdfResult[]`
|
|
|
|
Tablica PDF — handler (`PdfsResultHandler`) wysyła wszystkie na drukarkę przez `IPrintingService`.
|
|
|
|
### `DotxReportPrintResult`, `TextReportPrintResult`, `DxReportPrintResult`
|
|
|
|
Specjalizowane action result wydruku / podglądu konkretnych formatów (DOTX edytor, raport tekstowy,
|
|
DevExpress).
|
|
|
|
## Dialogi parametrów
|
|
|
|
### `QueryContextInformation`
|
|
|
|
Otwiera okno z parametrami uzupełniającymi `Context` przed wywołaniem właściwej operacji. To samo
|
|
okno pojawia się przed niektórymi czynnościami z menu lub przed raportami. Po `OK` wywoływany jest
|
|
handler, który dostaje uzupełnione obiekty parametrów jako argumenty. Po `Cancel` — `CancelHandler`.
|
|
|
|
#### Mechanizm
|
|
|
|
1. Akcja zwraca `QueryContextInformation` z handlerem typu `Func<Tn, object>`.
|
|
2. Framework patrzy na typy parametrów handlera (`T1`, `T2`, ...).
|
|
3. Dla każdego typu sprawdza, czy `Context` zawiera już instancję — jeśli **tak**, pomija
|
|
pytanie i od razu wywołuje handler.
|
|
4. Jeśli czegoś brakuje, otwiera okno parametrów (renderowane przez `QueryContextRenderer`).
|
|
5. Po `OK` wywołuje handler z parametrami pobranymi z `Context`.
|
|
6. Wartość zwrócona z handlera staje się **kolejnym action result** (rekurencyjnie obsługiwana).
|
|
|
|
#### Tworzenie — fabryki `Create`
|
|
|
|
```csharp
|
|
// Jeden typ parametrów
|
|
QueryContextInformation.Create<Params>(p => DoWork(p));
|
|
|
|
// Kilka typów (do 6)
|
|
QueryContextInformation.Create<Params1, Params2>((p1, p2) => DoWork(p1, p2));
|
|
|
|
// Context + parametry (Context można dostać jako pierwszy parametr)
|
|
QueryContextInformation.Create<Context, Params>((cx, p) => DoWork(cx, p));
|
|
|
|
// Bez handlera — sama informacja "wypełnij te typy w kontekście"
|
|
QueryContextInformation.CreateForTypes(typeof(Params1), typeof(Params2));
|
|
|
|
// Z dowolnego Delegate
|
|
QueryContextInformation.CreateFromHandler(myDelegate);
|
|
```
|
|
|
|
#### Klasa parametrów
|
|
|
|
Typowo dziedziczy z `ContextBase` (przyjmuje `Context` w konstruktorze, ma `OnChanged()` do
|
|
odświeżania), używa atrybutów Soneta i `System.ComponentModel`:
|
|
|
|
```csharp
|
|
[Caption("Parametry wydruku")]
|
|
class MyParams(Context context) : ContextBase(context) {
|
|
|
|
[Category("Daty")] // grupowanie wizualne
|
|
[Caption("Data od")]
|
|
[Priority(1)] // kolejność w grupie
|
|
[Accessor(AutoChange=true)]
|
|
public Date DataOd { get; set; }
|
|
|
|
[Category("Daty")]
|
|
[Caption("Zakres")]
|
|
[Priority(3)]
|
|
[Accessor(AutoChange=true)]
|
|
public FromTo Okres { get; set; }
|
|
|
|
[Category("Informacje")]
|
|
[Caption("Opis")]
|
|
[Required]
|
|
[Accessor(AutoChange=true)]
|
|
public string Info { get; set; }
|
|
|
|
[Hidden] // ukrycie pola
|
|
public int Internal { get; set; }
|
|
}
|
|
```
|
|
|
|
Renderer:
|
|
|
|
- grupuje pola po `[Category]` (`GroupContainer` z `CaptionHtml = nazwa kategorii`),
|
|
- sortuje wewnątrz grupy po `[Priority]` (rosnąco),
|
|
- pomija pola z `[Hidden]` / `[Browsable(false)]`,
|
|
- `[Accessor(AutoChange=true)]` zadba o automatycznie wywołanie `Session.InvokeChanged()` na `set`.
|
|
- może renderować tę samą kategorię wielokrotnie, jeśli pola są przeplatane innymi.
|
|
|
|
#### Wzorzec: zapytanie o parametr w workerze
|
|
|
|
```csharp
|
|
[Action("Zmień podstawę zwolnienia")]
|
|
public object Zmien() {
|
|
return QueryContextInformation.Create<Params>(p => {
|
|
using var t = Towar.Session.Logout(true);
|
|
Towar.PodstawaZwolnienia = p.Podstawa;
|
|
t.Commit();
|
|
return null;
|
|
});
|
|
}
|
|
```
|
|
|
|
#### Wzorzec: łańcuch dialogów (wynik handlera = kolejny `QueryContextInformation`)
|
|
|
|
```csharp
|
|
[Action("Dwuetapowy dialog")]
|
|
public object Wieloetapowo() {
|
|
return QueryContextInformation.Create<Params1>(p1 =>
|
|
QueryContextInformation.Create<Params2>(p2 => {
|
|
using var t = Session.Logout(true);
|
|
// wykorzystaj p1 i p2
|
|
t.Commit();
|
|
return null;
|
|
})
|
|
);
|
|
}
|
|
```
|
|
|
|
#### Wzorzec: dialog wewnątrz `FormActionResult.CommittedHandler`
|
|
|
|
```csharp
|
|
return new FormActionResult {
|
|
EditValue = new SecondTestObject { Context = Context },
|
|
UseDialog = true,
|
|
CommittingHandler = cx => FormAction.Close,
|
|
CommittedHandler = cx => QueryContextInformation.Create<Params>(p => {
|
|
using var t = Towar.Session.Logout(true);
|
|
Towar.PodstawaZwolnienia = p.Podstawa;
|
|
t.Commit();
|
|
return Towar; // otworzy formularz dla Towar po pytaniu
|
|
})
|
|
};
|
|
```
|
|
|
|
#### Wzorzec: dialog z `MessageBoxInformation` jako wynikiem
|
|
|
|
```csharp
|
|
public object Pokaz() {
|
|
return QueryContextInformation.Create((MessageParams p) =>
|
|
new MessageBoxInformation {
|
|
Caption = "Test".Translate(),
|
|
Text = p.Message,
|
|
Type = p.IsWarning
|
|
? MessageBoxInformationType.Warning
|
|
: MessageBoxInformationType.Information
|
|
});
|
|
}
|
|
```
|
|
|
|
#### Wzorzec: dialog z plikami (`NamedStream[]`)
|
|
|
|
`QueryContextInformation` obsługuje też typy z plikami — w klasie parametrów `NamedStream` lub
|
|
`NamedStream[]` z `GetListXxx()` zwracającym `FileDialogInfo`:
|
|
|
|
```csharp
|
|
class NsArgs : ContextBase {
|
|
public NsArgs(Context cx) : base(cx) {}
|
|
|
|
public NamedStream[] Streams { get; set; }
|
|
|
|
public FileDialogInfo GetListStreams()
|
|
=> new FileDialogInfo { InitialDirectory = "x:\\" }
|
|
.AddTxtFilter()
|
|
.AddXmlFilter();
|
|
}
|
|
|
|
// użycie:
|
|
return QueryContextInformation.Create((NsArgs ns) => ns.Streams[0].FileName);
|
|
```
|
|
|
|
#### Property obiektu
|
|
|
|
| Property | Znaczenie |
|
|
|---|---|
|
|
| `Context` | Kontekst, na którym pracuje okno. Standardowo `null` → użyty zostanie kontekst wywołania. |
|
|
| `Caption` | Tytuł okna. |
|
|
| `Data` | Dane przekazane do konstruktora (rzadko używane bezpośrednio). |
|
|
| `Types` | Tablica typów do uzupełnienia w kontekście — gdy używamy `CreateForTypes`. |
|
|
| `AcceptHandler` | `Func<object>` bez parametrów. Alias na handler ustawiony przez `Create<>`. |
|
|
| `CancelHandler` | `Func<object>` — wynik traktowany jak kolejny action result. |
|
|
| `ResultHandler` | `Func<object, object>` — postprocessing wartości zwróconej z handlera. |
|
|
| `ObjectConstructor` | `ConstructorInfo` do tworzenia obiektu wynikowego (zaawansowane). |
|
|
| `GetHandler()` | Zwraca `Delegate` przekazany do `Create<>` (dla refleksji w testach). |
|
|
| `SetCaption(c)` / `SetCancelHandler(h)` | Fluent setter. |
|
|
|
|
#### `TryInvoke(Context)`
|
|
|
|
Pozwala uniknąć okna, gdy parametry **są już** w kontekście:
|
|
|
|
```csharp
|
|
// 1) gdy w kontekście brakuje Params - zwraca self (otwarcie okna)
|
|
object r = QueryContextInformation
|
|
.Create<Params>(MyAction)
|
|
.TryInvoke(cx);
|
|
// r is QueryContextInformation == true
|
|
|
|
// 2) gdy Params jest w kontekście - wywołuje handler natychmiast
|
|
cx.Set(new Params(cx) { ... });
|
|
object r = QueryContextInformation
|
|
.Create<Params>(MyAction)
|
|
.TryInvoke(cx);
|
|
// r == wynik MyAction
|
|
```
|
|
|
|
#### Walidacja typu propertysów
|
|
|
|
Pola z atrybutem `[Context<T>(nameof(T.Prop))]` muszą mieć właściwy typ wartości docelowej (typ
|
|
property `T.Prop`). Niezgodność → `Context.InvalidValueException` przy wywołaniu
|
|
`ContextInvoker.CreateObject<>()`.
|
|
|
|
### `StartActionInformation`
|
|
|
|
Wewnętrzny action result — uruchomienie akcji w nowym kontekście (używany przez framework
|
|
do delegowania wykonania workera). Rzadko zwracany ręcznie.
|
|
|
|
## Operacje klienta i bezpieczeństwo
|
|
|
|
### `ClientActionResult`
|
|
|
|
Wywołanie operacji w aplikacji klienckiej **SonetaFrame** (desktop wrapper). Działa tylko gdy
|
|
`BusTools.DeviceType.IsBrowserApp()`. Pozwala wykonać akcję po stronie klienta (otwarcie pliku
|
|
lokalnego, integracja z systemem operacyjnym) i opcjonalnie odebrać odpowiedź przez `ResponseHandler`.
|
|
|
|
### `MfaRequest` / `MfaSourceBase`
|
|
|
|
2FA (Multi-Factor Authentication) — uruchamia okno weryfikacji tożsamości użytkownika. Handler
|
|
deleguje do serwisu `IMfaHandleResolver`. Stosować dla akcji wymagających dodatkowego potwierdzenia.
|
|
|
|
### `ClipboardStream`
|
|
|
|
Operacja na schowku przeglądarki (kopiowanie do / odczyt z).
|
|
|
|
## Tabela szybkiego wyboru
|
|
|
|
| Co chcę zrobić | Co zwrócić |
|
|
|---|---|
|
|
| Pokazać komunikat | `string` lub `MessageBoxInformation` |
|
|
| Pokazać błąd | `Exception` (throw) lub `MessageBoxInformation` (Type = Error) |
|
|
| Zapisać/zamknąć formularz | `FormAction.Save*` / `FormAction.Close` |
|
|
| Zadać pytanie tak/nie | `MessageBoxInformation` z `YesHandler`/`NoHandler` |
|
|
| Otworzyć obiekt do edycji | sam obiekt (`Row` lub inny) |
|
|
| Otworzyć inny folder | `NavigationResult` |
|
|
| Otworzyć stronę WWW | `HyperlinkResult` |
|
|
| Pobrać plik | `NamedStream` |
|
|
| Pobrać archiwum plików | `NamedStream[]` |
|
|
| Wydruk PDF | `PdfResult` lub `PdfResult[]` |
|
|
| Raport | `ReportResult` |
|
|
| Zapytać o parametry | `QueryContextInformation` |
|
|
| Nic nie robić | `null` / `void` |
|
|
|