Listes sources dans Xamarin.Mac
Cet article traite de l’utilisation des listes sources dans une application Xamarin.Mac. Il décrit la création et la gestion des listes sources dans Xcode et Interface Builder et l’interaction avec eux dans le code C#.
Lorsque vous utilisez C# et .NET dans une application Xamarin.Mac, vous avez accès aux mêmes listes sources que celles dans Objective-C lesquelles un développeur travaille et Xcode . Étant donné que Xamarin.Mac s’intègre directement à Xcode, vous pouvez utiliser le Générateur d’interface de Xcode pour créer et gérer vos listes sources (ou éventuellement les créer directement dans le code C#).
Une liste de sources est un type spécial d’affichage hiérarchique utilisé pour afficher la source d’une action, comme la barre latérale dans Finder ou iTunes.
Dans cet article, nous allons aborder les principes fondamentaux de l’utilisation des listes sources dans une application Xamarin.Mac. Il est fortement suggéré que vous travaillez tout d’abord dans l’article Hello, Mac , en particulier les sections Introduction to Xcode and Interface Builder et Outlets and Actions , car elle couvre les concepts et techniques clés que nous utiliserons dans cet article.
Vous pouvez également examiner les classes /méthodes C# exposantes dans Objective-Cla section du document interne Xamarin.Mac, ainsi que les Register
Export
instructions utilisées pour connecter vos classes C# à des objets et des Objective-C éléments d’interface utilisateur.
Présentation des listes sources
Comme indiqué ci-dessus, une liste de sources est un type spécial d’affichage hiérarchique utilisé pour afficher la source d’une action, comme la barre latérale dans Finder ou iTunes. Une liste source est un type de table qui permet à l’utilisateur de développer ou de réduire les lignes de données hiérarchiques. Contrairement à une vue table, les éléments d’une liste source ne se trouvent pas dans une liste plate, ils sont organisés dans une hiérarchie, comme les fichiers et les dossiers sur un disque dur. Si un élément d’une liste source contient d’autres éléments, il peut être développé ou réduit par l’utilisateur.
La liste source est une vue hiérarchique spécialement style (NSOutlineView
), qui est elle-même une sous-classe de l’affichage table (NSTableView
) et, par conséquent, hérite beaucoup de son comportement de sa classe parente. Par conséquent, de nombreuses opérations prises en charge par un mode Plan sont également prises en charge par une liste source. Une application Xamarin.Mac contrôle ces fonctionnalités et peut configurer les paramètres de la liste source (dans le code ou le Générateur d’interface) pour autoriser ou interdire certaines opérations.
Une liste de sources ne stocke pas ses propres données, au lieu de cela, elle s’appuie sur une source de données (NSOutlineViewDataSource
) pour fournir les lignes et les colonnes requises, selon les besoins.
Le comportement d’une liste source peut être personnalisé en fournissant une sous-classe du délégué en mode Plan (NSOutlineViewDelegate
) pour prendre en charge le type Plan pour sélectionner des fonctionnalités, la sélection et la modification d’éléments, le suivi personnalisé et les vues personnalisées pour des éléments individuels.
Étant donné qu’une liste source partage une grande partie de son comportement et de ses fonctionnalités avec une vue table et un mode Plan, vous pouvez passer par la documentation sur les vues de tableau et les vues hiérarchiques avant de continuer avec cet article.
Utilisation des listes sources
Une liste de sources est un type spécial d’affichage hiérarchique utilisé pour afficher la source d’une action, comme la barre latérale dans Finder ou iTunes. Contrairement aux vues hiérarchiques, avant de définir notre liste source dans le Générateur d’interface, nous allons créer les classes de stockage dans Xamarin.Mac.
Tout d’abord, nous allons créer une SourceListItem
classe pour contenir les données de notre liste de sources. Dans le Explorateur de solutions, cliquez avec le bouton droit sur le projet, puis sélectionnez Ajouter>un nouveau fichier... Sélectionnez Classe vide générale>, entrez SourceListItem
le nom, puis cliquez sur le bouton Nouveau :
Faites en sorte que le SourceListItem.cs
fichier ressemble à ce qui suit :
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
}
}
Dans le Explorateur de solutions, cliquez avec le bouton droit sur le projet, puis sélectionnez Ajouter>un nouveau fichier... Sélectionnez Classe vide générale>, entrez SourceListDataSource
le nom, puis cliquez sur le bouton Nouveau. Faites en sorte que le SourceListDataSource.cs
fichier ressemble à ce qui suit :
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
}
}
Cela fournira les données de notre liste de sources.
Dans le Explorateur de solutions, cliquez avec le bouton droit sur le projet, puis sélectionnez Ajouter>un nouveau fichier... Sélectionnez Classe vide générale>, entrez SourceListDelegate
le nom, puis cliquez sur le bouton Nouveau. Faites en sorte que le SourceListDelegate.cs
fichier ressemble à ce qui suit :
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
}
}
Cela fournira le comportement de notre liste source.
Enfin, dans le Explorateur de solutions, cliquez avec le bouton droit sur le projet et sélectionnez Ajouter>un nouveau fichier... Sélectionnez Classe vide générale>, entrez SourceListView
le nom, puis cliquez sur le bouton Nouveau. Faites en sorte que le SourceListView.cs
fichier ressemble à ce qui suit :
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
}
}
Cela crée une sous-classe personnalisée et réutilisable de NSOutlineView
(SourceListView
) que nous pouvons utiliser pour piloter la liste source dans n’importe quelle application Xamarin.Mac que nous créons.
Création et maintenance de listes sources dans Xcode
Nous allons maintenant concevoir notre liste source dans le Générateur d’interface. Double-cliquez sur le Main.storyboard
fichier pour l’ouvrir pour modification dans le Générateur d’interface et faites glisser un mode Fractionné à partir de l’inspecteur de bibliothèque, ajoutez-le au contrôleur de vue et définissez-le pour le redimensionner avec l’affichage dans l’éditeur de contraintes :
Ensuite, faites glisser une liste source à partir de l’inspecteur de bibliothèque, ajoutez-la à gauche de l’affichage fractionné et définissez-la pour la redimensionner avec l’affichage dans l’éditeur de contraintes :
Ensuite, basculez vers l’affichage d’identité, sélectionnez la liste source et remplacez la classe SourceListView
par :
Enfin, créez une sortie pour notre liste source appelée SourceList
dans le ViewController.h
fichier :
Enregistrez vos modifications et revenez à Visual Studio pour Mac à synchroniser avec Xcode.
Remplissage de la liste source
Nous allons modifier le RotationWindow.cs
fichier dans Visual Studio pour Mac et faire en sorte que sa AwakeFromNib
méthode ressemble à ce qui suit :
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);
}
La Initialize ()
méthode doit être appelée sur le point de sortie de notre liste source avant d’y ajouter des éléments. Pour chaque groupe d’éléments, nous créons un élément parent, puis ajoutons les sous-éléments à cet élément de groupe. Chaque groupe est ensuite ajouté à la collection SourceList.AddItem (...)
source List. Les deux dernières lignes chargent les données de la liste source et développent tous les groupes :
// Display side list
SourceList.ReloadData ();
SourceList.ExpandItem (null, true);
Enfin, modifiez le AppDelegate.cs
fichier et faites en sorte que la DidFinishLaunching
méthode ressemble à ce qui suit :
public override void DidFinishLaunching (NSNotification notification)
{
mainWindowController = new MainWindowController ();
mainWindowController.Window.MakeKeyAndOrderFront (this);
var rotation = new RotationWindowController ();
rotation.Window.MakeKeyAndOrderFront (this);
}
Si nous exécutons notre application, les éléments suivants s’affichent :
Résumé
Cet article a examiné en détail l’utilisation des listes sources dans une application Xamarin.Mac. Nous avons vu comment créer et gérer des listes sources dans le Générateur d’interface de Xcode et comment utiliser des listes sources dans du code C#.