Elenchi di origine in Xamarin.Mac
Questo articolo illustra l'uso degli elenchi di origine in un'applicazione Xamarin.Mac. Descrive la creazione e la gestione di elenchi di origine in Xcode e Interface Builder e l'interazione con essi nel codice C#.
Quando si lavora con C# e .NET in un'applicazione Xamarin.Mac, è possibile accedere agli stessi elenchi di origine in Objective-C cui uno sviluppatore lavora e Xcode . Poiché Xamarin.Mac si integra direttamente con Xcode, è possibile usare Interface Builder di Xcode per creare e gestire gli elenchi di origine (o, facoltativamente, crearli direttamente nel codice C#).
Un elenco di origine è un tipo speciale di Visualizzazione struttura usato per mostrare l'origine di un'azione, ad esempio la barra laterale in Finder o iTunes.
In questo articolo verranno illustrate le nozioni di base sull'uso degli elenchi di origine in un'applicazione Xamarin.Mac. È consigliabile usare prima di tutto l'articolo Hello, Mac , in particolare le sezioni Introduzione a Xcode e Interface Builder e Outlet e Actions , in quanto illustra i concetti e le tecniche chiave che verranno usati in questo articolo.
È possibile esaminare anche la sezione Esposizione di classi/metodi C# al Objective-Cdocumento Internals di Xamarin.Mac, che illustra anche i Register
comandi e Export
usati per collegare le classi C# agli oggetti e agli Objective-C elementi dell'interfaccia utente.
Introduzione agli elenchi di origine
Come indicato in precedenza, un elenco di origine è un tipo speciale di Visualizzazione struttura usato per mostrare l'origine di un'azione, ad esempio la barra laterale in Finder o iTunes. Un elenco di origine è un tipo di tabella che consente all'utente di espandere o comprimere righe di dati gerarchici. A differenza di una visualizzazione tabella, gli elementi di un elenco di origine non sono inclusi in un elenco semplice, sono organizzati in una gerarchia, ad esempio file e cartelle su un disco rigido. Se un elemento in un elenco di origine contiene altri elementi, può essere espanso o compresso dall'utente.
L'elenco di origine è una visualizzazione struttura in stile speciale (NSOutlineView
), che è una sottoclasse della vista tabella (NSTableView
) e, di conseguenza, eredita gran parte del comportamento dalla relativa classe padre. Di conseguenza, molte operazioni supportate da una visualizzazione struttura sono supportate anche da un elenco di origine. Un'applicazione Xamarin.Mac ha il controllo di queste funzionalità e può configurare i parametri dell'elenco di origine (nel codice o in Interface Builder) per consentire o impedire determinate operazioni.
Un elenco di origini non archivia i propri dati, ma si basa su un'origine dati (NSOutlineViewDataSource
) per fornire sia le righe che le colonne necessarie, in base alle esigenze.
Il comportamento di un elenco di origine può essere personalizzato fornendo una sottoclasse del delegato visualizzazione struttura (NSOutlineViewDelegate
) per supportare il tipo struttura per selezionare funzionalità, selezione degli elementi e modifica, rilevamento personalizzato e visualizzazioni personalizzate per singoli elementi.
Poiché un elenco di origine condivide gran parte del comportamento e delle funzionalità con una visualizzazione tabella e una visualizzazione struttura, è consigliabile esaminare la documentazione visualizzazioni tabella e visualizzazioni struttura prima di continuare con questo articolo.
Utilizzo degli elenchi di origine
Un elenco di origine è un tipo speciale di Visualizzazione struttura usato per mostrare l'origine di un'azione, ad esempio la barra laterale in Finder o iTunes. A differenza delle visualizzazioni struttura, prima di definire l'elenco di origine in Interface Builder, creare le classi di backup in Xamarin.Mac.
Creare prima di tutto una nuova SourceListItem
classe per contenere i dati per l'elenco di origine. Nella Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto e scegliere Aggiungi>nuovo file... Selezionare General Empty Class (Classe vuota generale>), immettere SourceListItem
per Name (Nome) e fare clic sul pulsante New (Nuovo):
Fare in modo che il SourceListItem.cs
file sia simile al seguente:
using System;
using System.Collections;
using System.Collections.Generic;
using AppKit;
using Foundation;
namespace MacOutlines
{
public class SourceListItem: NSObject, IEnumerator, IEnumerable
{
#region Private Properties
private string _title;
private NSImage _icon;
private string _tag;
private List<SourceListItem> _items = new List<SourceListItem> ();
#endregion
#region Computed Properties
public string Title {
get { return _title; }
set { _title = value; }
}
public NSImage Icon {
get { return _icon; }
set { _icon = value; }
}
public string Tag {
get { return _tag; }
set { _tag=value; }
}
#endregion
#region Indexer
public SourceListItem this[int index]
{
get
{
return _items[index];
}
set
{
_items[index] = value;
}
}
public int Count {
get { return _items.Count; }
}
public bool HasChildren {
get { return (Count > 0); }
}
#endregion
#region Enumerable Routines
private int _position = -1;
public IEnumerator GetEnumerator()
{
_position = -1;
return (IEnumerator)this;
}
public bool MoveNext()
{
_position++;
return (_position < _items.Count);
}
public void Reset()
{_position = -1;}
public object Current
{
get
{
try
{
return _items[_position];
}
catch (IndexOutOfRangeException)
{
throw new InvalidOperationException();
}
}
}
#endregion
#region Constructors
public SourceListItem ()
{
}
public SourceListItem (string title)
{
// Initialize
this._title = title;
}
public SourceListItem (string title, string icon)
{
// Initialize
this._title = title;
this._icon = NSImage.ImageNamed (icon);
}
public SourceListItem (string title, string icon, ClickedDelegate clicked)
{
// Initialize
this._title = title;
this._icon = NSImage.ImageNamed (icon);
this.Clicked = clicked;
}
public SourceListItem (string title, NSImage icon)
{
// Initialize
this._title = title;
this._icon = icon;
}
public SourceListItem (string title, NSImage icon, ClickedDelegate clicked)
{
// Initialize
this._title = title;
this._icon = icon;
this.Clicked = clicked;
}
public SourceListItem (string title, NSImage icon, string tag)
{
// Initialize
this._title = title;
this._icon = icon;
this._tag = tag;
}
public SourceListItem (string title, NSImage icon, string tag, ClickedDelegate clicked)
{
// Initialize
this._title = title;
this._icon = icon;
this._tag = tag;
this.Clicked = clicked;
}
#endregion
#region Public Methods
public void AddItem(SourceListItem item) {
_items.Add (item);
}
public void AddItem(string title) {
_items.Add (new SourceListItem (title));
}
public void AddItem(string title, string icon) {
_items.Add (new SourceListItem (title, icon));
}
public void AddItem(string title, string icon, ClickedDelegate clicked) {
_items.Add (new SourceListItem (title, icon, clicked));
}
public void AddItem(string title, NSImage icon) {
_items.Add (new SourceListItem (title, icon));
}
public void AddItem(string title, NSImage icon, ClickedDelegate clicked) {
_items.Add (new SourceListItem (title, icon, clicked));
}
public void AddItem(string title, NSImage icon, string tag) {
_items.Add (new SourceListItem (title, icon, tag));
}
public void AddItem(string title, NSImage icon, string tag, ClickedDelegate clicked) {
_items.Add (new SourceListItem (title, icon, tag, clicked));
}
public void Insert(int n, SourceListItem item) {
_items.Insert (n, item);
}
public void RemoveItem(SourceListItem item) {
_items.Remove (item);
}
public void RemoveItem(int n) {
_items.RemoveAt (n);
}
public void Clear() {
_items.Clear ();
}
#endregion
#region Events
public delegate void ClickedDelegate();
public event ClickedDelegate Clicked;
internal void RaiseClickedEvent() {
// Inform caller
if (this.Clicked != null)
this.Clicked ();
}
#endregion
}
}
Nella Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto e scegliere Aggiungi>nuovo file... Selezionare General Empty Class (Classe vuota Generale>), immettere SourceListDataSource
per Name (Nome) e fare clic sul pulsante New (Nuovo). Fare in modo che il SourceListDataSource.cs
file sia simile al seguente:
using System;
using System.Collections;
using System.Collections.Generic;
using AppKit;
using Foundation;
namespace MacOutlines
{
public class SourceListDataSource : NSOutlineViewDataSource
{
#region Private Variables
private SourceListView _controller;
#endregion
#region Public Variables
public List<SourceListItem> Items = new List<SourceListItem>();
#endregion
#region Constructors
public SourceListDataSource (SourceListView controller)
{
// Initialize
this._controller = controller;
}
#endregion
#region Override Properties
public override nint GetChildrenCount (NSOutlineView outlineView, Foundation.NSObject item)
{
if (item == null) {
return Items.Count;
} else {
return ((SourceListItem)item).Count;
}
}
public override bool ItemExpandable (NSOutlineView outlineView, Foundation.NSObject item)
{
return ((SourceListItem)item).HasChildren;
}
public override NSObject GetChild (NSOutlineView outlineView, nint childIndex, Foundation.NSObject item)
{
if (item == null) {
return Items [(int)childIndex];
} else {
return ((SourceListItem)item) [(int)childIndex];
}
}
public override NSObject GetObjectValue (NSOutlineView outlineView, NSTableColumn tableColumn, NSObject item)
{
return new NSString (((SourceListItem)item).Title);
}
#endregion
#region Internal Methods
internal SourceListItem ItemForRow(int row) {
int index = 0;
// Look at each group
foreach (SourceListItem item in Items) {
// Is the row inside this group?
if (row >= index && row <= (index + item.Count)) {
return item [row - index - 1];
}
// Move index
index += item.Count + 1;
}
// Not found
return null;
}
#endregion
}
}
Verranno forniti i dati per l'elenco di origine.
Nella Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto e scegliere Aggiungi>nuovo file... Selezionare General Empty Class (Classe vuota Generale>), immettere SourceListDelegate
per Name (Nome) e fare clic sul pulsante New (Nuovo). Fare in modo che il SourceListDelegate.cs
file sia simile al seguente:
using System;
using AppKit;
using Foundation;
namespace MacOutlines
{
public class SourceListDelegate : NSOutlineViewDelegate
{
#region Private variables
private SourceListView _controller;
#endregion
#region Constructors
public SourceListDelegate (SourceListView controller)
{
// Initialize
this._controller = controller;
}
#endregion
#region Override Methods
public override bool ShouldEditTableColumn (NSOutlineView outlineView, NSTableColumn tableColumn, Foundation.NSObject item)
{
return false;
}
public override NSCell GetCell (NSOutlineView outlineView, NSTableColumn tableColumn, Foundation.NSObject item)
{
nint row = outlineView.RowForItem (item);
return tableColumn.DataCellForRow (row);
}
public override bool IsGroupItem (NSOutlineView outlineView, Foundation.NSObject item)
{
return ((SourceListItem)item).HasChildren;
}
public override NSView GetView (NSOutlineView outlineView, NSTableColumn tableColumn, NSObject item)
{
NSTableCellView view = null;
// Is this a group item?
if (((SourceListItem)item).HasChildren) {
view = (NSTableCellView)outlineView.MakeView ("HeaderCell", this);
} else {
view = (NSTableCellView)outlineView.MakeView ("DataCell", this);
view.ImageView.Image = ((SourceListItem)item).Icon;
}
// Initialize view
view.TextField.StringValue = ((SourceListItem)item).Title;
// Return new view
return view;
}
public override bool ShouldSelectItem (NSOutlineView outlineView, Foundation.NSObject item)
{
return (outlineView.GetParent (item) != null);
}
public override void SelectionDidChange (NSNotification notification)
{
NSIndexSet selectedIndexes = _controller.SelectedRows;
// More than one item selected?
if (selectedIndexes.Count > 1) {
// Not handling this case
} else {
// Grab the item
var item = _controller.Data.ItemForRow ((int)selectedIndexes.FirstIndex);
// Was an item found?
if (item != null) {
// Fire the clicked event for the item
item.RaiseClickedEvent ();
// Inform caller of selection
_controller.RaiseItemSelected (item);
}
}
}
#endregion
}
}
In questo modo verrà fornito il comportamento dell'elenco di origine.
Infine, nella Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto e scegliere Aggiungi>nuovo file... Selezionare General Empty Class (Classe vuota Generale>), immettere SourceListView
per Name (Nome) e fare clic sul pulsante New (Nuovo). Fare in modo che il SourceListView.cs
file sia simile al seguente:
using System;
using AppKit;
using Foundation;
namespace MacOutlines
{
[Register("SourceListView")]
public class SourceListView : NSOutlineView
{
#region Computed Properties
public SourceListDataSource Data {
get {return (SourceListDataSource)this.DataSource; }
}
#endregion
#region Constructors
public SourceListView ()
{
}
public SourceListView (IntPtr handle) : base(handle)
{
}
public SourceListView (NSCoder coder) : base(coder)
{
}
public SourceListView (NSObjectFlag t) : base(t)
{
}
#endregion
#region Override Methods
public override void AwakeFromNib ()
{
base.AwakeFromNib ();
}
#endregion
#region Public Methods
public void Initialize() {
// Initialize this instance
this.DataSource = new SourceListDataSource (this);
this.Delegate = new SourceListDelegate (this);
}
public void AddItem(SourceListItem item) {
if (Data != null) {
Data.Items.Add (item);
}
}
#endregion
#region Events
public delegate void ItemSelectedDelegate(SourceListItem item);
public event ItemSelectedDelegate ItemSelected;
internal void RaiseItemSelected(SourceListItem item) {
// Inform caller
if (this.ItemSelected != null) {
this.ItemSelected (item);
}
}
#endregion
}
}
In questo modo viene creata una sottoclasse personalizzata riutilizzabile di NSOutlineView
(SourceListView
) che è possibile usare per guidare l'elenco di origine in qualsiasi applicazione Xamarin.Mac creata.
Creazione e gestione di elenchi di origine in Xcode
Verrà ora progettato l'elenco di origine in Interface Builder. Fare doppio clic sul Main.storyboard
file per aprirlo per la modifica in Interface Builder e trascinare una visualizzazione divisa dal controllo libreria, aggiungerlo al controller di visualizzazione e impostarlo per ridimensionarlo con la visualizzazione nell'editor vincoli:
Trascinare quindi un elenco di origine dal controllo libreria, aggiungerlo al lato sinistro della visualizzazione divisa e impostarlo per ridimensionarlo con La visualizzazione nell'editor vincoli:
Passare quindi alla visualizzazione identità, selezionare l'elenco di origine e modificare la classe in SourceListView
:
Infine, creare un outlet per l'elenco ViewController.h
di origine chiamato SourceList
nel file:
Salvare le modifiche e tornare a Visual Studio per Mac per la sincronizzazione con Xcode.
Popolamento dell'elenco di origine
Modificare il RotationWindow.cs
file in Visual Studio per Mac e impostarlo AwakeFromNib
come segue:
public override void AwakeFromNib ()
{
base.AwakeFromNib ();
// Populate source list
SourceList.Initialize ();
var library = new SourceListItem ("Library");
library.AddItem ("Venues", "house.png", () => {
Console.WriteLine("Venue Selected");
});
library.AddItem ("Singers", "group.png");
library.AddItem ("Genre", "cards.png");
library.AddItem ("Publishers", "box.png");
library.AddItem ("Artist", "person.png");
library.AddItem ("Music", "album.png");
SourceList.AddItem (library);
// Add Rotation
var rotation = new SourceListItem ("Rotation");
rotation.AddItem ("View Rotation", "redo.png");
SourceList.AddItem (rotation);
// Add Kiosks
var kiosks = new SourceListItem ("Kiosks");
kiosks.AddItem ("Sign-in Station 1", "imac");
kiosks.AddItem ("Sign-in Station 2", "ipad");
SourceList.AddItem (kiosks);
// Display side list
SourceList.ReloadData ();
SourceList.ExpandItem (null, true);
}
Il Initialize ()
metodo deve essere chiamato sul punto di vendita dell'elenco di origine prima che tutti gli elementi vengano aggiunti. Per ogni gruppo di elementi, creiamo un elemento padre e quindi aggiungiamo gli elementi secondari a tale elemento di gruppo. Ogni gruppo viene quindi aggiunto alla raccolta SourceList.AddItem (...)
dell'elenco di origine. Le ultime due righe caricano i dati per l'elenco di origine ed espande tutti i gruppi:
// Display side list
SourceList.ReloadData ();
SourceList.ExpandItem (null, true);
Infine, modificare il AppDelegate.cs
file e rendere il DidFinishLaunching
metodo simile al seguente:
public override void DidFinishLaunching (NSNotification notification)
{
mainWindowController = new MainWindowController ();
mainWindowController.Window.MakeKeyAndOrderFront (this);
var rotation = new RotationWindowController ();
rotation.Window.MakeKeyAndOrderFront (this);
}
Se si esegue l'applicazione, verrà visualizzato quanto segue:
Riepilogo
Questo articolo ha esaminato in dettaglio l'uso degli elenchi di origine in un'applicazione Xamarin.Mac. È stato illustrato come creare e gestire elenchi di origine in Interface Builder di Xcode e come usare elenchi di origine nel codice C#.
Collegamenti correlati
- Hello, Mac
- Table Views (Visualizzazioni tabelle)
- Outline Views (Visualizzazioni struttura)
- Linee guida dell'interfaccia umana OS X
- Introduzione alle visualizzazioni struttura
- NSOutlineView
- NSOutlineViewDataSource
- NSOutlineViewDelegate