共用方式為


Xamarin.Mac 中的大綱檢視

本文涵蓋在 Xamarin.Mac 應用程式中使用大綱檢視。 其描述如何在 Xcode 和 Interface Builder 中建立和維護大綱檢視,並以程序設計方式加以使用。

在 Xamarin.Mac 應用程式中使用 C# 和 .NET 時,您可以存取開發人員在 和 XcodeObjective-C運作的相同大綱檢視。 由於 Xamarin.Mac 直接與 Xcode 整合,因此您可以使用 Xcode 的 介面產生器 來建立和維護大綱檢視(或選擇性地直接在 C# 程式代碼中建立它們)。

大綱檢視是一種數據表類型,可讓用戶展開或折疊階層式數據列。 如同數據表檢視,大綱檢視會顯示一組相關項目的數據,其中數據列代表個別專案和數據行,代表這些項目的屬性。 不同於數據表檢視,大綱檢視中的專案不在一般清單中,它們會組織在階層中,例如硬碟上的檔案和資料夾。

範例應用程式執行

在本文中,我們將討論在 Xamarin.Mac 應用程式中使用大綱檢視的基本概念。 強烈建議您先完成 Hello,Mac 文章,特別是 Xcode 和 Interface Builder 和 Outlets 和 Actions 簡介小節,因為它涵蓋我們將在本文中使用的重要概念和技術。

您可能也想要查看 Xamarin.Mac Internals 檔的公開 C# 類別/方法Objective-C一節,它也會說明 Register 用來將 C# 類別連接至Objective-C物件和 UI 元素的 和 Export 命令。

大綱檢視簡介

大綱檢視是一種數據表類型,可讓用戶展開或折疊階層式數據列。 如同數據表檢視,大綱檢視會顯示一組相關項目的數據,其中數據列代表個別專案和數據行,代表這些項目的屬性。 不同於數據表檢視,大綱檢視中的專案不在一般清單中,它們會組織在階層中,例如硬碟上的檔案和資料夾。

如果大綱檢視中的專案包含其他專案,用戶可以展開或折迭該專案。 可展開的項目會顯示洩漏三角形,當專案折疊時指向右邊,並在項目展開時向下點。 按兩下洩漏三角形會導致項目展開或折疊。

大綱檢視 (NSOutlineView) 是數據表檢視的子類別,NSTableView因此會繼承其父類別的大部分行為。 因此,大綱檢視也支援許多數據表檢視所支持的作業,例如選取數據列或數據行、拖曳數據行標頭等來重新定位數據行。 Xamarin.Mac 應用程式可以控制這些功能,並可設定大綱檢視的參數(在程式代碼或介面產生器中),以允許或不允許某些作業。

大綱檢視不會儲存自己的數據,而是依賴數據源 (NSOutlineViewDataSource) 視需要提供所需的數據列和數據行。

您可以藉由提供大綱檢視委派的子類別來自定義大綱檢視的行為,NSOutlineViewDelegate以支援大綱數據行管理、輸入以選取功能、數據列選取和編輯、自定義追蹤,以及個別數據行和數據列的自定義檢視。

由於大綱檢視會與數據表檢視共用大部分的行為和功能,因此您可能想要先瀏覽我們的 數據表檢視 檔,再繼續進行本文。

在 Xcode 中建立和維護大綱檢視

當您建立新的 Xamarin.Mac Cocoa 應用程式時,預設會取得標準空白視窗。 這個視窗會在項目中自動包含的檔案中定義 .storyboard 。 若要編輯您的 Windows 設計,請在 方案總管 中按兩下Main.storyboard檔案:

選取主分鏡腳本

這會在 Xcode 的 Interface Builder 中開啟視窗設計:

在 Xcode 中編輯 UI

在連結庫偵測器的搜尋方塊中輸入 outline ,讓您更輕鬆地尋找大綱檢視控件:

從文檔庫選取大綱檢視

將 [大綱檢視] 拖曳到 [介面編輯器] 中的 [檢視控制器],使其填滿檢視控制器的內容區域,並將其設定為 [條件約束編輯器] 中的視窗壓縮和成長的位置:

編輯條件約束

在 [介面階層] 中選取 [大綱檢視],屬性偵測器提供下列屬性:

此螢幕快照顯示屬性偵測器中可用的屬性。

  • 大綱數據行 - 顯示階層式數據的數據表數據行。
  • 自動儲存大綱數據行 - 如果 true,則會自動儲存大綱欄,並在應用程式執行之間還原。
  • 縮排 - 展開專案下縮排數據行的數量。
  • 縮排跟隨儲存格 - 如果 true為 ,縮排標記會隨著儲存格縮排。
  • 自動儲存展開的專案 - 如果 true為 ,則會在應用程式執行之間自動儲存和還原項目的展開/折疊狀態。
  • 內容模式 - 可讓您使用 [檢視] 或NSView [儲存格] 來NSCell顯示資料列和資料行中的數據。 從 macOS 10.7 開始,您應該使用 Views。
  • 浮點數群組數據列 - 如果 true,數據表檢視會繪製群組儲存格,就像是浮動一樣。
  • 數據列 - 定義顯示的數據列數目。
  • 標頭 - 如果true為 ,則數據行會有標頭。
  • 重新排序 - 如果 true,使用者將能夠拖曳重新排序數據表中的數據行。
  • 重設大小 - 如果 true,使用者將能夠拖曳數據行標頭以調整數據行大小。
  • 數據行重設大小 - 控制數據表如何自動調整數據行大小。
  • 醒目提示 - 控制選取儲存格時,醒目提示表格所使用的類型。
  • 替代資料列 - 如果 true為 ,則其他資料列將有不同的背景色彩。
  • 水準方格 - 選取水平儲存格之間繪製的框線類型。
  • 垂直格線 - 選取垂直儲存格之間繪製的框線類型。
  • 網格線色彩 - 設定儲存格框線色彩。
  • 背景 - 設定儲存格背景色彩。
  • 選取 - 可讓您控制使用者如何選取表格中的數據格:
    • Multiple - 如果 true為 ,則使用者可以選取多個數據列和數據行。
    • 數據列 - 如果 true為 ,用戶可以選取資料行。
    • 輸入 Select - 如果 true,使用者可以輸入字元來選取資料列。
    • 空白 - 如果使用者 true不需要選取資料列或數據行,則數據表完全不允許選取。
  • 自動儲存 - 資料表格式的名稱會自動儲存在底下。
  • 數據行資訊 - 如果 true為 ,則會自動儲存資料行的順序和寬度。
  • 換行符 - 選取儲存格如何處理換行符。
  • 截斷最後一個可見行 - 如果 true,數據格將會在數據中截斷,無法容納在數據界限內。

重要

除非您維護舊版 Xamarin.Mac 應用程式, NSView 否則應該使用 NSCell 以大綱檢視爲基礎的大綱檢視。 NSCell 會被視為舊版,且未來可能不受支援。

在介面階層選取數據表數據行,屬性偵測器提供下列屬性:

此螢幕快照顯示 [屬性偵測器] 中所選數據表數據行可用的屬性。

  • Title - 設定數據列的標題。
  • 對齊 - 設定儲存格內文字的對齊方式。
  • 標題字型 - 選取儲存格標題文字的字型。
  • 排序索引鍵 - 這是用來排序數據行中數據的索引鍵 。 如果使用者無法排序此資料行,請保留空白。
  • 選取器 - 這是 用來執行排序的動作 。 如果使用者無法排序此資料行,請保留空白。
  • Order - 這是數據行數據的排序順序。
  • 重設大小 - 選取資料行的大小調整類型。
  • 編輯 - 如果 true為 ,用戶可以編輯以儲存格為基礎的表格中的儲存格。
  • Hidden - 如果 true為 ,則會隱藏資料行。

您也可以拖曳資料行的控點(垂直置中於數據行右側)向左或向右來調整數據行的大小。

讓我們選取數據表檢視中的每個數據行,並提供第一個數據行的Product標題和第二欄Details

在介面階層選取數據表資料格檢視 (NSTableViewCell),屬性偵測器提供下列屬性:

此螢幕快照顯示屬性偵測器中所選資料表單元格可用的屬性。

這些是標準檢視的所有屬性。 您也可以在這裡選擇調整此資料列大小。

在 [介面階層] 中選取數據表檢視儲存格(預設為 aNSTextField),而且屬性偵測器提供下列屬性:

此螢幕快照顯示屬性偵測器中所選數據表檢視儲存格可用的屬性。

您將擁有標準文字欄位的所有屬性,可在這裡設定。 根據預設,標準文字欄位是用來顯示數據行中儲存格的數據。

在介面階層選取數據表資料格檢視 (NSTableFieldCell),屬性偵測器提供下列屬性:

此螢幕快照顯示所選取資料表檢視儲存格可用的屬性。

以下是最重要的設定:

  • 版面配置 - 選取此資料列中的數據格配置方式。
  • 使用單行模式 - 如果 true為 ,儲存格會限制為單行。
  • 第一個運行時間版面配置寬度 - 如果 true為 ,單元格會偏好在應用程式第一次執行時設定的寬度(手動或自動)。
  • 動作 - 控制儲存格的編輯 動作 何時傳送。
  • 行為 - 定義儲存格是否可選取或可編輯。
  • RTF - 如果 true為 ,則儲存格可以顯示格式化和樣式的文字。
  • 復原 - 如果true為 ,單元格會承擔復原行為的責任。

選取 [介面階層] 中數據表數據行底部的 [數據表數據格檢視NSTableFieldCell]:[

選取數據表數據格檢視

這可讓您編輯做為指定數據行所建立之所有儲存格的基底 模式 的數據表單元格檢視。

新增動作和輸出

就像任何其他Cocoa UI控件一樣,我們需要公開大綱檢視,而且它是使用 動作輸出 將欄和單元格公開至C# 程式代碼(根據所需的功能)。

針對我們想要公開的任何大綱檢視專案,此程式都相同:

  1. 切換至助理 編輯器 ,並確定 ViewController.h 已選取檔案:

    選取正確的 .h 檔案

  2. [介面階層] 選取 [大綱檢視],按兩下控件並拖曳至 ViewController.h 檔案。

  3. 建立 大綱檢視的輸出 ,稱為 ProductOutline

    此螢幕快照顯示屬性偵測器中名為 ProductOutline 的出口。

  4. 建立資料表ProductColumn資料列的輸出,也稱為 和 DetailsColumn

    此螢幕快照顯示屬性偵測器中名為 DetailsColumn 的輸出。

  5. 儲存變更並返回 Visual Studio for Mac 以與 Xcode 同步。

接下來,我們將撰寫程式代碼,以在執行應用程式時顯示大綱的一些數據。

填入大綱檢視

透過介面產生器所設計的大綱檢視,並透過 輸出公開,接下來我們需要建立 C# 程式代碼來填入它。

首先,讓我們建立新的 Product 類別,以保存子產品個別數據列和群組的資訊。 在 方案總管 中,以滑鼠右鍵按兩下 [專案],然後選取 [新增>檔案...選取 [一般>空白類別],輸入 Product [名稱],然後按下 [新增] 按鈕:

建立空類別

Product.cs讓檔案看起來如下所示:

using System;
using Foundation;
using System.Collections.Generic;

namespace MacOutlines
{
    public class Product : NSObject
    {
        #region Public Variables
        public List<Product> Products = new List<Product>();
        #endregion

        #region Computed Properties
        public string Title { get; set;} = "";
        public string Description { get; set;} = "";
        public bool IsProductGroup {
            get { return (Products.Count > 0); }
        }
        #endregion

        #region Constructors
        public Product ()
        {
        }

        public Product (string title, string description)
        {
            this.Title = title;
            this.Description = description;
        }
        #endregion
    }
}

接下來,我們需要建立的 NSOutlineDataSource 子類別,以在要求時提供大綱的數據。 在 方案總管 中,以滑鼠右鍵按兩下 [專案],然後選取 [新增>檔案...選取 [一般>空白類別],輸入 ProductOutlineDataSource [名稱],然後按兩下 [新增] 按鈕。

ProductTableDataSource.cs編輯檔案,使其看起來如下:

using System;
using AppKit;
using CoreGraphics;
using Foundation;
using System.Collections;
using System.Collections.Generic;

namespace MacOutlines
{
    public class ProductOutlineDataSource : NSOutlineViewDataSource
    {
        #region Public Variables
        public List<Product> Products = new List<Product>();
        #endregion

        #region Constructors
        public ProductOutlineDataSource ()
        {
        }
        #endregion

        #region Override Methods
        public override nint GetChildrenCount (NSOutlineView outlineView, NSObject item)
        {
            if (item == null) {
                return Products.Count;
            } else {
                return ((Product)item).Products.Count;
            }

        }

        public override NSObject GetChild (NSOutlineView outlineView, nint childIndex, NSObject item)
        {
            if (item == null) {
                return Products [childIndex];
            } else {
                return ((Product)item).Products [childIndex];
            }

        }

        public override bool ItemExpandable (NSOutlineView outlineView, NSObject item)
        {
            if (item == null) {
                return Products [0].IsProductGroup;
            } else {
                return ((Product)item).IsProductGroup;
            }

        }
        #endregion
    }
}

此類別具有大綱檢視專案的記憶體,並覆寫 GetChildrenCount 以傳回數據表中的數據列數目。 會 GetChild 傳回特定的父專案或子專案(如大綱檢視所要求),並將 ItemExpandable 指定的專案定義為父項或子專案。

最後,我們需要建立的 NSOutlineDelegate 子類別,以提供大綱的行為。 在 方案總管 中,以滑鼠右鍵按兩下 [專案],然後選取 [新增>檔案...選取 [一般>空白類別],輸入 ProductOutlineDelegate [名稱],然後按兩下 [新增] 按鈕。

ProductOutlineDelegate.cs編輯檔案,使其看起來如下:

using System;
using AppKit;
using CoreGraphics;
using Foundation;
using System.Collections;
using System.Collections.Generic;

namespace MacOutlines
{
    public class ProductOutlineDelegate : NSOutlineViewDelegate
    {
        #region Constants
        private const string CellIdentifier = "ProdCell";
        #endregion

        #region Private Variables
        private ProductOutlineDataSource DataSource;
        #endregion

        #region Constructors
        public ProductOutlineDelegate (ProductOutlineDataSource datasource)
        {
            this.DataSource = datasource;
        }
        #endregion

        #region Override Methods

        public override NSView GetView (NSOutlineView outlineView, NSTableColumn tableColumn, NSObject item) {
            // This pattern allows you reuse existing views when they are no-longer in use.
            // If the returned view is null, you instance up a new view
            // If a non-null view is returned, you modify it enough to reflect the new data
            NSTextField view = (NSTextField)outlineView.MakeView (CellIdentifier, this);
            if (view == null) {
                view = new NSTextField ();
                view.Identifier = CellIdentifier;
                view.BackgroundColor = NSColor.Clear;
                view.Bordered = false;
                view.Selectable = false;
                view.Editable = false;
            }

            // Cast item
            var product = item as Product;

            // Setup view based on the column selected
            switch (tableColumn.Title) {
            case "Product":
                view.StringValue = product.Title;
                break;
            case "Details":
                view.StringValue = product.Description;
                break;
            }

            return view;
        }
        #endregion
    }
}

當我們建立的 ProductOutlineDelegate實例時,我們也會傳入 的實例 ProductOutlineDataSource ,以提供大綱的數據。 方法 GetView 負責傳回檢視 (data) 以顯示指定資料行和數據列的數據格。 如果可能的話,如果不是必須建立新的檢視,則會重複使用現有的檢視來顯示單元格。

若要填入大綱,讓我們編輯 MainWindow.cs 檔案,讓 AwakeFromNib 方法看起來如下所示:

public override void AwakeFromNib ()
{
    base.AwakeFromNib ();

    // Create data source and populate
    var DataSource = new ProductOutlineDataSource ();

    var Vegetables = new Product ("Vegetables", "Greens and Other Produce");
    Vegetables.Products.Add (new Product ("Cabbage", "Brassica oleracea - Leaves, axillary buds, stems, flowerheads"));
    Vegetables.Products.Add (new Product ("Turnip", "Brassica rapa - Tubers, leaves"));
    Vegetables.Products.Add (new Product ("Radish", "Raphanus sativus - Roots, leaves, seed pods, seed oil, sprouting"));
    Vegetables.Products.Add (new Product ("Carrot", "Daucus carota - Root tubers"));
    DataSource.Products.Add (Vegetables);

    var Fruits = new Product ("Fruits", "Fruit is a part of a flowering plant that derives from specific tissues of the flower");
    Fruits.Products.Add (new Product ("Grape", "True Berry"));
    Fruits.Products.Add (new Product ("Cucumber", "Pepo"));
    Fruits.Products.Add (new Product ("Orange", "Hesperidium"));
    Fruits.Products.Add (new Product ("Blackberry", "Aggregate fruit"));
    DataSource.Products.Add (Fruits);

    var Meats = new Product ("Meats", "Lean Cuts");
    Meats.Products.Add (new Product ("Beef", "Cow"));
    Meats.Products.Add (new Product ("Pork", "Pig"));
    Meats.Products.Add (new Product ("Veal", "Young Cow"));
    DataSource.Products.Add (Meats);

    // Populate the outline
    ProductOutline.DataSource = DataSource;
    ProductOutline.Delegate = new ProductOutlineDelegate (DataSource);

}

如果我們執行應用程式,則會顯示下列專案:

折疊的檢視

如果我們在大綱檢視中展開節點,它看起來會像下面這樣:

展開的檢視

依數據行排序

讓我們允許使用者按兩下數據行標頭,以排序大綱中的數據。 首先,按兩下 Main.storyboard 檔案以開啟檔案,以在介面產生器中編輯。 選取資料Product行,針對 [排序索引鍵],compare:針對 [選取器] 輸入 Title ,然後選取 Ascending [訂單]:

設定排序索引鍵順序

儲存變更並返回 Visual Studio for Mac 以與 Xcode 同步。

現在讓我們編輯 ProductOutlineDataSource.cs 檔案,並新增下列方法:

public void Sort(string key, bool ascending) {

    // Take action based on key
    switch (key) {
    case "Title":
        if (ascending) {
            Products.Sort ((x, y) => x.Title.CompareTo (y.Title));
        } else {
            Products.Sort ((x, y) => -1 * x.Title.CompareTo (y.Title));
        }
        break;
    }
}

public override void SortDescriptorsChanged (NSOutlineView outlineView, NSSortDescriptor[] oldDescriptors)
{
    // Sort the data
    Sort (oldDescriptors [0].Key, oldDescriptors [0].Ascending);
    outlineView.ReloadData ();
}

Sort方法可讓我們根據指定Product類別欄位,以遞增或遞減順序排序數據源中的數據。 每次使用單擊數據行標題時,就會呼叫覆寫 SortDescriptorsChanged 的方法。 它會傳遞我們在 Interface Builder 中設定的 Key 值,以及該數據行的排序順序。

如果我們執行應用程式並按下資料列標頭,資料列會依該資料列排序:

排序輸出的範例

數據列選取

如果您想要允許使用者選取單一數據列,請按兩下 Main.storyboard 檔案以在Interface Builder 中編輯。 選取 [介面階層] 中的 [大綱檢視],然後取消核取 [屬性偵測器] 中的 [多個] 複選框:

此螢幕快照顯示您可以變更 [多重] 設定的屬性偵測器。

儲存變更並返回 Visual Studio for Mac 以與 Xcode 同步。

接下來,編輯檔案並 ProductOutlineDelegate.cs 新增下列方法:

public override bool ShouldSelectItem (NSOutlineView outlineView, NSObject item)
{
    // Don't select product groups
    return !((Product)item).IsProductGroup;
}

這可讓使用者在大綱檢視中選取任何單一數據列。 ShouldSelectItem如果不想讓使用者能夠選取任何專案,則false傳回 false 。如果您不想讓使用者能夠選取任何專案,則傳回 給每個專案。

多重數據列選取

如果您想要允許使用者選取多個數據列,請按兩下 Main.storyboard 檔案以在 Interface Builder 中編輯。 選取 [介面階層] 中的 [大綱檢視],然後核取 [屬性偵測器] 中的 [多個] 複選框:

此螢幕快照顯示您可以選取 [多個] 的屬性偵測器。

儲存變更並返回 Visual Studio for Mac 以與 Xcode 同步。

接下來,編輯檔案並 ProductOutlineDelegate.cs 新增下列方法:

public override bool ShouldSelectItem (NSOutlineView outlineView, NSObject item)
{
    // Don't select product groups
    return !((Product)item).IsProductGroup;
}

這可讓使用者在大綱檢視中選取任何單一數據列。 ShouldSelectRow如果不想讓使用者能夠選取任何專案,則false傳回 false 。如果您不想讓使用者能夠選取任何專案,則傳回 給每個專案。

輸入以選取數據列

如果您想要允許使用者輸入已選取 [大綱檢視] 的字元,並選取具有該字元的第一個數據列,請按兩下 Main.storyboard 檔案以在介面產生器中編輯。 選取 [介面階層] 中的 [大綱檢視],然後核取 [屬性偵測器] 中的 [類型選取] 複選框:

編輯數據列類型

儲存變更並返回 Visual Studio for Mac 以與 Xcode 同步。

現在讓我們編輯 ProductOutlineDelegate.cs 檔案,並新增下列方法:

public override NSObject GetNextTypeSelectMatch (NSOutlineView outlineView, NSObject startItem, NSObject endItem, string searchString)
{
    foreach(Product product in DataSource.Products) {
        if (product.Title.Contains (searchString)) {
            return product;
        }
    }

    // Not found
    return null;
}

GetNextTypeSelectMatch方法會採用指定的 searchString ,並傳回具有該字串的第一個項目ProductTitle

重新排序數據行

如果您想要允許使用者在大綱檢視中拖曳重新排序數據行,請 Main.storyboard 按兩下檔案,以在介面產生器中編輯。 選取 [介面階層] 中的 [大綱檢視],然後核取 [屬性偵測器] 中的 [重新排序] 複選框:

顯示 [屬性檢查] 的螢幕快照,您可以在其中選取 [重新排序]。

如果我們為 [自動儲存] 屬性提供值並檢查 [資料行資訊] 字段,我們對數據表配置所做的任何變更都會自動儲存給我們,並在下次執行應用程式時還原。

儲存變更並返回 Visual Studio for Mac 以與 Xcode 同步。

現在讓我們編輯 ProductOutlineDelegate.cs 檔案,並新增下列方法:

public override bool ShouldReorder (NSOutlineView outlineView, nint columnIndex, nint newColumnIndex)
{
    return true;
}

方法 ShouldReorder 應該傳回 true 它想要允許重新排序到 newColumnIndex的任何數據行,否則會傳回 false;

如果我們執行應用程式,我們可以拖曳數據行標頭來重新排序資料行:

重新排序數據行的範例

編輯儲存格

如果您要允許使用者編輯指定儲存格的值,請編輯 ProductOutlineDelegate.cs 檔案並變更 GetViewForItem 方法,如下所示:

public override NSView GetView (NSOutlineView outlineView, NSTableColumn tableColumn, NSObject item) {
    // Cast item
    var product = item as Product;

    // This pattern allows you reuse existing views when they are no-longer in use.
    // If the returned view is null, you instance up a new view
    // If a non-null view is returned, you modify it enough to reflect the new data
    NSTextField view = (NSTextField)outlineView.MakeView (tableColumn.Title, this);
    if (view == null) {
        view = new NSTextField ();
        view.Identifier = tableColumn.Title;
        view.BackgroundColor = NSColor.Clear;
        view.Bordered = false;
        view.Selectable = false;
        view.Editable = !product.IsProductGroup;
    }

    // Tag view
    view.Tag = outlineView.RowForItem (item);

    // Allow for edit
    view.EditingEnded += (sender, e) => {

        // Grab product
        var prod = outlineView.ItemAtRow(view.Tag) as Product;

        // Take action based on type
        switch(view.Identifier) {
        case "Product":
            prod.Title = view.StringValue;
            break;
        case "Details":
            prod.Description = view.StringValue;
            break;
        }
    };

    // Setup view based on the column selected
    switch (tableColumn.Title) {
    case "Product":
        view.StringValue = product.Title;
        break;
    case "Details":
        view.StringValue = product.Description;
        break;
    }

    return view;
}

現在,如果我們執行應用程式,用戶可以編輯資料表檢視中的儲存格:

編輯儲存格的範例

在大綱檢視中使用影像

若要在儲存格中包含NSOutlineView影像,您必須變更大綱檢視NSTableViewDelegate'sGetView方法傳回資料的方式,以使用 NSTableCellView 而非一般 NSTextField。 例如:

public override NSView GetView (NSOutlineView outlineView, NSTableColumn tableColumn, NSObject item) {
    // Cast item
    var product = item as Product;

    // This pattern allows you reuse existing views when they are no-longer in use.
    // If the returned view is null, you instance up a new view
    // If a non-null view is returned, you modify it enough to reflect the new data
    NSTableCellView view = (NSTableCellView)outlineView.MakeView (tableColumn.Title, this);
    if (view == null) {
        view = new NSTableCellView ();
        if (tableColumn.Title == "Product") {
            view.ImageView = new NSImageView (new CGRect (0, 0, 16, 16));
            view.AddSubview (view.ImageView);
            view.TextField = new NSTextField (new CGRect (20, 0, 400, 16));
        } else {
            view.TextField = new NSTextField (new CGRect (0, 0, 400, 16));
        }
        view.TextField.AutoresizingMask = NSViewResizingMask.WidthSizable;
        view.AddSubview (view.TextField);
        view.Identifier = tableColumn.Title;
        view.TextField.BackgroundColor = NSColor.Clear;
        view.TextField.Bordered = false;
        view.TextField.Selectable = false;
        view.TextField.Editable = !product.IsProductGroup;
    }

    // Tag view
    view.TextField.Tag = outlineView.RowForItem (item);

    // Allow for edit
    view.TextField.EditingEnded += (sender, e) => {

        // Grab product
        var prod = outlineView.ItemAtRow(view.Tag) as Product;

        // Take action based on type
        switch(view.Identifier) {
        case "Product":
            prod.Title = view.TextField.StringValue;
            break;
        case "Details":
            prod.Description = view.TextField.StringValue;
            break;
        }
    };

    // Setup view based on the column selected
    switch (tableColumn.Title) {
    case "Product":
        view.ImageView.Image = NSImage.ImageNamed (product.IsProductGroup ? "tags.png" : "tag.png");
        view.TextField.StringValue = product.Title;
        break;
    case "Details":
        view.TextField.StringValue = product.Description;
        break;
    }

    return view;
}

如需詳細資訊,請參閱使用影像檔的<使用影像與大綱檢視>一節。

數據系結大綱檢視

藉由在 Xamarin.Mac 應用程式中使用索引鍵/值編碼和數據系結技術,您可以大幅減少您必須撰寫和維護的程式碼數量,以填入和使用 UI 元素。 您也可以從前端使用者介面(Model-View-Controller)進一步分離備份數據(數據模型),進而更輕鬆地維護、更有彈性的應用程式設計。

索引鍵/值編碼 (KVC) 是間接存取物件屬性的機制,使用索引鍵(特別格式化的字串)來識別屬性,而不是透過實例變數或存取子方法存取它們。get/set 藉由在 Xamarin.Mac 應用程式中實作 Key-Value Code 相容存取子,您可以存取其他 macOS 功能,例如 Key-Value Observing (KVO)、數據系結、核心數據、Cocoa 系結和可腳本性。

如需詳細資訊,請參閱數據系結和索引鍵/值編碼檔的大綱檢視數據系結一節。

摘要

本文已詳細探討在 Xamarin.Mac 應用程式中使用大綱檢視。 我們看到了大綱檢視的不同類型和用法、如何在 Xcode 的介面產生器中建立和維護大綱檢視,以及如何在 C# 程式代碼中使用大綱檢視。