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 Tvůrci rozhraní a interakci s nimi v kódu.
Při práci s C# a .NET v aplikaci Xamarin.Mac máte přístup ke stejným zobrazením tabulek, ve kterých vývojář pracuje Objective-C , a Xcode . Vzhledem k tomu, že Xamarin.Mac se integruje přímo s Xcode, můžete pomocí Tvůrce rozhraní Xcode vytvářet a udržovat zobrazení tabulek (nebo je volitelně vytvářet 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 vytvořeného zobrazení tabulky může uživatel řadit podle sloupců, změnit uspořádání sloupců, přidat sloupce, odebrat sloupce nebo upravit 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 nejprve projít si článek Hello, Mac , konkrétně úvod do Xcode a Interface Builder aOutlets and Actions oddíly, protože se zabývá klíčovými koncepty a technikami, které budeme používat v tomto článku.
Můžete se také podívat na třídy / metody pro zveřejnění kódu jazyka C# v Objective-C části dokumentu Interní dokumenty Xamarin.Mac , vysvětluje Register
a Export
příkazy používané k převodu tříd jazyka C# na Objective-C objekty a prvky 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 místo buněk (NSCell
) zobrazit NSView
řádky i sloupce. To znamená, že stále můžete použít NSCell
, ale obvykle podtřídu NSTableCellView
a vytvoříte 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 tím, ž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í tabulek Apple navrhuje následující:
- Umožňuje uživateli seřadit tabulku kliknutím na záhlaví sloupců.
- Vytvořte záhlaví sloupců, která jsou jmenná jména nebo krátké fráze jmen, které popisují data zobrazená v tomto sloupci.
Další informace najdete v části Zobrazení obsahuv pokynech pro lidské rozhraní společnosti Apple oS X.
Vytváření a údržba zobrazení tabulek v Xcode
Když vytvoříte novou aplikaci Xamarin.Mac Cocoa, ve výchozím nastavení získáte standardní prázdné okno. Tato okna jsou definována .storyboard
v souboru automaticky zahrnuté v projektu. Pokud chcete upravit návrh oken, poklikejte v Průzkumník řešení na Main.storyboard
soubor:
Tím se otevře 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 na kontroler zobrazení v editoru rozhraní, aby vyplnil oblast obsahu kontroleru zobrazení a nastavte ho na místo, kam se zmenší a zvětší s oknem v Editoru omezení:
Vyberte zobrazení tabulky v hierarchii rozhraní a v inspektoru atributů jsou k dispozici následující vlastnosti:
- Režim obsahu – Umožňuje použít zobrazení () nebo buňky (
NSView
NSCell
) k zobrazení dat v řádcích a sloupcích. Počínaje macOS 10.7 byste měli používat zobrazení. - Floats Seskupuje řádky – Pokud
true
, bude zobrazení tabulky kreslit seskupené buňky, jako by byly plovoucí. - Sloupce – Definuje počet zobrazených sloupců.
- Záhlaví – Pokud
true
sloupce budou obsahovat záhlaví. - Změna pořadí – Pokud
true
, uživatel bude moct přetáhnout sloupce v tabulce. - Změna velikosti – Pokud
true
bude uživatel moct přetáhnout záhlaví sloupců, aby změnil velikost sloupců. - Změna velikosti sloupců – 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:
- Více – Pokud
true
může uživatel vybrat více řádků a sloupců. - Sloupec – Pokud
true
uživatel může vybrat sloupce. - Typ Vybrat – Pokud
true
může uživatel 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.
- Více – Pokud
- Automatické ukládání – název, pod kterým se formát tabulek automaticky uloží.
- 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 nechováte starší verzi aplikace Xamarin.Mac, NSView
měla by se zobrazení tabulek používat na NSCell
základě zobrazení tabulek. NSCell
je považováno za starší verzi a nemusí být podporováno v budoucnu.
Vyberte sloupec tabulky v hierarchii rozhraní 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, ponechejte prázdné.
- Selektor – jedná se o akci použitou k provedení řazení. Pokud uživatel nemůže tento sloupec seřadit, ponechejte prázdné.
- Pořadí – je pořadí řazení pro data 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ňce. - Skryté – Pokud
true
je sloupec skrytý.
Můžete také změnit velikost sloupce přetažením úchytu (svisle na střed na pravé straně sloupce) doleva nebo doprava.
Pojďme vybrat každý sloupec v našem zobrazení tabulky a dát první sloupec názevProduct
a druhý sloupec Details
.
V hierarchii rozhraní vyberte zobrazení buněk tabulky (NSTableViewCell
) a v inspektoru atributů jsou k dispozici následující vlastnosti:
Jedná se o všechny vlastnosti standardního zobrazení. Tady máte také možnost změnit velikost řádků pro tento sloupec.
Vyberte buňku zobrazení tabulky (ve výchozím nastavení je to NSTextField
) v hierarchii rozhraní a v inspektoru atributů jsou k dispozici následující vlastnosti:
Budete mít všechny vlastnosti standardního textového pole, které se tady nastaví. Ve výchozím nastavení se standardní textové pole používá k zobrazení dat pro buňku ve sloupci.
V hierarchii rozhraní vyberte zobrazení buněk 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 jednořádkového řádku – 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 (buď 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í zpět.
Vyberte zobrazení buněk tabulky (NSTableFieldCell
) v dolní části sloupce tabulky v hierarchii rozhraní:
To umožňuje upravit zobrazení buňky tabulky použité jako základní vzor pro všechny buňky vytvořené pro daný sloupec.
Přidání akcí a zásuvek
Stejně jako jakýkoli jiný ovládací prvek uživatelského rozhraní Cocoa musíme vystavit 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í).
Proces je stejný pro libovolný prvek Zobrazení tabulky, který chceme vystavit:
Přepněte do Editoru asistentů a ujistěte se, že
ViewController.h
je soubor vybraný:V hierarchii rozhraní vyberte zobrazení tabulky, klikněte na něj a přetáhněte ho
ViewController.h
do souboru.Vytvořte zásuvku pro zobrazení tabulky s názvem
ProductTable
:Vytvořte zásuvky pro sloupce tabulek a také volejte
ProductColumn
aDetailsColumn
:Uložte změny a vraťte se do Visual Studio pro Mac pro synchronizaci s Xcode.
Dále napíšeme kód, který zobrazí některá data tabulky při spuštění aplikace.
Naplnění zobrazení tabulky
S naším zobrazením tabulky navrženým v Tvůrci rozhraní a vystaveným prostřednictvím zásuvky 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 Project a vyberte AddNew>File... Vyberte Třídu GeneralEmpty>, 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 Project a vyberte AddNew>File... Vyberte TříduGeneralEmpty>, 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
, aby vrátil počet řádků v tabulce.
Nakonec musíme vytvořit podtřídu NSTableDelegate
, která bude poskytovat chování pro naši tabulku. V Průzkumník řešení klikněte pravým tlačítkem na Project a vyberte AddNew>File... Vyberte TříduGeneralEmpty>, 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. Tato GetViewForItem
metoda zodpovídá za vrácení zobrazení (dat) k zobrazení buňky pro sloupec a řádek. Pokud je to možné, bude existující zobrazení znovu použito k zobrazení buňky, pokud není nové zobrazení nutné vytvořit.
Pokud chcete vyplnit tabulku, upravme ViewController.cs
soubor a udělejte metodu AwakeFromNib
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 ř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 vzestupně nebo sestupně. Přepsaná SortDescriptorsChanged
metoda bude volána při každém kliknutí na záhlaví sloupce. Předá se hodnota Klíč , 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 pro ShouldSelectRow
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 řádků:
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 najednouSelectedRow
- 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ů, 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 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 pro ShouldSelectRow
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 řádků:
DeselectAll(NSObject)
– Zruší výběr všech řádků v tabulce. Sloužíthis
k odeslání prvního parametru do 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 do objektu, který provádí výběr.SelectRow(nint,bool)
- Vybere daný řádek. Předánífalse
druhého parametru vymaže výběr a vybere jenom jeden řádek, předejtetrue
výběr a tento řádek zahrňte.SelectRows(NSIndexSet,bool)
- Vybere danou sadu řádků. Předejtefalse
druhý parametr vymažte výběr a vyberte pouze tyto řádky, předejte výběr a zahrňtetrue
tyto řádky.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 povolit uživateli zadat znak s vybraným zobrazením tabulky a vybrat první řádek 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ího Product
, 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řetahová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ého ukládání a zkontrolujeme pole Informace o sloupci , všechny změny provedené v rozložení tabulky se automaticky uloží pro 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 newColumnIndex
do , jinak vrátit false
;
Pokud spustíme aplikaci, můžeme přetáhnout záhlaví sloupců kolem a změnit pořadí sloupců:
Úpravy buněk
Pokud chcete uživateli povolit úpravu 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ď aplikaci spustíme, může uživatel upravit buňky v zobrazení tabulky:
Použití obrázků v zobrazeních tabulek
Pokud chcete do buňky zahrnout obrázek jako součást buňkyNSTableView
, musíte změnit způsob vrácení dat metodou zobrazeníGetViewForItem
NSTableViewDelegate's
tabulky tak, aby se místo typického objektu používala NSTableCellView
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žívání obrázků se zobrazeními tabulek v naší dokumentaci k práci s obrázkem .
Přidání tlačítka Odstranit na řádek
Na základě požadavků vaší aplikace můžou nastat situace, kdy potřebujete zadat tlačítko akce pro každý řádek v tabulce. V tomto příkladu rozbalme příklad zobrazení tabulky vytvořený výše, abychom do každého řá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). V dalším kroku 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 zobrazení textu, které byly dříve 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 udělejte ji takto:
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, pokud se vytvoří nová NSTableViewCell
akce založená na 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
se používá k uložení čísla řádku, který se právě zpracovává. 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 ();
Pokud se buňka zobrazení tabulky místo vytvoření nové 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 se zkontrolují všechna dílčí zobrazení, dokud se nenajde NSButton
, a vlastnost Tag
se 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í Key-Value kódování a datových vazeb v aplikaci Xamarin.Mac můžete výrazně snížit množství kódu, který musíte psát 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 aplikací.
Key-Value Kódování (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 k nim prostřednictvím proměnných instancí nebo metod přístupových objektů (get/set
). Implementací Key-Value přístupových objektů kompatibilních s kódováním v aplikaci Xamarin.Mac získáte přístup k dalším funkcím macOS, jako jsou Key-Value Observing (KVO), datové vazby, základní data, vazby Cocoa a skriptovatelnost.
Další informace najdete v části Datové vazby zobrazení tabulky v dokumentaci k datové vazbě a Key-Value kódování .
Souhrn
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í tabulek v Tvůrci rozhraní Xcode a jak pracovat se zobrazeními tabulek v kódu jazyka C#.