Zobrazení tabulek v Xamarin.Mac
Tento článek popisuje práci se zobrazeními tabulek v aplikaci Xamarin.Mac. Popisuje vytváření zobrazení tabulek v Xcode a Interface Builderu a interakci s nimi v kódu.
Při práci s jazykem C# a .NET v aplikaci Xamarin.Mac máte přístup ke stejným zobrazením tabulek, ve Objective-C kterých vývojář pracuje, a Xcode . Vzhledem k tomu, že se Xamarin.Mac integruje přímo s Xcode, můžete pomocí Tvůrce rozhraní Xcode vytvářet a udržovat zobrazení tabulky (nebo je volitelně vytvořit přímo v kódu jazyka C#).
Zobrazení tabulky zobrazuje data v tabulkovém formátu obsahujícím jeden nebo více sloupců informací v několika řádcích. Na základě typu vytvářeného zobrazení tabulky může uživatel řadit podle sloupců, měnit uspořádání sloupců, přidávat sloupce, odebírat sloupce nebo upravovat data obsažená v tabulce.
V tomto článku se podíváme na základy práce se zobrazeními tabulek v aplikaci Xamarin.Mac. Důrazně doporučujeme, abyste si nejprve prošli článek Hello, Mac , konkrétně úvod do Xcode a Tvůrce rozhraní a výstupy a akce , protože se zabývá klíčovými koncepty a technikami, které budeme používat v tomto článku.
Možná se také budete chtít podívat na oddíly v dokumentu Interní dokumenty Xamarin.Mac pro zveřejnění tříd a metod Objective-Cjazyka C#. Vysvětluje také, které Register
příkazy a Export
které se používají k připojení tříd jazyka C# k Objective-C objektům a prvkům uživatelského rozhraní.
Úvod do zobrazení tabulek
Zobrazení tabulky zobrazuje data v tabulkovém formátu obsahujícím jeden nebo více sloupců informací v několika řádcích. Zobrazení tabulky se zobrazují uvnitř zobrazení posouvání (NSScrollView
) a počínaje macOS 10.7 můžete k zobrazení řádků i sloupců použít libovolnou NSView
možnost místo buněk (NSCell
). To znamená, že můžete přesto použít NSCell
podtřídu NSTableCellView
a vytvořit vlastní řádky a sloupce.
Zobrazení tabulky neukládá vlastní data, místo toho spoléhá na zdroj dat (NSTableViewDataSource
) k poskytnutí požadovaných řádků i sloupců podle potřeby.
Chování zobrazení tabulky lze přizpůsobit tak, že poskytuje podtřídu delegáta zobrazení tabulky (NSTableViewDelegate
) pro podporu správy sloupců tabulky, typ pro výběr funkcí, výběr řádků a úpravy, vlastní sledování a vlastní zobrazení pro jednotlivé sloupce a řádky.
Při vytváření zobrazení tabulky navrhuje Apple následující:
- Umožňuje uživateli seřadit tabulku kliknutím na záhlaví sloupců.
- Vytvořte záhlaví sloupců, která jsou podstatná jména nebo krátké fráze podstatných jmen, které popisují data zobrazená v tomto sloupci.
Další informace najdete v části Zobrazení obsahu pokynů apple pro lidské rozhraní OS X.
Vytváření a údržba zobrazení tabulek v Xcode
Když vytvoříte novou aplikaci Xamarin.Mac Cocoa, ve výchozím nastavení se zobrazí standardní prázdné okno. Tato okna jsou definována .storyboard
v souboru, který je automaticky zahrnutý v projektu. Pokud chcete upravit návrh oken, poklikejte v Průzkumník řešení na Main.storyboard
soubor:
Otevře se návrh okna v Tvůrci rozhraní Xcode:
Zadejte table
do vyhledávacího pole inspektoru knihovny, abyste usnadnili vyhledání ovládacích prvků Zobrazení tabulky:
Přetáhněte zobrazení tabulky do kontroleru zobrazení v editoru rozhraní, aby vyplnil oblast obsahu kontroleru zobrazení a nastavte ho na místo, kde se zmenší a zvětší s oknem v Editoru omezení:
V hierarchii rozhraní vyberte zobrazení tabulky a v inspektoru atributů jsou k dispozici následující vlastnosti:
- Režim obsahu – Umožňuje použít zobrazení (
NSView
) nebo buňky (NSCell
) k zobrazení dat v řádcích a sloupcích. Počínaje macOS 10.7 byste měli používat zobrazení. - Plovoucí řady seskupí řádky – Pokud
true
bude zobrazení tabulky nakreslit seskupené buňky, jako by byly plovoucí. - Sloupce – definuje počet zobrazených sloupců.
- Záhlaví – Pokud
true
budou sloupce obsahovat záhlaví. - Změna pořadí – Pokud
true
bude uživatel moct přeuspořádat sloupce v tabulce. - Změna velikosti – Pokud
true
bude uživatel moct přetáhnout záhlaví sloupců, aby změnil velikost sloupců. - Nastavení velikosti sloupce – Určuje, jak bude tabulka automaticky měnit velikost sloupců.
- Zvýraznění – určuje typ zvýraznění tabulky, která se používá při výběru buňky.
- Alternativní řádky – Pokud
true
, někdy jiný řádek bude mít jinou barvu pozadí. - Vodorovná mřížka – vybere typ ohraničení nakresleného mezi buňkami vodorovně.
- Svislá mřížka – vybere typ ohraničení nakresleného mezi buňkami svisle.
- Barva mřížky – Nastaví barvu ohraničení buňky.
- Pozadí – Nastaví barvu pozadí buňky.
- Výběr – Umožňuje řídit, jak může uživatel vybrat buňky v tabulce jako:
- Násobek – Pokud
true
může uživatel vybrat více řádků a sloupců. - Sloupec – Pokud
true
uživatel může vybrat sloupce. - Zadejte Select - If
true
, uživatel může zadat znak pro výběr řádku. - Prázdné – Pokud
true
uživatel nemusí vybrat řádek nebo sloupec, tabulka neumožňuje vůbec žádný výběr.
- Násobek – Pokud
- Automatické ukládání – název, pod kterým se automaticky uloží formát tabulek.
- Informace o sloupci – Pokud
true
se pořadí a šířka sloupců automaticky uloží. - Konce řádků – Vyberte, jak buňka zpracovává konce řádků.
- Zkrátí poslední viditelnou čáru – pokud
true
se buňka zkrátí v datech, nemůže se vejít do hranic.
Důležité
Pokud si nechováte starší aplikaci Xamarin.Mac, NSView
měla by se v zobrazeních tabulek založená na základě použít NSCell
zobrazení tabulek. NSCell
se považuje za starší verzi a v budoucnu se nemusí podporovat.
V hierarchii rozhraní vyberte sloupec tabulky a v inspektoru atributů jsou k dispozici následující vlastnosti:
- Název – Nastaví název sloupce.
- Zarovnání – nastavte zarovnání textu v buňkách.
- Písmo nadpisu – vybere písmo pro text záhlaví buňky.
- Klíč řazení – je klíč použitý k řazení dat ve sloupci. Pokud uživatel nemůže tento sloupec seřadit, nechejte prázdné.
- Selektor – používá se akce k řazení. Pokud uživatel nemůže tento sloupec seřadit, nechejte prázdné.
- Pořadí – je pořadí řazení dat sloupců.
- Změna velikosti – Vybere typ změny velikosti sloupce.
- Upravitelné – Pokud
true
může uživatel upravovat buňky v tabulce založené na buňkách. - Skrytý – Pokud
true
je sloupec skrytý.
Velikost sloupce můžete změnit také přetažením úchytu (svisle na střed na pravé straně sloupce) doleva nebo doprava.
Pojďme vybrat každý sloupec v zobrazení tabulky a dát prvnímu sloupci název Product
a druhý sloupec Details
.
V hierarchii rozhraní vyberte zobrazení buňky tabulky (NSTableViewCell
) a v inspektoru atributů jsou k dispozici následující vlastnosti:
Toto jsou všechny vlastnosti standardního zobrazení. Tady máte také možnost upravit velikost řádků pro tento sloupec.
Vyberte buňku zobrazení tabulky (ve výchozím nastavení je NSTextField
to ) v hierarchii rozhraní a v inspektoru atributů jsou k dispozici následující vlastnosti:
Tady budete mít všechny vlastnosti standardního textového pole. Ve výchozím nastavení se standardní textové pole používá k zobrazení dat pro buňku ve sloupci.
V hierarchii rozhraní vyberte zobrazení buňky tabulky (NSTableFieldCell
) a v inspektoru atributů jsou k dispozici následující vlastnosti:
Nejdůležitější nastavení jsou:
- Rozložení – Vyberte způsob rozložení buněk v tomto sloupci.
- Používá režim s jedním řádkem – Pokud
true
je buňka omezena na jeden řádek. - První šířka rozložení modulu runtime – Pokud
true
bude buňka upřednostňovat šířku nastavenou (ručně nebo automaticky), když se zobrazí při prvním spuštění aplikace. - Akce – určuje, kdy se pro buňku odešle akce pro úpravy.
- Chování – definuje, jestli je buňka vybratelná nebo upravitelná.
- Formátovaný text – Pokud
true
může buňka zobrazit formátovaný a stylovaný text. - Zpět - Pokud
true
buňka přebírá odpovědnost za chování vrácení zpět.
Vyberte zobrazení buňky tabulky (NSTableFieldCell
) v dolní části sloupce tabulky v hierarchii rozhraní:
To vám umožní upravit zobrazení buněk tabulky použité jako základní vzor pro všechny buňky vytvořené pro daný sloupec.
Přidání akcí a výstupů
Stejně jako jakýkoli jiný ovládací prvek uživatelského rozhraní Cocoa potřebujeme zveřejnit zobrazení tabulky a je to sloupce a buňky kódu jazyka C# pomocí akcí a výstupů (na základě požadovaných funkcí).
Tento proces je stejný pro všechny elementy Table View, které chceme zveřejnit:
Přepněte do Editoru asistentů a ujistěte se, že
ViewController.h
je vybraný soubor:V hierarchii rozhraní vyberte zobrazení tabulky, klikněte na něj a přetáhněte ho
ViewController.h
do souboru.Vytvořte výstup pro zobrazení tabulky s názvem
ProductTable
:Vytvořit výstupy pro sloupce tabulek, které jsou také volány
ProductColumn
aDetailsColumn
:Uložte změny a vraťte se do Visual Studio pro Mac pro synchronizaci s Xcode.
V dalším kroku napíšeme kód, který při spuštění aplikace zobrazí nějaká data pro tabulku.
Naplnění zobrazení tabulky
S naším zobrazením tabulky navrženým v Tvůrci rozhraní a vystaveným prostřednictvím výstupu musíme vytvořit kód jazyka C#, který ho naplní.
Nejprve vytvoříme novou Product
třídu, která bude obsahovat informace pro jednotlivé řádky. V Průzkumník řešení klikněte pravým tlačítkem na Projekt a vyberte Přidat>nový soubor... Vyberte položku Obecné>prázdné třídy, zadejte Product
název a klikněte na tlačítko Nový:
Udělejte soubor Product.cs
takto:
using System;
namespace MacTables
{
public class Product
{
#region Computed Properties
public string Title { get; set;} = "";
public string Description { get; set;} = "";
#endregion
#region Constructors
public Product ()
{
}
public Product (string title, string description)
{
this.Title = title;
this.Description = description;
}
#endregion
}
}
Dále musíme vytvořit podtřídu, která NSTableDataSource
bude poskytovat data pro naši tabulku, jak je požadována. V Průzkumník řešení klikněte pravým tlačítkem na Projekt a vyberte Přidat>nový soubor... Vyberte Obecné>prázdné třídy, zadejte ProductTableDataSource
název a klikněte na tlačítko Nový.
ProductTableDataSource.cs
Upravte soubor a udělejte ho takto:
using System;
using AppKit;
using CoreGraphics;
using Foundation;
using System.Collections;
using System.Collections.Generic;
namespace MacTables
{
public class ProductTableDataSource : NSTableViewDataSource
{
#region Public Variables
public List<Product> Products = new List<Product>();
#endregion
#region Constructors
public ProductTableDataSource ()
{
}
#endregion
#region Override Methods
public override nint GetRowCount (NSTableView tableView)
{
return Products.Count;
}
#endregion
}
}
Tato třída má úložiště pro položky zobrazení tabulky a přepíše GetRowCount
počet řádků v tabulce.
Nakonec musíme vytvořit podtřídu, která NSTableDelegate
zajistí chování naší tabulky. V Průzkumník řešení klikněte pravým tlačítkem na Projekt a vyberte Přidat>nový soubor... Vyberte Obecné>prázdné třídy, zadejte ProductTableDelegate
název a klikněte na tlačítko Nový.
ProductTableDelegate.cs
Upravte soubor a udělejte ho takto:
using System;
using AppKit;
using CoreGraphics;
using Foundation;
using System.Collections;
using System.Collections.Generic;
namespace MacTables
{
public class ProductTableDelegate: NSTableViewDelegate
{
#region Constants
private const string CellIdentifier = "ProdCell";
#endregion
#region Private Variables
private ProductTableDataSource DataSource;
#endregion
#region Constructors
public ProductTableDelegate (ProductTableDataSource datasource)
{
this.DataSource = datasource;
}
#endregion
#region Override Methods
public override NSView GetViewForItem (NSTableView tableView, NSTableColumn tableColumn, nint row)
{
// This pattern allows you reuse existing views when they are no-longer in use.
// If the returned view is null, you instance up a new view
// If a non-null view is returned, you modify it enough to reflect the new data
NSTextField view = (NSTextField)tableView.MakeView (CellIdentifier, this);
if (view == null) {
view = new NSTextField ();
view.Identifier = CellIdentifier;
view.BackgroundColor = NSColor.Clear;
view.Bordered = false;
view.Selectable = false;
view.Editable = false;
}
// Setup view based on the column selected
switch (tableColumn.Title) {
case "Product":
view.StringValue = DataSource.Products [(int)row].Title;
break;
case "Details":
view.StringValue = DataSource.Products [(int)row].Description;
break;
}
return view;
}
#endregion
}
}
Když vytvoříme instanci objektu ProductTableDelegate
, předáme také instanci ProductTableDataSource
, která poskytuje data pro tabulku. Metoda GetViewForItem
zodpovídá za vrácení zobrazení (dat) pro zobrazení buňky pro sloupec a řádek. Pokud je to možné, existující zobrazení bude znovu použito k zobrazení buňky, pokud není nové zobrazení nutné vytvořit.
Pokud chcete naplnit tabulku, pojďme soubor upravit ViewController.cs
a nastavit, aby AwakeFromNib
metoda vypadala takto:
public override void AwakeFromNib ()
{
base.AwakeFromNib ();
// Create the Product Table Data Source and populate it
var DataSource = new ProductTableDataSource ();
DataSource.Products.Add (new Product ("Xamarin.iOS", "Allows you to develop native iOS Applications in C#"));
DataSource.Products.Add (new Product ("Xamarin.Android", "Allows you to develop native Android Applications in C#"));
DataSource.Products.Add (new Product ("Xamarin.Mac", "Allows you to develop Mac native Applications in C#"));
// Populate the Product Table
ProductTable.DataSource = DataSource;
ProductTable.Delegate = new ProductTableDelegate (DataSource);
}
Pokud spustíme aplikaci, zobrazí se následující:
Řazení podle sloupce
Umožníme uživateli seřadit data v tabulce kliknutím na záhlaví sloupce. Nejprve poklikáním na Main.storyboard
soubor otevřete soubor pro úpravy v Tvůrci rozhraní. Product
Vyberte sloupec, zadejte Title
klíč řazení, compare:
pro selektor a vyberte Ascending
pořadí:
Details
Vyberte sloupec, zadejte Description
klíč řazení, compare:
pro selektor a vyberte Ascending
pořadí:
Uložte změny a vraťte se do Visual Studio pro Mac pro synchronizaci s Xcode.
Teď soubor upravíme ProductTableDataSource.cs
a přidáme následující metody:
public void Sort(string key, bool ascending) {
// Take action based on key
switch (key) {
case "Title":
if (ascending) {
Products.Sort ((x, y) => x.Title.CompareTo (y.Title));
} else {
Products.Sort ((x, y) => -1 * x.Title.CompareTo (y.Title));
}
break;
case "Description":
if (ascending) {
Products.Sort ((x, y) => x.Description.CompareTo (y.Description));
} else {
Products.Sort ((x, y) => -1 * x.Description.CompareTo (y.Description));
}
break;
}
}
public override void SortDescriptorsChanged (NSTableView tableView, NSSortDescriptor[] oldDescriptors)
{
// Sort the data
if (oldDescriptors.Length > 0) {
// Update sort
Sort (oldDescriptors [0].Key, oldDescriptors [0].Ascending);
} else {
// Grab current descriptors and update sort
NSSortDescriptor[] tbSort = tableView.SortDescriptors;
Sort (tbSort[0].Key, tbSort[0].Ascending);
}
// Refresh table
tableView.ReloadData ();
}
Metoda Sort
nám umožňuje seřadit data ve zdroji dat na základě daného Product
pole třídy ve vzestupném nebo sestupném pořadí. Přepsaná SortDescriptorsChanged
metoda bude volána při každém kliknutí na záhlaví sloupce. Předá se hodnota Klíče , kterou jsme nastavili v Tvůrci rozhraní, a pořadí řazení pro daný sloupec.
Pokud spustíme aplikaci a klikneme na záhlaví sloupců, řádky se seřadí podle daného sloupce:
Výběr řádku
Pokud chcete uživateli povolit výběr jednoho řádku, poklikejte na soubor a otevřete ho Main.storyboard
pro úpravy v Tvůrci rozhraní. Vyberte zobrazení tabulky v hierarchii rozhraní a zrušte zaškrtnutí políčka Více v inspektoru atributů:
Uložte změny a vraťte se do Visual Studio pro Mac pro synchronizaci s Xcode.
Dále upravte ProductTableDelegate.cs
soubor a přidejte následující metodu:
public override bool ShouldSelectRow (NSTableView tableView, nint row)
{
return true;
}
To uživateli umožní vybrat libovolný jeden řádek v zobrazení tabulky. Vraťte false
se ShouldSelectRow
pro libovolný řádek, který nechcete, aby uživatel mohl vybrat nebo false
pro každý řádek, pokud nechcete, aby uživatel mohl vybrat žádné řádky.
Zobrazení tabulky (NSTableView
) obsahuje následující metody pro práci s výběrem řádku:
DeselectRow(nint)
– Zruší výběr daného řádku v tabulce.SelectRow(nint,bool)
- Vybere daný řádek. Předánífalse
druhého parametru pro výběr pouze jednoho řádku najednou.SelectedRow
– Vrátí aktuální řádek vybraný v tabulce.IsRowSelected(nint)
- Vrátítrue
, pokud je vybraný daný řádek.
Výběr více řádků
Pokud chcete uživateli povolit výběr více řádků, poklikáním Main.storyboard
otevřete soubor pro úpravy v Tvůrci rozhraní. Vyberte zobrazení tabulky v hierarchii rozhraní a zaškrtněte políčko Více v inspektoru atributů:
Uložte změny a vraťte se do Visual Studio pro Mac pro synchronizaci s Xcode.
Dále upravte ProductTableDelegate.cs
soubor a přidejte následující metodu:
public override bool ShouldSelectRow (NSTableView tableView, nint row)
{
return true;
}
To uživateli umožní vybrat libovolný jeden řádek v zobrazení tabulky. Vraťte false
se ShouldSelectRow
pro libovolný řádek, který nechcete, aby uživatel mohl vybrat nebo false
pro každý řádek, pokud nechcete, aby uživatel mohl vybrat žádné řádky.
Zobrazení tabulky (NSTableView
) obsahuje následující metody pro práci s výběrem řádku:
DeselectAll(NSObject)
– Zruší výběr všech řádků v tabulce. Sloužíthis
k odeslání prvního parametru v objektu, který provádí výběr.DeselectRow(nint)
– Zruší výběr daného řádku v tabulce.SelectAll(NSobject)
– Vybere všechny řádky v tabulce. Sloužíthis
k odeslání prvního parametru v objektu, který provádí výběr.SelectRow(nint,bool)
- Vybere daný řádek. Předání druhého parametru vymaže výběr a vybere jenom jeden řádek, předátefalse
true
ho a rozšíříte výběr a zahrnete tento řádek.SelectRows(NSIndexSet,bool)
- Vybere danou sadu řádků. Předání druhého parametru vymaže výběr a vybere jenom tyto řádky, předáfalse
setrue
pro rozšíření výběru a zahrnutí těchto řádků.SelectedRow
– Vrátí aktuální řádek vybraný v tabulce.SelectedRows
– VrátíNSIndexSet
indexy vybraných řádků.SelectedRowCount
– Vrátí počet vybraných řádků.IsRowSelected(nint)
- Vrátítrue
, pokud je vybraný daný řádek.
Typ pro výběr řádku
Pokud chcete uživateli povolit zadání znaku s vybraným zobrazením tabulky a výběrem prvního řádku s tímto znakem, poklikejte na Main.storyboard
soubor a otevřete ho pro úpravy v Tvůrci rozhraní. Vyberte zobrazení tabulky v hierarchii rozhraní a zaškrtněte políčko Vybrat typ v inspektoru atributů:
Uložte změny a vraťte se do Visual Studio pro Mac pro synchronizaci s Xcode.
Teď soubor upravíme ProductTableDelegate.cs
a přidáme následující metodu:
public override nint GetNextTypeSelectMatch (NSTableView tableView, nint startRow, nint endRow, string searchString)
{
nint row = 0;
foreach(Product product in DataSource.Products) {
if (product.Title.Contains(searchString)) return row;
// Increment row counter
++row;
}
// If not found select the first row
return 0;
}
Metoda GetNextTypeSelectMatch
vezme danou searchString
a vrátí řádek prvníhoProduct
, který má tento řetězec v něm .Title
Pokud spustíme aplikaci a zadáme znak, vybere se řádek:
Změna pořadí sloupců
Pokud chcete uživateli povolit přeuspořádání sloupců v zobrazení tabulky, poklikejte na soubor a otevřete ho Main.storyboard
pro úpravy v Tvůrci rozhraní. Vyberte zobrazení tabulky v hierarchii rozhraní a zaškrtněte políčko Změnit pořadí v inspektoru atributů:
Pokud zadáme hodnotu vlastnosti Automatické ukládání a zkontrolujeme pole Informace o sloupci, všechny změny provedené v rozložení tabulky se automaticky uloží za nás a obnoví se při příštím spuštění aplikace.
Uložte změny a vraťte se do Visual Studio pro Mac pro synchronizaci s Xcode.
Teď soubor upravíme ProductTableDelegate.cs
a přidáme následující metodu:
public override bool ShouldReorder (NSTableView tableView, nint columnIndex, nint newColumnIndex)
{
return true;
}
Metoda ShouldReorder
by měla vrátit true
pro libovolný sloupec, který chcete povolit přetáhnout do newColumnIndex
, jinak vrátit false
;
Pokud spustíme aplikaci, můžeme záhlaví sloupců přetáhnout kolem a změnit pořadí sloupců:
Úpravy buněk
Pokud chcete uživateli povolit úpravy hodnot pro danou buňku, upravte ProductTableDelegate.cs
soubor a změňte metodu GetViewForItem
následujícím způsobem:
public override NSView GetViewForItem (NSTableView tableView, NSTableColumn tableColumn, nint row)
{
// This pattern allows you reuse existing views when they are no-longer in use.
// If the returned view is null, you instance up a new view
// If a non-null view is returned, you modify it enough to reflect the new data
NSTextField view = (NSTextField)tableView.MakeView (tableColumn.Title, this);
if (view == null) {
view = new NSTextField ();
view.Identifier = tableColumn.Title;
view.BackgroundColor = NSColor.Clear;
view.Bordered = false;
view.Selectable = false;
view.Editable = true;
view.EditingEnded += (sender, e) => {
// Take action based on type
switch(view.Identifier) {
case "Product":
DataSource.Products [(int)view.Tag].Title = view.StringValue;
break;
case "Details":
DataSource.Products [(int)view.Tag].Description = view.StringValue;
break;
}
};
}
// Tag view
view.Tag = row;
// Setup view based on the column selected
switch (tableColumn.Title) {
case "Product":
view.StringValue = DataSource.Products [(int)row].Title;
break;
case "Details":
view.StringValue = DataSource.Products [(int)row].Description;
break;
}
return view;
}
Když teď spustíme aplikaci, uživatel může upravit buňky v zobrazení tabulky:
Použití obrázků v zobrazeních tabulek
Pokud chcete do buňky zahrnout obrázek jako NSTableView
součást buňky, budete muset změnit způsob, jakým jsou data vrácena metodou Zobrazení GetViewForItem
NSTableViewDelegate's
tabulky, aby místo NSTableCellView
typického NSTextField
. Příklad:
public override NSView GetViewForItem (NSTableView tableView, NSTableColumn tableColumn, nint row)
{
// This pattern allows you reuse existing views when they are no-longer in use.
// If the returned view is null, you instance up a new view
// If a non-null view is returned, you modify it enough to reflect the new data
NSTableCellView view = (NSTableCellView)tableView.MakeView (tableColumn.Title, this);
if (view == null) {
view = new NSTableCellView ();
if (tableColumn.Title == "Product") {
view.ImageView = new NSImageView (new CGRect (0, 0, 16, 16));
view.AddSubview (view.ImageView);
view.TextField = new NSTextField (new CGRect (20, 0, 400, 16));
} else {
view.TextField = new NSTextField (new CGRect (0, 0, 400, 16));
}
view.TextField.AutoresizingMask = NSViewResizingMask.WidthSizable;
view.AddSubview (view.TextField);
view.Identifier = tableColumn.Title;
view.TextField.BackgroundColor = NSColor.Clear;
view.TextField.Bordered = false;
view.TextField.Selectable = false;
view.TextField.Editable = true;
view.TextField.EditingEnded += (sender, e) => {
// Take action based on type
switch(view.Identifier) {
case "Product":
DataSource.Products [(int)view.TextField.Tag].Title = view.TextField.StringValue;
break;
case "Details":
DataSource.Products [(int)view.TextField.Tag].Description = view.TextField.StringValue;
break;
}
};
}
// Tag view
view.TextField.Tag = row;
// Setup view based on the column selected
switch (tableColumn.Title) {
case "Product":
view.ImageView.Image = NSImage.ImageNamed ("tags.png");
view.TextField.StringValue = DataSource.Products [(int)row].Title;
break;
case "Details":
view.TextField.StringValue = DataSource.Products [(int)row].Description;
break;
}
return view;
}
Další informace najdete v části Použití obrázků se zobrazeními tabulek v naší dokumentaci Práce s obrázky .
Přidání tlačítka Odstranit na řádek
V závislosti na požadavcích aplikace můžou nastat situace, kdy potřebujete zadat tlačítko akce pro každý řádek v tabulce. V příkladu tohoto příkladu rozbalme výše vytvořený příklad zobrazení tabulky, abychom na každém řádku zahrnuli tlačítko Odstranit .
Nejprve upravte Main.storyboard
Tvůrce rozhraní Xcode, vyberte zobrazení tabulky a zvyšte počet sloupců na tři (3). Dále změňte název nového sloupce na Action
:
Uložte změny do scénáře a vraťte se do Visual Studio pro Mac, aby se změny synchronizovaly.
Dále upravte ViewController.cs
soubor a přidejte následující veřejnou metodu:
public void ReloadTable ()
{
ProductTable.ReloadData ();
}
Ve stejném souboru upravte vytvoření nového delegáta zobrazení tabulky uvnitř ViewDidLoad
metody následujícím způsobem:
// Populate the Product Table
ProductTable.DataSource = DataSource;
ProductTable.Delegate = new ProductTableDelegate (this, DataSource);
Teď upravte ProductTableDelegate.cs
soubor tak, aby zahrnoval privátní připojení k řadiči zobrazení a při vytváření nové instance delegáta převezměte kontroler jako parametr:
#region Private Variables
private ProductTableDataSource DataSource;
private ViewController Controller;
#endregion
#region Constructors
public ProductTableDelegate (ViewController controller, ProductTableDataSource datasource)
{
this.Controller = controller;
this.DataSource = datasource;
}
#endregion
Dále do třídy přidejte následující novou privátní metodu:
private void ConfigureTextField (NSTableCellView view, nint row)
{
// Add to view
view.TextField.AutoresizingMask = NSViewResizingMask.WidthSizable;
view.AddSubview (view.TextField);
// Configure
view.TextField.BackgroundColor = NSColor.Clear;
view.TextField.Bordered = false;
view.TextField.Selectable = false;
view.TextField.Editable = true;
// Wireup events
view.TextField.EditingEnded += (sender, e) => {
// Take action based on type
switch (view.Identifier) {
case "Product":
DataSource.Products [(int)view.TextField.Tag].Title = view.TextField.StringValue;
break;
case "Details":
DataSource.Products [(int)view.TextField.Tag].Description = view.TextField.StringValue;
break;
}
};
// Tag view
view.TextField.Tag = row;
}
To přebírá všechny konfigurace textového zobrazení, které byly provedeny v GetViewForItem
metodě a umístí je do jediného volatelného umístění (od posledního sloupce tabulky neobsahuje textové zobrazení, ale tlačítko).
Nakonec upravte metodu GetViewForItem
a nastavte ji jako následující:
public override NSView GetViewForItem (NSTableView tableView, NSTableColumn tableColumn, nint row)
{
// This pattern allows you reuse existing views when they are no-longer in use.
// If the returned view is null, you instance up a new view
// If a non-null view is returned, you modify it enough to reflect the new data
NSTableCellView view = (NSTableCellView)tableView.MakeView (tableColumn.Title, this);
if (view == null) {
view = new NSTableCellView ();
// Configure the view
view.Identifier = tableColumn.Title;
// Take action based on title
switch (tableColumn.Title) {
case "Product":
view.ImageView = new NSImageView (new CGRect (0, 0, 16, 16));
view.AddSubview (view.ImageView);
view.TextField = new NSTextField (new CGRect (20, 0, 400, 16));
ConfigureTextField (view, row);
break;
case "Details":
view.TextField = new NSTextField (new CGRect (0, 0, 400, 16));
ConfigureTextField (view, row);
break;
case "Action":
// Create new button
var button = new NSButton (new CGRect (0, 0, 81, 16));
button.SetButtonType (NSButtonType.MomentaryPushIn);
button.Title = "Delete";
button.Tag = row;
// Wireup events
button.Activated += (sender, e) => {
// Get button and product
var btn = sender as NSButton;
var product = DataSource.Products [(int)btn.Tag];
// Configure alert
var alert = new NSAlert () {
AlertStyle = NSAlertStyle.Informational,
InformativeText = $"Are you sure you want to delete {product.Title}? This operation cannot be undone.",
MessageText = $"Delete {product.Title}?",
};
alert.AddButton ("Cancel");
alert.AddButton ("Delete");
alert.BeginSheetForResponse (Controller.View.Window, (result) => {
// Should we delete the requested row?
if (result == 1001) {
// Remove the given row from the dataset
DataSource.Products.RemoveAt((int)btn.Tag);
Controller.ReloadTable ();
}
});
};
// Add to view
view.AddSubview (button);
break;
}
}
// Setup view based on the column selected
switch (tableColumn.Title) {
case "Product":
view.ImageView.Image = NSImage.ImageNamed ("tag.png");
view.TextField.StringValue = DataSource.Products [(int)row].Title;
view.TextField.Tag = row;
break;
case "Details":
view.TextField.StringValue = DataSource.Products [(int)row].Description;
view.TextField.Tag = row;
break;
case "Action":
foreach (NSView subview in view.Subviews) {
var btn = subview as NSButton;
if (btn != null) {
btn.Tag = row;
}
}
break;
}
return view;
}
Pojďme se podrobněji podívat na několik částí tohoto kódu. Nejprve se provede nová NSTableViewCell
akce na základě názvu sloupce. Pro první dva sloupce (Product a Details) se volá nová ConfigureTextField
metoda.
Pro sloupec Akce se vytvoří nový NSButton
a přidá se do buňky jako dílčí zobrazení:
// Create new button
var button = new NSButton (new CGRect (0, 0, 81, 16));
button.SetButtonType (NSButtonType.MomentaryPushIn);
button.Title = "Delete";
button.Tag = row;
...
// Add to view
view.AddSubview (button);
Vlastnost Button Tag
slouží k uložení počtu zpracovávaných řádků. Toto číslo se použije později, když uživatel požádá o odstranění řádku v události tlačítka Activated
:
// Wireup events
button.Activated += (sender, e) => {
// Get button and product
var btn = sender as NSButton;
var product = DataSource.Products [(int)btn.Tag];
// Configure alert
var alert = new NSAlert () {
AlertStyle = NSAlertStyle.Informational,
InformativeText = $"Are you sure you want to delete {product.Title}? This operation cannot be undone.",
MessageText = $"Delete {product.Title}?",
};
alert.AddButton ("Cancel");
alert.AddButton ("Delete");
alert.BeginSheetForResponse (Controller.View.Window, (result) => {
// Should we delete the requested row?
if (result == 1001) {
// Remove the given row from the dataset
DataSource.Products.RemoveAt((int)btn.Tag);
Controller.ReloadTable ();
}
});
};
Na začátku obslužné rutiny události získáme tlačítko a produkt, který je na daném řádku tabulky. Uživateli, který potvrdí odstranění řádku, se zobrazí výstraha. Pokud se uživatel rozhodne řádek odstranit, daný řádek se odebere ze zdroje dat a tabulka se znovu načte:
// Remove the given row from the dataset
DataSource.Products.RemoveAt((int)btn.Tag);
Controller.ReloadTable ();
A konečně, pokud se buňka zobrazení tabulky místo vytváření nových znovu používá, nakonfiguruje ji následující kód na základě zpracovávaného sloupce:
// Setup view based on the column selected
switch (tableColumn.Title) {
case "Product":
view.ImageView.Image = NSImage.ImageNamed ("tag.png");
view.TextField.StringValue = DataSource.Products [(int)row].Title;
view.TextField.Tag = row;
break;
case "Details":
view.TextField.StringValue = DataSource.Products [(int)row].Description;
view.TextField.Tag = row;
break;
case "Action":
foreach (NSView subview in view.Subviews) {
var btn = subview as NSButton;
if (btn != null) {
btn.Tag = row;
}
}
break;
}
U sloupce Akce jsou všechna dílčí zobrazení prohledávána, dokud NSButton
se nenajde, a pak se Tag
vlastnost aktualizuje tak, aby ukazovala na aktuální řádek.
Po provedení těchto změn bude mít aplikace při každém spuštění každého řádku tlačítko Odstranit :
Když uživatel klikne na tlačítko Odstranit , zobrazí se upozornění s žádostí o odstranění daného řádku:
Pokud uživatel zvolí odstranění, řádek se odebere a tabulka se překreslí:
Zobrazení tabulky datových vazeb
Pomocí technik kódování klíč-hodnota a datové vazby v aplikaci Xamarin.Mac můžete výrazně snížit množství kódu, který musíte napsat a udržovat pro naplnění a práci s prvky uživatelského rozhraní. Výhodou je také další oddělení backingových dat (datový model) od front-endového uživatelského rozhraní (Model-View-Controller), což usnadňuje údržbu a flexibilnější návrh aplikace.
Kódování klíč-hodnota (KVC) je mechanismus pro přístup k vlastnostem objektu nepřímo pomocí klíčů (speciálně formátovaných řetězců) k identifikaci vlastností místo přístupu prostřednictvím proměnných instancí nebo metod přístupového objektu (get/set
). Implementací přístupových objektů kompatibilních s kódováním klíč-hodnota v aplikaci Xamarin.Mac získáte přístup k dalším funkcím systému macOS, jako je KVO (Key-Value Observing), Datová vazba, Základní data, vazby Cocoa a skriptovatelnost.
Další informace najdete v části Datové vazby zobrazení tabulky v dokumentaci k datovým vazbě a kódování klíč-hodnota.
Shrnutí
Tento článek se podrobně podíval na práci se zobrazeními tabulek v aplikaci Xamarin.Mac. Viděli jsme různé typy a použití zobrazení tabulek, jak vytvářet a udržovat zobrazení tabulky v Tvůrci rozhraní Xcode a jak pracovat se zobrazeními tabulek v kódu jazyka C#.