Xamarin.Mac のアウトライン ビュー

この記事では、Xamarin.Mac アプリケーションでのアウトライン ビューの操作について説明します。 ここでは、Xcode と Interface Builder でアウトライン ビューを作成および管理し、プログラムで操作する方法について説明します。

Xamarin.Mac アプリケーションで C# と .NET を操作する場合、開発者と Xcode で作業しているのと同じアウトライン ビューにObjective-Cアクセスできます。 Xamarin.Mac は Xcode と直接統合されるため、Xcode の Interface Builder を使用してアウトライン ビューを作成および管理できます (または必要に応じて、C# コードで直接作成することもできます)。

アウトライン ビューは、ユーザーが階層データの行を展開または折りたたみできるようにするテーブルの一種です。 テーブル ビューと同様に、アウトライン ビューには関連アイテムのセットのデータが表示され、行は個々のアイテムを表し、列はそれらのアイテムの属性を表します。 テーブル ビューとは異なり、アウトライン ビュー内のアイテムはフラット リストに含まれていないため、ハード ドライブ上のファイルやフォルダーなどの階層に整理されます。

アプリの実行例

この記事では、Xamarin.Mac アプリケーションでのアウトライン ビューの操作の基本について説明します。 この記事で使用する主要な概念と手法について説明するため 、まず Hello、Mac の記事、特 に Xcode とインターフェイス ビルダーアウトレットとアクション の概要に関するセクションを使用することを強くお勧めします。

Xamarin.Mac Internals ドキュメントの「C# クラス/メソッドをに公開するObjective-C」セクションも参照してください。C# クラスObjective-Cをオブジェクトと UI 要素に結び付けるために使用される コマンドと Export コマンドについても説明Registerします。

アウトライン ビューの概要

アウトライン ビューは、ユーザーが階層データの行を展開または折りたたみできるようにするテーブルの一種です。 テーブル ビューと同様に、アウトライン ビューには関連アイテムのセットのデータが表示され、行は個々のアイテムを表し、列はそれらのアイテムの属性を表します。 テーブル ビューとは異なり、アウトライン ビュー内のアイテムはフラット リストに含まれていないため、ハード ドライブ上のファイルやフォルダーなどの階層に整理されます。

アウトライン ビューのアイテムに他のアイテムが含まれている場合は、ユーザーが展開または折りたたむことができます。 展開可能な項目には開閉用三角形が表示されます。この三角形は、アイテムが折りたたまれているときに右を指し、項目が展開されたときに下を指します。 開閉用三角形をクリックすると、項目が展開または折りたたみます。

アウトライン ビュー (NSOutlineView) はテーブル ビュー (NSTableView) のサブクラスであるため、その動作の多くは親クラスから継承されます。 その結果、行または列の選択、列ヘッダーのドラッグによる列の再配置など、テーブル ビューでサポートされる多くの操作もアウトライン ビューでサポートされます。 Xamarin.Mac アプリケーションは、これらの機能を制御でき、アウトライン ビューのパラメーター (コードまたはインターフェイス ビルダー) を構成して、特定の操作を許可または禁止できます。

アウトライン ビューでは、独自のデータは格納されません。代わりに、データ ソース (NSOutlineViewDataSource) に依存して、必要に応じて必要な行と列の両方を提供します。

アウトライン ビューの動作は、アウトライン ビュー デリゲート (NSOutlineViewDelegate) のサブクラスを提供して、アウトライン列の管理をサポートし、種類を指定して機能を選択し、行の選択と編集、カスタム追跡、および個々の列と行のカスタム ビューを提供することでカスタマイズできます。

アウトライン ビューは、その動作と機能の多くをテーブル ビューと共有しているため、この記事を続行する前に 、テーブル ビュー に関するドキュメントを参照してください。

Xcode でのアウトライン ビューの作成と管理

新しい Xamarin.Mac Cocoa アプリケーションを作成すると、既定で標準の空白のウィンドウが表示されます。 このウィンドウは、プロジェクトに .storyboard 自動的に含まれるファイルで定義されます。 Windows デザインを編集するには、ソリューション エクスプローラーでファイルをMain.storyboardダブルクリックします。

メインストーリーボードの選択

これにより、Xcode のインターフェイス ビルダーでウィンドウ デザインが開きます。

Xcode での UI の編集

[ライブラリ インスペクター] の検索ボックスに「」と入力outlineすると、アウトライン ビュー コントロールを簡単に見つけることができます。

ライブラリからアウトライン ビューを選択する

アウトライン ビューを インターフェイス エディターのビュー コントローラーにドラッグし、ビュー コントローラーのコンテンツ領域を塗りつぶし、 制約エディターのウィンドウと共に縮小して拡大する場所に設定します。

制約の編集

インターフェイス階層でアウトライン ビューを選択すると、属性インスペクターで次のプロパティを使用できます。

[属性インスペクター] で使用できるプロパティを示すスクリーンショット。

  • アウトライン列 - 階層データが表示されるテーブル列。
  • [アウトライン列の自動保存 ] - の場合 true、アウトライン列はアプリケーションの実行間に自動的に保存および復元されます。
  • インデント - 展開された項目の下の列をインデントする量。
  • インデントはセルの後 - の場合 true、インデント マークはセルと共にインデントされます。
  • [展開されたアイテムの自動保存] - の場合 true、項目の展開/折りたたまれた状態は、アプリケーションの実行中に自動的に保存および復元されます。
  • コンテンツ モード - ビュー () またはセル (NSViewNSCell) を使用して、行と列にデータを表示できます。 macOS 10.7 以降では、Views を使用する必要があります。
  • Floats Group Rows - の場合 true、テーブル ビューでは、グループ化されたセルがフローティングであるかのように描画されます。
  • - 表示される列の数を定義します。
  • ヘッダー - の場合 true、列にはヘッダーが含まれます。
  • 並べ替え - の場合 true、ユーザーはテーブル内の列をドラッグして並べ替えることができます。
  • サイズ変更 - の場合 true、ユーザーは列ヘッダーをドラッグして列のサイズを変更できます。
  • 列のサイズ設定 - テーブルで列のサイズを自動設定する方法を制御します。
  • 強調表示 - セルの選択時に表が使用する強調表示の種類を制御します。
  • 代替行 - の場合 true、他の行の背景色が異なります。
  • [水平グリッド ] - セル間に水平方向に描画される罫線の種類を選択します。
  • 垂直グリッド - セル間に垂直方向に描画される罫線の種類を選択します。
  • グリッドの色 - セルの罫線の色を設定します。
  • 背景 - セルの背景色を設定します。
  • 選択 - ユーザーがテーブル内のセルを次のように選択する方法を制御できます。
    • 複数 - の場合 true、ユーザーは複数の行と列を選択できます。
    • - の場合 true、ユーザーは列を選択できます。
    • 「Select 」と入力する - の場合 true、ユーザーは文字を入力して行を選択できます。
    • - の場合 true、ユーザーは行または列を選択する必要はありません。テーブルでは、まったく選択できません。
  • 自動保存 - テーブル形式が自動的に保存される名前。
  • 列情報 - の場合 true、列の順序と幅が自動的に保存されます。
  • [改行] - セルで改行を処理する方法を選択します。
  • [最後に表示される行を切り捨てる ] - の場合 true、セルはデータ内で切り捨てられ、境界内に収まりません。

重要

従来の Xamarin.Mac アプリケーションを維持している場合を除き、 NSView ベースのアウトライン ビューはベースのテーブル ビューで NSCell 使用する必要があります。 NSCell はレガシと見なされ、今後サポートされない場合があります。

インターフェイス階層でテーブル列を選択すると、属性インスペクターで次のプロパティを使用できます。

[属性インスペクター] で選択したテーブル列で使用できるプロパティを示すスクリーンショット。

  • Title - 列のタイトルを設定します。
  • [配置 ] - セル内のテキストの配置を設定します。
  • タイトル フォント - セルのヘッダー テキストのフォントを選択します。
  • 並べ替えキー - 列のデータを並べ替えるために使用されるキーです。 ユーザーがこの列を並べ替えることができない場合は、空白のままにします。
  • セレクター - 並べ替えを実行するために使用される アクション です。 ユーザーがこの列を並べ替えることができない場合は、空白のままにします。
  • Order - 列データの並べ替え順序です。
  • サイズ変更 - 列のサイズ変更の種類を選択します。
  • 編集可能 - の場合 true、ユーザーはセル ベースのテーブル内のセルを編集できます。
  • Hidden - の場合 true、列は非表示になります。

また、ハンドル (列の右側を垂直方向に中央揃え) を左または右にドラッグして、列のサイズを変更することもできます。

テーブル ビューの各列を選択し、最初の列に の TitleProduct と 2 番目 Detailsの列を指定します。

インターフェイス階層でテーブル セル ビュー (NSTableViewCell) を選択すると、属性インスペクターで次のプロパティを使用できます。

[属性インスペクター] で選択したテーブル セルで使用できるプロパティを示すスクリーンショット。

これらはすべて標準ビューのプロパティです。 この列の行のサイズを変更することもできます。

インターフェイス階層で [テーブル ビュー] セル (既定では 、 NSTextField) を選択し、属性インスペクターで次のプロパティを使用できます。

[属性インスペクター] で選択したテーブル ビュー セルで使用できるプロパティを示すスクリーンショット。

ここでは、標準のテキスト フィールドのすべてのプロパティを設定できます。 既定では、標準のテキスト フィールドを使用して、列内のセルのデータを表示します。

インターフェイス階層でテーブル セル ビュー (NSTableFieldCell) を選択すると、属性インスペクターで次のプロパティを使用できます。

選択したテーブル ビュー セルで使用できるプロパティを示すスクリーンショット。

ここで最も重要な設定は次のとおりです。

  • レイアウト - この列のセルのレイアウト方法を選択します。
  • 単一行モードを使用 する - の場合 true、セルは 1 行に制限されます。
  • First Runtime Layout Width - の場合 true、アプリケーションの初回実行時にセルが表示されるときに、セルに設定された幅 (手動または自動) が優先されます。
  • Action - セルに対して編集 アクション が送信されるタイミングを制御します。
  • 動作 - セルが選択可能か編集可能か定義します。
  • リッチ テキスト - の場合 true、セルには書式設定されたテキストとスタイル設定されたテキストを表示できます。
  • 元に戻す - の場合 true、セルは元に戻す動作の責任を負います。

インターフェイス階層のテーブル列の下部にあるテーブル セル ビュー (NSTableFieldCell) を選択します。

テーブル セル ビューの選択

これにより、特定の列に対して作成されたすべてのセルの基本 パターン として使用されるテーブル セル ビューを編集できます。

アクションとアウトレットの追加

他の Cocoa UI コントロールと同様に、(必要な機能に基づいて) ActionsOutlets を使用して、アウトライン ビューとその列とセルを C# コードに公開する必要があります。

このプロセスは、公開するアウトライン ビュー要素と同じです。

  1. アシスタント エディターに切り替え、ファイルがViewController.h選択されていることを確認します。

    正しい .h ファイルの選択

  2. インターフェイス階層からアウトライン ビューを選択し、control キーを押しながらクリックしてファイルにViewController.hドラッグします。

  3. アウトライン ビューの アウトレット を という名前 ProductOutlineで作成します。

    属性インスペクターの ProductOutline というアウトレットを示すスクリーンショット。

  4. テーブル列のアウトレットを作成し、 と DetailsColumnと呼びますProductColumn

    [属性インスペクター] の 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 、ビュー (データ) を返して、give 列と行のセルを表示します。 可能であれば、新しいビューを作成する必要がない場合は、既存のビューを再利用してセルを表示します。

アウトラインを設定するには、ファイルを 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、[並べ替えキー] に「」と入力Titleし、[ compare:セレクター] に「Order」を選択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 メソッドは、列見出しをクリックするたびに呼び出されます。 インターフェイス ビルダーで設定した キー 値と、その列の並べ替え順序が渡されます。

アプリケーションを実行し、[列ヘッダー] をクリックすると、その列で行が並べ替えられます。

並べ替えられた出力の例

行の選択

ユーザーが 1 つの行を選択できるようにする場合は、ファイルを 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 ダブルクリックして開き、インターフェイス ビルダーで編集します。 [インターフェイス階層] の [アウトライン ビュー] を選択し、[属性インスペクター] の [複数] チェックボックスをチェックします。

[属性インスペクター] を示すスクリーンショット。[複数] を選択できます。

変更を保存し、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の一部として画像を含めるには、一般的な NSTextFieldではなく を使用NSTableCellViewするようにアウトライン ビューの NSTableViewDelegate'sGetView メソッドによってデータが返される方法を変更する必要があります。 次に例を示します。

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 アプリケーションでKey-Valueコーディングとデータ バインディングの手法を使用すると、UI 要素を設定して操作するために記述および維持する必要があるコードの量を大幅に減らすことができます。 また、バッキング データ (データ モデル) をフロントエンド ユーザー インターフェイス (Model-View-Controller) からさらに切り離すことで、保守が容易になり、より柔軟なアプリケーション設計が可能になるという利点もあります。

Key-Valueコーディング (KVC) は、インスタンス変数またはアクセサー メソッド () を介してアクセスするのではなく、キー (特別に書式設定された文字列) を使用してプロパティを識別して、オブジェクトのプロパティに間接的にアクセスするためのメカニズムですget/set。 Xamarin.Mac アプリケーションKey-Valueコーディングに準拠したアクセサーを実装することで、Key-Value Observing (KVO)、データ バインディング、コア データ、Cocoa バインディング、スクリプト機能などの他の macOS 機能にアクセスできます。

詳細については、 データ バインディングと Key-Value コーディングに関するドキュメントのアウトライン ビュー のデータ バインディング に関するセクションを参照してください。

まとめ

この記事では、Xamarin.Mac アプリケーションでのアウトライン ビューの操作について詳しく説明しました。 アウトライン ビューのさまざまな種類と使用方法、Xcode のインターフェイス ビルダーでアウトライン ビューを作成および管理する方法、および C# コードでアウトライン ビューを操作する方法について説明しました。