Bagikan melalui


Daftar sumber di Xamarin.Mac

Artikel ini membahas cara bekerja dengan daftar sumber dalam aplikasi Xamarin.Mac. Ini menjelaskan pembuatan dan pemeliharaan daftar sumber di Xcode dan Interface Builder dan berinteraksi dengannya dalam kode C#.

Saat bekerja dengan C# dan .NET dalam aplikasi Xamarin.Mac, Anda memiliki akses ke Daftar Sumber yang sama dengan yang digunakan Objective-C pengembang dan Xcode . Karena Xamarin.Mac terintegrasi langsung dengan Xcode, Anda dapat menggunakan Penyusun Antarmuka Xcode untuk membuat dan memelihara Daftar Sumber Anda (atau secara opsional membuatnya langsung dalam kode C#).

Daftar Sumber adalah jenis khusus Tampilan Kerangka yang digunakan untuk menampilkan sumber tindakan, seperti bilah samping di Finder atau iTunes.

Contoh daftar sumber

Dalam artikel ini, kita akan membahas dasar-dasar bekerja dengan Daftar Sumber dalam aplikasi Xamarin.Mac. Sangat disarankan agar Anda bekerja melalui artikel Hello, Mac terlebih dahulu, khususnya bagian Pengenalan Xcode dan Penyusun Antarmuka dan Outlet dan Tindakan , karena mencakup konsep dan teknik utama yang akan kita gunakan dalam artikel ini.

Anda mungkin ingin melihat kelas / metode Exposing C# keObjective-Cbagian dari dokumen Xamarin.Mac Internals juga, ini menjelaskan Register perintah dan Export yang digunakan untuk menyambungkan kelas C# Anda ke Objective-C objek dan Elemen UI.

Pengantar Daftar Sumber

Seperti yang dinyatakan di atas, Daftar Sumber adalah jenis khusus Tampilan Kerangka yang digunakan untuk menampilkan sumber tindakan, seperti bilah samping di Finder atau iTunes. Daftar Sumber adalah jenis Tabel yang memungkinkan pengguna memperluas atau menciutkan baris data hierarkis. Tidak seperti Tampilan Tabel, item dalam Daftar Sumber tidak berada dalam daftar datar, item tersebut diatur dalam hierarki, seperti file dan folder di hard drive. Jika item dalam Daftar Sumber berisi item lain, item tersebut dapat diperluas atau diciutkan oleh pengguna.

Daftar Sumber adalah Tampilan Kerangka yang ditata khusus (NSOutlineView), yang merupakan subkelas dari Tampilan Tabel (NSTableView) dan dengan demikian, mewarisi sebagian besar perilakunya dari kelas induknya. Akibatnya, banyak operasi yang didukung oleh Tampilan Kerangka, juga didukung oleh Daftar Sumber. Aplikasi Xamarin.Mac memiliki kontrol atas fitur-fitur ini, dan dapat mengonfigurasi parameter Daftar Sumber (baik dalam kode atau Penyusun Antarmuka) untuk mengizinkan atau melarang operasi tertentu.

Daftar Sumber tidak menyimpan datanya sendiri, sebaliknya bergantung pada Sumber Data (NSOutlineViewDataSource) untuk menyediakan baris dan kolom yang diperlukan, sesuai kebutuhan.

Perilaku Daftar Sumber dapat dikustomisasi dengan menyediakan subkelas Delegasi Tampilan Kerangka (NSOutlineViewDelegate) untuk mendukung jenis Kerangka untuk memilih fungsionalitas, pemilihan dan pengeditan item, pelacakan kustom, dan tampilan kustom untuk item individual.

Karena Daftar Sumber berbagi sebagian besar perilaku dan fungsionalitasnya dengan Tampilan Tabel dan Tampilan Kerangka, Anda mungkin ingin menelusuri dokumentasi Tampilan Tabel dan Tampilan Kerangka kami sebelum melanjutkan artikel ini.

Bekerja dengan Daftar Sumber

Daftar Sumber adalah jenis khusus Tampilan Kerangka yang digunakan untuk menampilkan sumber tindakan, seperti bilah samping di Finder atau iTunes. Tidak seperti Tampilan Kerangka, sebelum kita menentukan Daftar Sumber di Penyusun Antarmuka, mari kita buat kelas backing di Xamarin.Mac.

Pertama, mari kita buat kelas baru SourceListItem untuk menyimpan data untuk Daftar Sumber kami. Di Penjelajah Solusi, klik kanan Proyek dan pilih Tambahkan>File Baru... Pilih Kelas Kosong Umum>, masukkan SourceListItem untuk Nama dan klik tombol Baru:

Menambahkan kelas kosong

SourceListItem.cs Buat file terlihat seperti berikut ini:

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
    }
}

Di Penjelajah Solusi, klik kanan Proyek dan pilih Tambahkan>File Baru... Pilih Kelas Kosong Umum>, masukkan SourceListDataSource untuk Nama dan klik tombol Baru. SourceListDataSource.cs Buat file terlihat seperti berikut ini:

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
    }
}

Ini akan menyediakan data untuk Daftar Sumber kami.

Di Penjelajah Solusi, klik kanan Proyek dan pilih Tambahkan>File Baru... Pilih Kelas Kosong Umum>, masukkan SourceListDelegate untuk Nama dan klik tombol Baru. SourceListDelegate.cs Buat file terlihat seperti berikut ini:

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
    }
}

Ini akan memberikan perilaku Daftar Sumber kami.

Terakhir, di Penjelajah Solusi, klik kanan Proyek dan pilih Tambahkan>File Baru... Pilih Kelas Kosong Umum>, masukkan SourceListView untuk Nama dan klik tombol Baru. SourceListView.cs Buat file terlihat seperti berikut ini:

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
    }
}

Ini membuat subkelas kustom yang dapat digunakan kembali (NSOutlineViewSourceListView) yang dapat kita gunakan untuk mendorong Daftar Sumber di aplikasi Xamarin.Mac apa pun yang kita buat.

Membuat dan Memelihara Daftar Sumber di Xcode

Sekarang, mari kita desain Daftar Sumber kami di Penyusun Antarmuka. Main.storyboard Klik dua kali file untuk membukanya untuk pengeditan di Penyusun Antarmuka dan seret Tampilan Terpisah dari Pemeriksa Pustaka, tambahkan ke Pengontrol Tampilan dan atur untuk mengubah ukuran dengan Tampilan di Editor Batasan:

Mengedit batasan di Penyusun Antarmuka.

Selanjutnya, seret Daftar Sumber dari Pemeriksa Pustaka, tambahkan ke sisi kiri Tampilan Pisahkan dan atur untuk mengubah ukuran dengan Tampilan di Editor Batasan:

Mengedit batasan dengan menyeret Daftar Sumber ke Tampilan Terpisah.

Selanjutnya, beralihlah ke Tampilan Identitas, pilih Daftar Sumber, dan ubah Kelasnya menjadi SourceListView:

Mengatur nama kelas

Terakhir, buat Outlet untuk Daftar Sumber kami yang ViewController.h dipanggil SourceList dalam file:

Mengonfigurasi Outlet

Simpan perubahan Anda dan kembali ke Visual Studio untuk Mac untuk disinkronkan dengan Xcode.

Mengisi Daftar Sumber

Mari kita edit RotationWindow.cs file di Visual Studio untuk Mac dan buat metodenya AwakeFromNib terlihat seperti berikut:

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);

}

Metode Initialize () ini perlu dipanggil terhadap OutletDaftar Sumber kami sebelum item apa pun ditambahkan ke dalamnya. Untuk setiap grup item, kami membuat item induk lalu menambahkan sub item ke item grup tersebut. Setiap grup kemudian ditambahkan ke koleksi SourceList.AddItem (...)Daftar Sumber . Dua baris terakhir memuat data untuk Daftar Sumber dan memperluas semua grup:

// Display side list
SourceList.ReloadData ();
SourceList.ExpandItem (null, true);

Terakhir, edit AppDelegate.cs file dan buat DidFinishLaunching metode terlihat seperti berikut:

public override void DidFinishLaunching (NSNotification notification)
{
    mainWindowController = new MainWindowController ();
    mainWindowController.Window.MakeKeyAndOrderFront (this);

    var rotation = new RotationWindowController ();
    rotation.Window.MakeKeyAndOrderFront (this);
}

Jika kita menjalankan aplikasi kita, berikut ini akan ditampilkan:

Contoh eksekusi aplikasi

Ringkasan

Artikel ini telah melihat secara rinci tentang bekerja dengan Daftar Sumber dalam aplikasi Xamarin.Mac. Kami melihat cara membuat dan memelihara Daftar Sumber di Penyusun Antarmuka Xcode dan cara bekerja dengan Daftar Sumber dalam kode C#.