Listy źródłowe na platformie Xamarin.Mac
W tym artykule opisano pracę z listami źródłowymi w aplikacji platformy Xamarin.Mac. W tym artykule opisano tworzenie i konserwowanie list źródłowych w programie Xcode i narzędziu Interface Builder oraz interakcję z nimi w kodzie języka C#.
Podczas pracy z językami C# i .NET w aplikacji platformy Xamarin.Mac masz dostęp do tych samych list źródłowych, w Objective-C których pracuje deweloper i czy program Xcode . Ponieważ platforma Xamarin.Mac integruje się bezpośrednio z programem Xcode, możesz użyć narzędzia Interface Builder środowiska Xcode do tworzenia i obsługi list źródłowych (lub opcjonalnie tworzenia ich bezpośrednio w kodzie języka C#).
Lista źródłowa to specjalny typ widoku konspektu używany do wyświetlania źródła akcji, takiego jak pasek boczny w programie Finder lub iTunes.
W tym artykule omówimy podstawy pracy z listami źródłowymi w aplikacji platformy Xamarin.Mac. Zdecydowanie zaleca się, aby najpierw zapoznać się z artykułem Hello, Mac , w szczególności wprowadzenie do narzędzi Xcode i Interface Builder i Outlet and Actions , ponieważ obejmuje ona kluczowe pojęcia i techniki, których będziemy używać w tym artykule.
Warto zapoznać się również z sekcją Uwidacznianie klas/ metod Objective-C języka C# w dokumencie Xamarin.Mac Internals . Register
Objaśnienie poleceń i Export
używanych do podłączania klas języka C# do Objective-C obiektów i elementów interfejsu użytkownika.
Wprowadzenie do list źródłowych
Jak wspomniano powyżej, lista źródłowa jest specjalnym typem widoku konspektu używanym do wyświetlania źródła akcji, na przykład paska bocznego w programie Finder lub iTunes. Lista źródłowa to typ tabeli, który umożliwia użytkownikowi rozwijanie lub zwijanie wierszy danych hierarchicznych. W przeciwieństwie do widoku tabeli elementy na liście źródłowej nie znajdują się na płaskiej liście, są zorganizowane w hierarchii, takich jak pliki i foldery na dysku twardym. Jeśli element na liście źródłowej zawiera inne elementy, można go rozwinąć lub zwinąć przez użytkownika.
Lista źródłowa jest specjalnie stylizowanym widokiem konspektu (NSOutlineView
), który sam jest podklasą widoku tabeli (NSTableView
), a w związku z tym dziedziczy znaczną część swojego zachowania z klasy nadrzędnej. W związku z tym wiele operacji obsługiwanych przez widok konspektu jest również obsługiwanych przez listę źródłową. Aplikacja Xamarin.Mac ma kontrolę nad tymi funkcjami i może skonfigurować parametry listy źródłowej (w kodzie lub konstruktorze interfejsu), aby zezwalać na niektóre operacje lub nie zezwalać na nie.
Lista źródłowa nie przechowuje własnych danych, a zamiast tego opiera się na źródle danych (NSOutlineViewDataSource
), aby zapewnić wymagane zarówno wiersze, jak i kolumny zgodnie z potrzebami.
Zachowanie listy źródłowej można dostosować, udostępniając podklasę delegata widoku konspektu (NSOutlineViewDelegate
), aby obsługiwać typ konspektu w celu wybrania funkcji, zaznaczenia i edytowania elementów, śledzenia niestandardowego i widoków niestandardowych dla poszczególnych elementów.
Ponieważ lista źródłowa udostępnia większość jej zachowań i funkcji w widoku tabeli i widoku konspektu, warto zapoznać się z naszą dokumentacją widoków tabel i widoków konspektu przed kontynuowaniem tego artykułu.
Praca z listami źródłowymi
Lista źródłowa to specjalny typ widoku konspektu używany do wyświetlania źródła akcji, takiego jak pasek boczny w programie Finder lub iTunes. W przeciwieństwie do widoków konspektu, zanim zdefiniujemy naszą listę źródłową w narzędziu Interface Builder, utwórzmy klasy zapasowe na platformie Xamarin.Mac.
Najpierw utwórzmy nową SourceListItem
klasę do przechowywania danych dla naszej listy źródłowej. W Eksplorator rozwiązań kliknij prawym przyciskiem myszy projekt i wybierz polecenie Dodaj>nowy plik... Wybierz pozycję Ogólna>Pusta klasa, wprowadź SourceListItem
nazwę i kliknij przycisk Nowy:
SourceListItem.cs
Utwórz plik w następujący sposób:
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
}
}
W Eksplorator rozwiązań kliknij prawym przyciskiem myszy projekt i wybierz polecenie Dodaj>nowy plik... Wybierz pozycję Ogólna>Pusta klasa, wprowadź SourceListDataSource
nazwę i kliknij przycisk Nowy. SourceListDataSource.cs
Utwórz plik w następujący sposób:
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
}
}
Zapewni to dane dla naszej listy źródłowej.
W Eksplorator rozwiązań kliknij prawym przyciskiem myszy projekt i wybierz polecenie Dodaj>nowy plik... Wybierz pozycję Ogólna>Pusta klasa, wprowadź SourceListDelegate
nazwę i kliknij przycisk Nowy. SourceListDelegate.cs
Utwórz plik w następujący sposób:
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
}
}
Zapewni to zachowanie naszej listy źródłowej.
Na koniec w Eksplorator rozwiązań kliknij prawym przyciskiem myszy projekt i wybierz polecenie Dodaj>nowy plik... Wybierz pozycję Ogólna>Pusta klasa, wprowadź SourceListView
nazwę i kliknij przycisk Nowy. SourceListView.cs
Utwórz plik w następujący sposób:
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
}
}
Spowoduje to utworzenie niestandardowej podklasy wielokrotnego NSOutlineView
użytku (SourceListView
), której możemy użyć do kierowania listą źródłową w dowolnej aplikacji platformy Xamarin.Mac, którą tworzymy.
Tworzenie i obsługa list źródłowych w programie Xcode
Teraz zaprojektujmy naszą listę źródłową w narzędziu Interface Builder. Kliknij dwukrotnie plik, aby otworzyć go do edycji w narzędziu Main.storyboard
Interface Builder i przeciągnij widok podzielony z Inspektora biblioteki, dodaj go do kontrolera widoku i ustaw jego rozmiar za pomocą widoku w Edytorze ograniczeń:
Następnie przeciągnij listę źródłową z Inspektora biblioteki, dodaj ją do lewej strony widoku podziału i ustaw jej rozmiar na widok w Edytorze ograniczeń:
Następnie przejdź do widoku tożsamości, wybierz listę źródłową i zmień ją na Klasa na SourceListView
:
Na koniec utwórz punkt wylotowy dla naszej listy źródłowej ViewController.h
o nazwie SourceList
w pliku :
Zapisz zmiany i wróć do Visual Studio dla komputerów Mac, aby przeprowadzić synchronizację z programem Xcode.
Wypełnianie listy źródłowej
Zmodyfikujmy RotationWindow.cs
plik w Visual Studio dla komputerów Mac i ustawmyAwakeFromNib
, że jest to metoda podobna do następującej:
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);
}
Przed Initialize ()
dodaniu do niej wszystkich elementów należy wywołać metodę ujścia listy źródłowej. Dla każdej grupy elementów utworzymy element nadrzędny, a następnie dodamy elementy podrzędne do tego elementu grupy. Każda grupa jest następnie dodawana do kolekcji SourceList.AddItem (...)
listy źródłowej . Ostatnie dwa wiersze ładują dane dla listy źródłowej i rozszerza wszystkie grupy:
// Display side list
SourceList.ReloadData ();
SourceList.ExpandItem (null, true);
Na koniec zmodyfikuj AppDelegate.cs
plik i utwórz metodę DidFinishLaunching
podobną do następującej:
public override void DidFinishLaunching (NSNotification notification)
{
mainWindowController = new MainWindowController ();
mainWindowController.Window.MakeKeyAndOrderFront (this);
var rotation = new RotationWindowController ();
rotation.Window.MakeKeyAndOrderFront (this);
}
Jeśli uruchomimy aplikację, zostaną wyświetlone następujące elementy:
Podsumowanie
W tym artykule szczegółowo przedstawiono pracę z listami źródłowymi w aplikacji platformy Xamarin.Mac. Zobaczyliśmy, jak tworzyć i obsługiwać listy źródłowe w narzędziu Interface Builder programu Xcode oraz jak pracować z listami źródłowymi w kodzie języka C#.