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 maintenance de listes sources dans Xcode et Interface Builder et l’interaction avec ces listes dans le code C#.
Lorsque vous utilisez C# et .NET dans une application Xamarin.Mac, vous avez accès aux mêmes listes de sources qu’un développeur travaillant dans Objective-C 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 de sources (ou éventuellement les créer directement dans du code C#).
Une liste de sources est un type spécial d’affichage Plan utilisé pour afficher la source d’une action, comme la barre latérale dans le Finder ou iTunes.
Dans cet article, nous allons aborder les principes de base de l’utilisation des listes sources dans une application Xamarin.Mac. Il est fortement suggéré de commencer par l’article Hello, Mac , en particulier les sections Introduction to Xcode et Interface Builderet Outlets and Actions , car il couvre les concepts et techniques clés que nous allons utiliser dans cet article.
Vous pouvez également consulter la section Exposing C# classes/méthodes to Objective-C du document Xamarin.Mac Internals . Il explique les Register
commandes et Export
utilisées pour connecter vos classes C# à des objets et des éléments d’interface Objective-C utilisateur.
Présentation des listes sources
Comme indiqué ci-dessus, une liste de sources est un type spécial d’affichage Plan utilisé pour afficher la source d’une action, comme la barre latérale dans le Finder ou iTunes. Une liste source est un type de table qui permet à l’utilisateur de développer ou de réduire des lignes de données hiérarchiques. Contrairement à un affichage Table, les éléments d’une liste source ne sont 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 de sources contient d’autres éléments, il peut être développé ou réduit par l’utilisateur.
La liste source est une vueNSOutlineView
de plan de style (), qui est elle-même une sous-classe de l’affichage Table (NSTableView
) et, par conséquent, hérite d’une grande partie 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 de sources (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, mais s’appuie sur une source de données (NSOutlineViewDataSource
) pour fournir à la fois les lignes et les colonnes requises, en fonction des besoins.
Le comportement d’une liste de sources peut être personnalisé en fournissant une sous-classe du délégué en mode Plan (NSOutlineViewDelegate
) pour prendre en charge le type de plan pour sélectionner les fonctionnalités, la sélection et la modification d’élément, le suivi personnalisé et les vues personnalisées pour des éléments individuels.
Étant donné qu’une liste de sources partage une grande partie de son comportement et de ses fonctionnalités avec une vue Table et un mode Plan, vous pouvez consulter notre documentation vues table et vues de plan avant de continuer avec cet article.
Utilisation des listes sources
Une liste de sources est un type spécial d’affichage Plan utilisé pour afficher la source d’une action, comme la barre latérale dans le Finder ou iTunes. Contrairement aux vues hiérarchiques, avant de définir notre liste de sources dans Le Générateur d’interface, nous allons créer les classes de sauvegarde dans Xamarin.Mac.
Tout d’abord, nous allons créer une classe SourceListItem
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 Général>Classe vide, entrez SourceListItem
comme 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
comme 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 fournit 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
comme 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 fournit le comportement de notre liste de sources.
Enfin, 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 SourceListView
comme 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 réutilisable personnalisée de NSOutlineView
(SourceListView
) que nous pouvons utiliser pour générer la liste des sources dans n’importe quelle application Xamarin.Mac que nous créons.
Création et maintenance de listes de sources dans Xcode
Maintenant, nous allons concevoir notre liste de sources dans Le Générateur d’interface. Double-cliquez sur le fichier pour l’ouvrir Main.storyboard
pour le modifier dans le Générateur d’interface, puis faites glisser une vue fractionnée à partir de l’inspecteur de bibliothèque, ajoutez-le au contrôleur d’affichage et définissez-le pour le redimensionner avec l’affichage dans l’éditeur de contraintes :
Ensuite, faites glisser une liste de sources à partir de l’inspecteur de bibliothèque, ajoutez-la sur le côté gauche de l’affichage fractionné et définissez-la pour la redimensionner avec l’affichage dans l’éditeur de contraintes :
Ensuite, basculez vers la vue d’identité, sélectionnez la liste des sources, puis remplacez la classe parSourceListView
:
Enfin, créez un outlet pour notre liste de sources appelé SourceList
dans le ViewController.h
fichier :
Enregistrez vos modifications et revenez à Visual Studio pour Mac à synchroniser avec Xcode.
Remplissage de la liste des sources
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 par rapport au point de vente de notre liste de sources 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 (...)
de la liste de sources . 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 de sources dans le Générateur d’interface de Xcode et comment utiliser des listes de sources dans du code C#.