Udostępnij za pośrednictwem


Kopiowanie i wklejanie na platformie Xamarin.Mac

W tym artykule opisano pracę z tablicą wklejaną w celu zapewnienia kopiowania i wklejania w aplikacji platformy Xamarin.Mac. Pokazuje on, jak pracować ze standardowymi typami danych, które mogą być współużytkowane przez wiele aplikacji i jak obsługiwać dane niestandardowe w ramach danej aplikacji.

Omówienie

Podczas pracy z językiem C# i platformą .NET w aplikacji platformy Xamarin.Mac masz dostęp do tej samej tablicy wklejanej (kopiowania i wklejania) obsługiwanej przez dewelopera działającego w Objective-C programie.

W tym artykule omówimy dwa główne sposoby korzystania z tablicy wklejanej w aplikacji platformy Xamarin.Mac:

  1. Standardowe typy danych — ponieważ operacje na tablicy wklejanej są zwykle wykonywane między dwiema niepowiązanymi aplikacjami, żadna z aplikacji nie zna typów danych, które obsługują inne aplikacje. Aby zmaksymalizować potencjał udostępniania, tablica wklejana może przechowywać wiele reprezentacji danego elementu (przy użyciu standardowego zestawu typowych typów danych), dzięki czemu aplikacja korzystająca będzie mogła wybrać wersję najlepiej dopasowaną do swoich potrzeb.
  2. Dane niestandardowe — aby obsługiwać kopiowanie i wklejanie złożonych danych na platformie Xamarin.Mac, można zdefiniować niestandardowy typ danych, który będzie obsługiwany przez tablicę wklejania. Na przykład aplikacja do rysowania wektorowego, która umożliwia użytkownikowi kopiowanie i wklejanie złożonych kształtów składających się z wielu typów danych i punktów.

Przykład uruchomionej aplikacji

W tym artykule omówimy podstawy pracy z tablicą wklejaną w aplikacji Xamarin.Mac w celu obsługi operacji kopiowania i wklejania. 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ę z sekcją Uwidacznianie klas/metod Objective-C języka C# w sekcji dokumentu Xamarin.Mac Internals , a także objaśnienie Register atrybutów i Export używanych do podłączania klas języka C# do Objective-C obiektów i elementów interfejsu użytkownika.

Wprowadzenie do wklejania

Tablica wklejania przedstawia ustandaryzowany mechanizm wymiany danych w danej aplikacji lub między aplikacjami. Typowym zastosowaniem funkcji wklejania w aplikacji platformy Xamarin.Mac jest obsługa operacji kopiowania i wklejania, jednak obsługiwane są również różne inne operacje (takie jak przeciąganie i upuszczanie i usługi aplikacji).

Aby szybko rozpocząć od prostego, praktyczne wprowadzenie do korzystania z tablic wklejanych w aplikacji Xamarin.Mac. Później przedstawimy szczegółowe wyjaśnienie sposobu działania tablicy wklejanej i używanych metod.

W tym przykładzie utworzymy prostą aplikację opartą na dokumentach, która zarządza oknem zawierającym widok obrazu. Użytkownik będzie mógł kopiować i wklejać obrazy między dokumentami w aplikacji i do lub z innych aplikacji lub z wielu okien wewnątrz tej samej aplikacji.

Tworzenie projektu platformy Xamarin

Najpierw utworzymy nową aplikację platformy Xamarin.Mac opartą na dokumencie, dla którego dodamy obsługę kopiowania i wklejania.

Należy wykonać następujące czynności:

  1. Uruchom Visual Studio dla komputerów Mac i kliknij link Nowy projekt....

  2. Wybierz pozycję Aplikacja Cocoa aplikacji Dla komputerów >Mac>, a następnie kliknij przycisk Dalej:

    Tworzenie nowego projektu aplikacji Cocoa

  3. Wprowadź MacCopyPaste wartość w polu Nazwa projektu i pozostaw wszystko inne jako domyślne. Kliknij przycisk Dalej:

    Ustawianie nazwy projektu

  4. Kliknij przycisk Utwórz:

    Potwierdzanie nowych ustawień projektu

Dodawanie dokumentu NSDocument

Następnie dodamy klasę niestandardową NSDocument , która będzie działać jako magazyn w tle dla interfejsu użytkownika aplikacji. Będzie zawierać pojedynczy widok obrazu i wiedzieć, jak skopiować obraz z widoku do domyślnego tablicy wklejanej oraz jak pobrać obraz z domyślnej tablicy wklejanej i wyświetlić go w widoku obrazu.

Kliknij prawym przyciskiem myszy projekt Xamarin.Mac w okienku rozwiązania i wybierz polecenie Dodaj>nowy plik.:

Dodawanie dokumentu NSDocument do projektu

Wprowadź ImageDocument nazwę i kliknij przycisk Nowy. Zmodyfikuj klasę ImageDocument.cs i ustaw ją tak:

using System;
using AppKit;
using Foundation;
using ObjCRuntime;

namespace MacCopyPaste
{
    [Register("ImageDocument")]
    public class ImageDocument : NSDocument
    {
        #region Computed Properties
        public NSImageView ImageView {get; set;}

        public ImageInfo Info { get; set; } = new ImageInfo();

        public bool ImageAvailableOnPasteboard {
            get {
                // Initialize the pasteboard
                NSPasteboard pasteboard = NSPasteboard.GeneralPasteboard;
                Class [] classArray  = { new Class ("NSImage") };

                // Check to see if an image is on the pasteboard
                return pasteboard.CanReadObjectForClasses (classArray, null);
            }
        }
        #endregion

        #region Constructor
        public ImageDocument ()
        {
        }
        #endregion

        #region Public Methods
        [Export("CopyImage:")]
        public void CopyImage(NSObject sender) {

            // Grab the current image
            var image = ImageView.Image;

            // Anything to process?
            if (image != null) {
                // Get the standard pasteboard
                var pasteboard = NSPasteboard.GeneralPasteboard;

                // Empty the current contents
                pasteboard.ClearContents();

                // Add the current image to the pasteboard
                pasteboard.WriteObjects (new NSImage[] {image});

                // Save the custom data class to the pastebaord
                pasteboard.WriteObjects (new ImageInfo[] { Info });

                // Using a Pasteboard Item
                NSPasteboardItem item = new NSPasteboardItem();
                string[] writableTypes = {"public.text"};

                // Add a data provier to the item
                ImageInfoDataProvider dataProvider = new ImageInfoDataProvider (Info.Name, Info.ImageType);
                var ok = item.SetDataProviderForTypes (dataProvider, writableTypes);

                // Save to pasteboard
                if (ok) {
                    pasteboard.WriteObjects (new NSPasteboardItem[] { item });
                }
            }

        }

        [Export("PasteImage:")]
        public void PasteImage(NSObject sender) {

            // Initialize the pasteboard
            NSPasteboard pasteboard = NSPasteboard.GeneralPasteboard;
            Class [] classArray  = { new Class ("NSImage") };

            bool ok = pasteboard.CanReadObjectForClasses (classArray, null);
            if (ok) {
                // Read the image off of the pasteboard
                NSObject [] objectsToPaste = pasteboard.ReadObjectsForClasses (classArray, null);
                NSImage image = (NSImage)objectsToPaste[0];

                // Display the new image
                ImageView.Image = image;
            }

            Class [] classArray2 = { new Class ("ImageInfo") };
            ok = pasteboard.CanReadObjectForClasses (classArray2, null);
            if (ok) {
                // Read the image off of the pasteboard
                NSObject [] objectsToPaste = pasteboard.ReadObjectsForClasses (classArray2, null);
                ImageInfo info = (ImageInfo)objectsToPaste[0];

            }

        }
        #endregion
    }
}

Przyjrzyjmy się szczegółowo niektórym kodom poniżej.

Poniższy kod udostępnia właściwość do testowania istnienia danych obrazu na domyślnym tablicy wklejanej, jeśli obraz jest dostępny, true jest zwracany w przeciwnym razie false:

public bool ImageAvailableOnPasteboard {
    get {
        // Initialize the pasteboard
        NSPasteboard pasteboard = NSPasteboard.GeneralPasteboard;
        Class [] classArray  = { new Class ("NSImage") };

        // Check to see if an image is on the pasteboard
        return pasteboard.CanReadObjectForClasses (classArray, null);
    }
}

Poniższy kod kopiuje obraz z dołączonego widoku obrazu do domyślnego tablicy wklejanej:

[Export("CopyImage:")]
public void CopyImage(NSObject sender) {

    // Grab the current image
    var image = ImageView.Image;

    // Anything to process?
    if (image != null) {
        // Get the standard pasteboard
        var pasteboard = NSPasteboard.GeneralPasteboard;

        // Empty the current contents
        pasteboard.ClearContents();

        // Add the current image to the pasteboard
        pasteboard.WriteObjects (new NSImage[] {image});

        // Save the custom data class to the pastebaord
        pasteboard.WriteObjects (new ImageInfo[] { Info });

        // Using a Pasteboard Item
        NSPasteboardItem item = new NSPasteboardItem();
        string[] writableTypes = {"public.text"};

        // Add a data provider to the item
        ImageInfoDataProvider dataProvider = new ImageInfoDataProvider (Info.Name, Info.ImageType);
        var ok = item.SetDataProviderForTypes (dataProvider, writableTypes);

        // Save to pasteboard
        if (ok) {
            pasteboard.WriteObjects (new NSPasteboardItem[] { item });
        }
    }

}

Poniższy kod wkleja obraz z domyślnego tablicy wklejanej i wyświetla go w dołączonym widoku obrazu (jeśli tablica wklejania zawiera prawidłowy obraz):

[Export("PasteImage:")]
public void PasteImage(NSObject sender) {

    // Initialize the pasteboard
    NSPasteboard pasteboard = NSPasteboard.GeneralPasteboard;
    Class [] classArray  = { new Class ("NSImage") };

    bool ok = pasteboard.CanReadObjectForClasses (classArray, null);
    if (ok) {
        // Read the image off of the pasteboard
        NSObject [] objectsToPaste = pasteboard.ReadObjectsForClasses (classArray, null);
        NSImage image = (NSImage)objectsToPaste[0];

        // Display the new image
        ImageView.Image = image;
    }

    Class [] classArray2 = { new Class ("ImageInfo") };
    ok = pasteboard.CanReadObjectForClasses (classArray2, null);
    if (ok) {
        // Read the image off of the pasteboard
        NSObject [] objectsToPaste = pasteboard.ReadObjectsForClasses (classArray2, null);
        ImageInfo info = (ImageInfo)objectsToPaste[0]
    }
}

W tym dokumencie utworzymy interfejs użytkownika dla aplikacji Xamarin.Mac.

Kompilowanie interfejsu użytkownika

Kliknij dwukrotnie plik Main.storyboard, aby otworzyć go w programie Xcode. Następnie dodaj pasek narzędzi i obraz oraz skonfiguruj je w następujący sposób:

Edytowanie paska narzędzi

Dodaj kopię i wklej element paska narzędzi obrazu po lewej stronie paska narzędzi. Użyjemy tych skrótów, aby skopiować i wkleić z menu Edycja. Następnie dodaj cztery elementy paska narzędzi obrazów po prawej stronie paska narzędzi. Użyjemy tych elementów, aby wypełnić obraz dobrze niektórymi domyślnymi obrazami.

Aby uzyskać więcej informacji na temat pracy z paskami narzędzi, zobacz dokumentację pasków narzędzi.

Następnie uwidocznimy następujące punkty i akcje dla naszych elementów paska narzędzi i źródła obrazu:

Tworzenie gniazd i akcji

Aby uzyskać więcej informacji na temat pracy z placówkami i akcjami, zobacz sekcję Placówki i akcje w naszej dokumentacji Hello, Mac .

Włączanie interfejsu użytkownika

Dzięki interfejsowi użytkownika utworzonemu w środowisku Xcode i naszemu elementowi interfejsu użytkownika uwidocznionemu za pośrednictwem placówek i akcji musimy dodać kod, aby włączyć interfejs użytkownika. Kliknij dwukrotnie plik ImageWindow.cs w okienku rozwiązania i utwórz go w następujący sposób:

using System;
using Foundation;
using AppKit;

namespace MacCopyPaste
{
    public partial class ImageWindow : NSWindow
    {
        #region Private Variables
        ImageDocument document;
        #endregion

        #region Computed Properties
        [Export ("Document")]
        public ImageDocument Document {
            get {
                return document;
            }
            set {
                WillChangeValue ("Document");
                document = value;
                DidChangeValue ("Document");
            }
        }

        public ViewController ImageViewController {
            get { return ContentViewController as ViewController; }
        }

        public NSImage Image {
            get {
                return ImageViewController.Image;
            }
            set {
                ImageViewController.Image = value;
            }
        }
        #endregion

        #region Constructor
        public ImageWindow (IntPtr handle) : base (handle)
        {
        }
        #endregion

        #region Override Methods
        public override void AwakeFromNib ()
        {
            base.AwakeFromNib ();

            // Create a new document instance
            Document = new ImageDocument ();

            // Attach to image view
            Document.ImageView = ImageViewController.ContentView;
        }
        #endregion

        #region Public Methods
        public void CopyImage (NSObject sender)
        {
            Document.CopyImage (sender);
        }

        public void PasteImage (NSObject sender)
        {
            Document.PasteImage (sender);
        }

        public void ImageOne (NSObject sender)
        {
            // Load image
            Image = NSImage.ImageNamed ("Image01.jpg");

            // Set image info
            Document.Info.Name = "city";
            Document.Info.ImageType = "jpg";
        }

        public void ImageTwo (NSObject sender)
        {
            // Load image
            Image = NSImage.ImageNamed ("Image02.jpg");

            // Set image info
            Document.Info.Name = "theater";
            Document.Info.ImageType = "jpg";
        }

        public void ImageThree (NSObject sender)
        {
            // Load image
            Image = NSImage.ImageNamed ("Image03.jpg");

            // Set image info
            Document.Info.Name = "keyboard";
            Document.Info.ImageType = "jpg";
        }

        public void ImageFour (NSObject sender)
        {
            // Load image
            Image = NSImage.ImageNamed ("Image04.jpg");

            // Set image info
            Document.Info.Name = "trees";
            Document.Info.ImageType = "jpg";
        }
        #endregion
    }
}

Przyjrzyjmy się temu kodowi szczegółowo poniżej.

Najpierw uwidaczniamy wystąpienie klasy utworzonej ImageDocument powyżej:

private ImageDocument _document;
...

[Export ("Document")]
public ImageDocument Document {
    get { return _document; }
    set {
        WillChangeValue ("Document");
        _document = value;
        DidChangeValue ("Document");
    }
}

Za pomocą parametrów ExportWillChangeValueDocument i DidChangeValueskonfigurowaliśmy właściwość , aby umożliwić kodowanie klucz-wartość i powiązanie danych w programie Xcode.

Uwidaczniamy również obraz z poziomu obrazu dodanego do interfejsu użytkownika w środowisku Xcode za pomocą następującej właściwości:

public ViewController ImageViewController {
    get { return ContentViewController as ViewController; }
}

public NSImage Image {
    get {
        return ImageViewController.Image;
    }
    set {
        ImageViewController.Image = value;
    }
}

Po załadowaniu i wyświetleniu okna głównego utworzymy wystąpienie klasy ImageDocument i dołączymy do niego obraz interfejsu użytkownika za pomocą następującego kodu:

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

    // Create a new document instance
    Document = new ImageDocument ();

    // Attach to image view
    Document.ImageView = ImageViewController.ContentView;
}

Na koniec w odpowiedzi na kliknięcie przez użytkownika elementów paska narzędzi kopiowania i wklejania wywołujemy wystąpienie ImageDocument klasy, aby wykonać rzeczywistą pracę:

partial void CopyImage (NSObject sender) {
    Document.CopyImage(sender);
}

partial void PasteImage (Foundation.NSObject sender) {
    Document.PasteImage(sender);
}

Włączanie menu Plik i Edycja

Ostatnią czynnością, którą musimy zrobić, jest włączenie elementu menu Nowy z menu Plik (aby utworzyć nowe wystąpienia okna głównego) oraz włączenie elementów menu Wycinanie, Kopiowanie i wklejanie z menu Edycja .

Aby włączyć element menu Nowy, zmodyfikuj plik AppDelegate.cs i dodaj następujący kod:

public int UntitledWindowCount { get; set;} =1;
...

[Export ("newDocument:")]
void NewDocument (NSObject sender) {
    // Get new window
    var storyboard = NSStoryboard.FromName ("Main", null);
    var controller = storyboard.InstantiateControllerWithIdentifier ("MainWindow") as NSWindowController;

    // Display
    controller.ShowWindow(this);

    // Set the title
    controller.Window.Title = (++UntitledWindowCount == 1) ? "untitled" : string.Format ("untitled {0}", UntitledWindowCount);
}

Aby uzyskać więcej informacji, zobacz sekcję Praca z wieloma systemami Windows w naszej dokumentacji systemu Windows .

Aby włączyć elementy menu Wycinanie, kopiowanie i wklejanie, zmodyfikuj plik AppDelegate.cs i dodaj następujący kod:

[Export("copy:")]
void CopyImage (NSObject sender)
{
    // Get the main window
    var window = NSApplication.SharedApplication.KeyWindow as ImageWindow;

    // Anything to do?
    if (window == null)
        return;

    // Copy the image to the clipboard
    window.Document.CopyImage (sender);
}

[Export("cut:")]
void CutImage (NSObject sender)
{
    // Get the main window
    var window = NSApplication.SharedApplication.KeyWindow as ImageWindow;

    // Anything to do?
    if (window == null)
        return;

    // Copy the image to the clipboard
    window.Document.CopyImage (sender);

    // Clear the existing image
    window.Image = null;
}

[Export("paste:")]
void PasteImage (NSObject sender)
{
    // Get the main window
    var window = NSApplication.SharedApplication.KeyWindow as ImageWindow;

    // Anything to do?
    if (window == null)
        return;

    // Paste the image from the clipboard
    window.Document.PasteImage (sender);
}

Dla każdego elementu menu otrzymujemy bieżące, najważniejsze, kluczowe okno i rzutujemy je do klasy ImageWindow :

var window = NSApplication.SharedApplication.KeyWindow as ImageWindow;

W tym miejscu wywołujemy ImageDocument wystąpienie klasy tego okna w celu obsługi akcji kopiowania i wklejania. Na przykład:

window.Document.CopyImage (sender);

Chcemy , aby elementy menu Wycinanie, kopiowanie i wklejanie były dostępne tylko wtedy, gdy dane obrazu znajdują się w domyślnym tablicy wklejanej lub w obszarze obrazu bieżącego aktywnego okna.

Dodajmy plik EditMenuDelegate.cs do projektu Xamarin.Mac i utwórzmy go w następujący sposób:

using System;
using AppKit;

namespace MacCopyPaste
{
    public class EditMenuDelegate : NSMenuDelegate
    {
        #region Override Methods
        public override void MenuWillHighlightItem (NSMenu menu, NSMenuItem item)
        {
        }

        public override void NeedsUpdate (NSMenu menu)
        {
            // Get list of menu items
            NSMenuItem[] Items = menu.ItemArray ();

            // Get the key window and determine if the required images are available
            var window = NSApplication.SharedApplication.KeyWindow as ImageWindow;
            var hasImage = (window != null) && (window.Image != null);
            var hasImageOnPasteboard = (window != null) && window.Document.ImageAvailableOnPasteboard;

            // Process every item in the menu
            foreach(NSMenuItem item in Items) {
                // Take action based on the menu title
                switch (item.Title) {
                case "Cut":
                case "Copy":
                case "Delete":
                    // Only enable if there is an image in the view
                    item.Enabled = hasImage;
                    break;
                case "Paste":
                    // Only enable if there is an image on the pasteboard
                    item.Enabled = hasImageOnPasteboard;
                    break;
                default:
                    // Only enable the item if it has a sub menu
                    item.Enabled = item.HasSubmenu;
                    break;
                }
            }
        }
        #endregion
    }
}

Ponownie uzyskamy bieżące, najważniejsze okno i użyjemy jego ImageDocument wystąpienia klasy, aby sprawdzić, czy istnieją wymagane dane obrazu. Następnie użyjemy MenuWillHighlightItem metody , aby włączyć lub wyłączyć każdy element na podstawie tego stanu.

Zmodyfikuj plik AppDelegate.cs i utwórz metodę DidFinishLaunching podobną do następującej:

public override void DidFinishLaunching (NSNotification notification)
{
    // Disable automatic item enabling on the Edit menu
    EditMenu.AutoEnablesItems = false;
    EditMenu.Delegate = new EditMenuDelegate ();
}

Najpierw wyłączamy automatyczne włączanie i wyłączanie elementów menu w menu Edycja. Następnie dołączymy wystąpienie klasy utworzonej EditMenuDelegate powyżej.

Aby uzyskać więcej informacji, zobacz dokumentację menu .

Testowanie aplikacji

Wszystko jest gotowe do przetestowania aplikacji. Skompiluj i uruchom aplikację oraz zostanie wyświetlony główny interfejs:

Uruchamianie aplikacji

Jeśli otworzysz menu Edycja, pamiętaj, że opcja Wycinanie, kopiowanie i wklejanie jest wyłączona, ponieważ nie ma obrazu w obszarze obrazu lub w domyślnym wklejaniu:

Otwieranie menu Edycja

Jeśli dodasz obraz do źródła obrazu i ponownie otworzysz menu Edycja, elementy zostaną teraz włączone:

Pokazywanie elementów menu Edycja jest włączone

Jeśli skopiujesz obraz i wybierzesz pozycję Nowy z menu pliku, możesz wkleić ten obraz do nowego okna:

Wklejanie obrazu do nowego okna

W poniższych sekcjach przyjrzymy się szczegółowo pracy z tablicą wklejaną w aplikacji Xamarin.Mac.

Informacje o tablicy wkleja

W systemie macOS (wcześniej znanym jako OS X) wklejanie (NSPasteboard) zapewnia obsługę kilku procesów serwera, takich jak kopiowanie i wklejanie, przeciąganie i upuszczanie i usługi aplikacji. W poniższych sekcjach przyjrzymy się bliżej kilku kluczowych pojęć dotyczących tablicy wklejanej.

Co to jest tablica wklejania?

Klasa NSPasteboard zapewnia ustandaryzowany mechanizm wymiany informacji między aplikacjami lub w danej aplikacji. Główną funkcją tablicy wklejanej jest obsługa operacji kopiowania i wklejania:

  1. Gdy użytkownik wybierze element w aplikacji i używa elementu menu Wytnij lub Kopiuj , co najmniej jedna reprezentacja wybranego elementu zostanie umieszczona w tablicy wklejanej.
  2. Gdy użytkownik używa elementu menu Wklej (w ramach tej samej aplikacji lub innej), wersja danych, które może obsłużyć, jest kopiowana z tablicy wklejanej i dodawana do aplikacji.

Mniej oczywiste zastosowania tablicy wklejań obejmują operacje znajdowania, przeciągania, przeciągania i upuszczania oraz usług aplikacji:

  • Gdy użytkownik inicjuje operację przeciągania, dane przeciągania są kopiowane do tablicy wklejanej. Jeśli operacja przeciągania kończy się upuszczaniem do innej aplikacji, aplikacja kopiuje dane z tablicy wklejanej.
  • W przypadku usług tłumaczenia dane do tłumaczenia są kopiowane do tablicy wklejającej przez żądającą aplikację. Usługa aplikacji, pobiera dane z tablicy wklejanej, wykonuje tłumaczenie, a następnie wkleja dane z powrotem do tablicy wklejanej.

W najprostszej formie tablice wklejane są używane do przenoszenia danych wewnątrz danej aplikacji lub między aplikacjami i istnieją tam w specjalnym globalnym obszarze pamięci poza procesem aplikacji. Chociaż koncepcje tablic wklejanych są łatwe do zrozumienia, istnieje kilka bardziej złożonych szczegółów, które należy rozważyć. Zostaną one szczegółowo omówione poniżej.

Nazwane tablice wklejania

Tablica wklejania może być publiczna lub prywatna i może być używana do różnych celów w aplikacji lub między wieloma aplikacjami. System macOS udostępnia kilka standardowych tablic wklejanych, z których każdy ma określone, dobrze zdefiniowane użycie:

  • NSGeneralPboard — Domyślna tablica wklejania dla operacji wycinania, kopiowania i wklejania .
  • NSRulerPboard — Obsługuje operacje wycinania, kopiowania i wklejania na linijkach.
  • NSFontPboard — Obsługuje operacje wycinania, kopiowania i wklejania obiektów NSFont .
  • NSFindPboard — Obsługuje panele wyszukiwania specyficzne dla aplikacji, które mogą udostępniać tekst wyszukiwania.
  • NSDragPboard — Obsługuje operacje przeciągania i upuszczania .

W większości sytuacji użyjesz jednego ze zdefiniowanych przez system tablic wklejanych. Mogą jednak wystąpić sytuacje, które wymagają utworzenia własnych tablic wklejanych. W takich sytuacjach można użyć FromName (string name) metody NSPasteboard klasy do utworzenia niestandardowego tablicy wklejanej o podanej nazwie.

Opcjonalnie możesz wywołać metodę CreateWithUniqueNameNSPasteboard klasy, aby utworzyć unikatowo nazwaną tablicę wklejaną.

Elementy tablicy wklejanych

Każdy element danych zapisywany przez aplikację w tablicy wklejanej jest uważany za element tablicy wklejanej, a tablica wklejania może przechowywać wiele elementów w tym samym czasie. W ten sposób aplikacja może zapisywać wiele wersji danych kopiowanych do tablicy wklejanej (na przykład zwykły tekst i sformatowany tekst), a aplikacja do pobierania może odczytywać tylko dane, które mogą przetwarzać (na przykład tylko zwykły tekst).

Reprezentacje danych i identyfikatory jednolitych typów

Operacje na tablicy wklejanej zwykle odbywają się między dwiema (lub więcej) aplikacjami, które nie znają się nawzajem lub typami danych, które mogą obsłużyć. Jak wspomniano w powyższej sekcji, aby zmaksymalizować potencjał udostępniania informacji, tablica wklejania może przechowywać wiele reprezentacji kopiowanych i wklejanych danych.

Każda reprezentacja jest identyfikowana za pomocą identyfikatora UTI (Uniform Type Identifier), który nie jest niczym więcej niż prostym ciągiem, który jednoznacznie identyfikuje typ prezentowanej daty (aby uzyskać więcej informacji, zobacz dokumentację przeglądu identyfikatorów jednolitych typów firmy Apple).

Jeśli tworzysz niestandardowy typ danych (na przykład obiekt rysunkowy w aplikacji rysunku wektorowego), możesz utworzyć własny identyfikator UTI w celu unikatowego zidentyfikowania go w operacjach kopiowania i wklejania.

Gdy aplikacja przygotowuje się do wklejania danych skopiowanych z tablicy wklejanej, musi znaleźć reprezentację, która najlepiej pasuje do swoich możliwości (jeśli istnieje). Zazwyczaj będzie to najbogatszy dostępny typ (na przykład sformatowany tekst dla aplikacji do przetwarzania wyrazów), wracając do najprostszych formularzy dostępnych zgodnie z potrzebami (zwykły tekst dla prostego edytora tekstów).

Obiecane dane

Ogólnie rzecz biorąc, należy podać jak najwięcej reprezentacji kopiowanych danych, aby zmaksymalizować udostępnianie między aplikacjami. Jednak ze względu na ograniczenia czasu lub pamięci może to być niepraktyczne, aby faktycznie zapisać każdy typ danych w tablicy wklejanej.

W takiej sytuacji można umieścić pierwszą reprezentację danych na tablicy wklejanej, a aplikacja odbierającą może zażądać innej reprezentacji, którą można wygenerować na bieżąco tuż przed operacją wklejania.

Po ustawieniu początkowego elementu w tablicy wklejanej określisz, że co najmniej jedna z innych dostępnych reprezentacji jest dostarczana przez obiekt zgodny z interfejsem NSPasteboardItemDataProvider . Te obiekty zapewnią dodatkowe reprezentacje na żądanie, zgodnie z żądaniem aplikacji odbieranej.

Liczba zmian

Każda tablica wklejania zachowuje liczbę zmian, która zwiększa się za każdym razem, gdy nowy właściciel zostanie zadeklarowany. Aplikacja może określić, czy zawartość tablicy wkleja została zmieniona od czasu ostatniego zbadania jej przez sprawdzenie wartości liczby zmian.

ChangeCount Użyj metod NSPasteboard i ClearContents klasy, aby zmodyfikować liczbę zmian danego tablicy wklejanej.

Kopiowanie danych do tablicy wklejanej

Wykonasz operację kopiowania, najpierw korzystając z tablicy wklejanej, usuwając wszelkie istniejące treści i zapisując dowolną liczbę reprezentacji danych, które są wymagane do wklejenia.

Na przykład:

// Get the standard pasteboard
var pasteboard = NSPasteboard.GeneralPasteboard;

// Empty the current contents
pasteboard.ClearContents();

// Add the current image to the pasteboard
pasteboard.WriteObjects (new NSImage[] {image});

Zazwyczaj wystarczy napisać do ogólnego tablicy wklejanej, jak zrobiliśmy w powyższym przykładzie. Każdy obiekt wysyłany do WriteObjects metody musi być zgodny z interfejsem INSPasteboardWriting . Kilka wbudowanych klas (takich jak NSString, , NSImageNSURL, NSColor, NSAttributedStringi NSPasteboardItem) jest automatycznie zgodnych z tym interfejsem.

Jeśli piszesz niestandardową klasę danych do tablicy wklejanej, musi być zgodna z interfejsem INSPasteboardWriting lub być opakowana w wystąpienie NSPasteboardItem klasy (zobacz sekcję Niestandardowe typy danych poniżej).

Odczytywanie danych z tablicy wklejanej

Jak wspomniano powyżej, aby zmaksymalizować potencjał udostępniania danych między aplikacjami, wiele reprezentacji skopiowanych danych może zostać zapisanych w tablicy wklejanej. Do aplikacji odbieranej należy wybranie najbogatszej możliwej wersji dla jej możliwości (jeśli istnieje).

Prosta operacja wklejania

Dane z tablicy wklejanej są odczytywane przy użyciu ReadObjectsForClasses metody . Będzie on wymagał dwóch parametrów:

  1. Tablica NSObject typów klas, które mają być odczytywane z tablicy wklejanej. Należy najpierw uporządkować ten typ danych z najbardziej pożądanym typem danych z pozostałymi typami w preferencjach malejących.
  2. Słownik zawierający dodatkowe ograniczenia (takie jak ograniczenie do określonych typów zawartości adresu URL) lub pusty słownik, jeśli nie są wymagane żadne dalsze ograniczenia.

Metoda zwraca tablicę elementów spełniających kryteria, które zostały przekazane, i dlatego zawiera co najwyżej taką samą liczbę żądanych typów danych. Możliwe jest również, że żaden z żądanych typów nie jest obecny i zostanie zwrócona pusta tablica.

Na przykład poniższy kod sprawdza, czy element NSImage istnieje w ogólnym tablicy wklejanej i wyświetla go na obrazie, jeśli tak:

[Export("PasteImage:")]
public void PasteImage(NSObject sender) {

    // Initialize the pasteboard
    NSPasteboard pasteboard = NSPasteboard.GeneralPasteboard;
    Class [] classArray  = { new Class ("NSImage") };

    bool ok = pasteboard.CanReadObjectForClasses (classArray, null);
    if (ok) {
        // Read the image off of the pasteboard
        NSObject [] objectsToPaste = pasteboard.ReadObjectsForClasses (classArray, null);
        NSImage image = (NSImage)objectsToPaste[0];

        // Display the new image
        ImageView.Image = image;
    }

    Class [] classArray2 = { new Class ("ImageInfo") };
    ok = pasteboard.CanReadObjectForClasses (classArray2, null);
    if (ok) {
        // Read the image off of the pasteboard
        NSObject [] objectsToPaste = pasteboard.ReadObjectsForClasses (classArray2, null);
        ImageInfo info = (ImageInfo)objectsToPaste[0];
            }
}

Żądanie wielu typów danych

Na podstawie typu tworzonej aplikacji Xamarin.Mac może być możliwe obsłużenie wielu reprezentacji wklejonych danych. W takiej sytuacji istnieją dwa scenariusze pobierania danych z tablicy wklejającej:

  1. Utwórz pojedyncze wywołanie ReadObjectsForClasses metody i podaj tablicę wszystkich pożądanych reprezentacji (w preferowanej kolejności).
  2. Wykonaj wiele wywołań metody ReadObjectsForClasses z prośbą o różne typy za każdym razem.

Zobacz sekcję Simple Paste Operation (Prosta operacja wklejania) powyżej, aby uzyskać więcej informacji na temat pobierania danych z tablicy wklejanej.

Sprawdzanie istniejących typów danych

Czasami warto sprawdzić, czy tablica wklejana zawiera daną reprezentację danych bez faktycznego odczytywania danych z tablicy wklejanej (na przykład włączenia elementu menu Wklej tylko wtedy, gdy istnieją prawidłowe dane).

Wywołaj metodę CanReadObjectForClasses tablicy wklejanej, aby sprawdzić, czy zawiera dany typ.

Na przykład poniższy kod określa, czy ogólny tablica wklejania zawiera NSImage wystąpienie:

public bool ImageAvailableOnPasteboard {
    get {
        // Initialize the pasteboard
        NSPasteboard pasteboard = NSPasteboard.GeneralPasteboard;
        Class [] classArray  = { new Class ("NSImage") };

        // Check to see if an image is on the pasteboard
        return pasteboard.CanReadObjectForClasses (classArray, null);
    }
}

Odczytywanie adresów URL z tablicy wklejanej

Na podstawie funkcji danej aplikacji platformy Xamarin.Mac może być wymagane odczytywanie adresów URL z tablicy wklejanej, ale tylko wtedy, gdy spełniają one określony zestaw kryteriów (na przykład wskazywanie plików lub adresów URL określonego typu danych). W takiej sytuacji można określić dodatkowe kryteria wyszukiwania przy użyciu drugiego parametru CanReadObjectForClasses metod lub ReadObjectsForClasses .

Niestandardowe typy danych

Czasami konieczne będzie zapisanie własnych typów niestandardowych w tablicy wklejanej z aplikacji Xamarin.Mac. Na przykład aplikacja do rysowania wektorów, która umożliwia użytkownikowi kopiowanie i wklejanie obiektów rysunkowych.

W takiej sytuacji należy zaprojektować klasę niestandardową danych, tak aby dziedziczyła NSObject i była zgodna z kilkoma interfejsami (INSCodingi INSPasteboardWritingINSPasteboardReading). Opcjonalnie możesz użyć elementu , NSPasteboardItem aby hermetyzować dane, które mają zostać skopiowane lub wklejone.

Obie te opcje zostaną szczegółowo omówione poniżej.

Używanie klasy niestandardowej

W tej sekcji rozszerzymy prostą przykładową aplikację utworzoną na początku tego dokumentu i dodamy klasę niestandardową, aby śledzić informacje o obrazie, który kopiujemy i wklejamy między oknami.

Dodaj nową klasę do projektu i wywołaj ją ImageInfo.cs. Zmodyfikuj plik i utwórz go w następujący sposób:

using System;
using AppKit;
using Foundation;

namespace MacCopyPaste
{
    [Register("ImageInfo")]
    public class ImageInfo : NSObject, INSCoding, INSPasteboardWriting, INSPasteboardReading
    {
        #region Computed Properties
        [Export("name")]
        public string Name { get; set; }

        [Export("imageType")]
        public string ImageType { get; set; }
        #endregion

        #region Constructors
        [Export ("init")]
        public ImageInfo ()
        {
        }

        public ImageInfo (IntPtr p) : base (p)
        {
        }

        [Export ("initWithCoder:")]
        public ImageInfo(NSCoder decoder) {

            // Decode data
            NSString name = decoder.DecodeObject("name") as NSString;
            NSString type = decoder.DecodeObject("imageType") as NSString;

            // Save data
            Name = name.ToString();
            ImageType = type.ToString ();
        }
        #endregion

        #region Public Methods
        [Export ("encodeWithCoder:")]
        public void EncodeTo (NSCoder encoder) {

            // Encode data
            encoder.Encode(new NSString(Name),"name");
            encoder.Encode(new NSString(ImageType),"imageType");
        }

        [Export ("writableTypesForPasteboard:")]
        public virtual string[] GetWritableTypesForPasteboard (NSPasteboard pasteboard) {
            string[] writableTypes = {"com.xamarin.image-info", "public.text"};
            return writableTypes;
        }

        [Export ("pasteboardPropertyListForType:")]
        public virtual NSObject GetPasteboardPropertyListForType (string type) {

            // Take action based on the requested type
            switch (type) {
            case "com.xamarin.image-info":
                return NSKeyedArchiver.ArchivedDataWithRootObject(this);
            case "public.text":
                return new NSString(string.Format("{0}.{1}", Name, ImageType));
            }

            // Failure, return null
            return null;
        }

        [Export ("readableTypesForPasteboard:")]
        public static string[] GetReadableTypesForPasteboard (NSPasteboard pasteboard){
            string[] readableTypes = {"com.xamarin.image-info", "public.text"};
            return readableTypes;
        }

        [Export ("readingOptionsForType:pasteboard:")]
        public static NSPasteboardReadingOptions GetReadingOptionsForType (string type, NSPasteboard pasteboard) {

            // Take action based on the requested type
            switch (type) {
            case "com.xamarin.image-info":
                return NSPasteboardReadingOptions.AsKeyedArchive;
            case "public.text":
                return NSPasteboardReadingOptions.AsString;
            }

            // Default to property list
            return NSPasteboardReadingOptions.AsPropertyList;
        }

        [Export ("initWithPasteboardPropertyList:ofType:")]
        public NSObject InitWithPasteboardPropertyList (NSObject propertyList, string type) {

            // Take action based on the requested type
            switch (type) {
            case "com.xamarin.image-info":
                return new ImageInfo();
            case "public.text":
                return new ImageInfo();
            }

            // Failure, return null
            return null;
        }
        #endregion
    }
}

W poniższych sekcjach przyjrzymy się szczegółowo tej klasie.

Dziedziczenie i interfejsy

Aby można było zapisać niestandardową klasę danych lub odczytać ją z tablicy wklejanej, musi być zgodna INSPastebaordWriting z interfejsami i INSPasteboardReading . Ponadto musi on dziedziczyć z NSObject interfejsu i być zgodny z INSCoding nim:

[Register("ImageInfo")]
public class ImageInfo : NSObject, INSCoding, INSPasteboardWriting, INSPasteboardReading
...

Klasa musi być również uwidoczniona przy Objective-C użyciu Register dyrektywy i musi uwidocznić wszelkie wymagane właściwości lub metody przy użyciu metody Export. Na przykład:

[Export("name")]
public string Name { get; set; }

[Export("imageType")]
public string ImageType { get; set; }

Ujawniamy dwa pola danych, które będą zawierać ta klasa — nazwę obrazu i jego typ (jpg, png itp.).

Aby uzyskać więcej informacji, zobacz sekcję Uwidacznianie klas /metodObjective-Cjęzyka C# w dokumentacji wewnętrznej platformy Xamarin.Mac, objaśnienie Register atrybutów i Export używanych do podłączania klas języka C# do Objective-C obiektów i elementów interfejsu użytkownika.

Konstruktory

Dla naszej niestandardowej klasy danych wymagane będą dwa konstruktory (prawidłowo uwidocznione Objective-Cw obiekcie ) tak, aby można je było odczytać z tablicy wklejanej:

[Export ("init")]
public ImageInfo ()
{
}

[Export ("initWithCoder:")]
public ImageInfo(NSCoder decoder) {

    // Decode data
    NSString name = decoder.DecodeObject("name") as NSString;
    NSString type = decoder.DecodeObject("imageType") as NSString;

    // Save data
    Name = name.ToString();
    ImageType = type.ToString ();
}

Najpierw uwidaczniamy pusty konstruktor w domyślnej Objective-Cinitmetodzie .

Następnie uwidaczniamy NSCoding zgodny konstruktor, który będzie używany do utworzenia nowego wystąpienia obiektu z tablicy wklejanej podczas wklejania pod wyeksportowaną nazwą initWithCoder.

Ten konstruktor przyjmuje NSCoder element (utworzony przez NSKeyedArchiver obiekt podczas zapisywania w tablicy wklejanej) wyodrębnia dane parowane klucz/wartość i zapisuje je w polach właściwości klasy danych.

Zapisywanie w tablicy wklejanych

Zgodnie z interfejsem INSPasteboardWriting musimy uwidocznić dwie metody i opcjonalnie trzecią metodę, aby można było zapisać klasę w tablicy wklejanej.

Najpierw musimy poinformować tablicę wklejającą, w jakiej reprezentacji typu danych można zapisać klasę niestandardową:

[Export ("writableTypesForPasteboard:")]
public virtual string[] GetWritableTypesForPasteboard (NSPasteboard pasteboard) {
    string[] writableTypes = {"com.xamarin.image-info", "public.text"};
    return writableTypes;
}

Każda reprezentacja jest identyfikowana za pośrednictwem identyfikatora UTI (Uniform Type Identifier), który nie jest niczym więcej niż prostym ciągiem, który jednoznacznie identyfikuje typ prezentowanych danych (aby uzyskać więcej informacji, zobacz dokumentację przeglądu identyfikatorów jednolitych typów firmy Apple).

W naszym formacie niestandardowym tworzymy własny identyfikator UTI: "com.xamarin.image-info" (zwróć uwagę, że w odwrotnej notacji tak jak identyfikator aplikacji). Nasza klasa jest również w stanie napisać standardowy ciąg do tablicy wklejanej (public.text).

Następnie musimy utworzyć obiekt w żądanym formacie, który faktycznie zostanie zapisany w tablicy wklejanej:

[Export ("pasteboardPropertyListForType:")]
public virtual NSObject GetPasteboardPropertyListForType (string type) {

    // Take action based on the requested type
    switch (type) {
    case "com.xamarin.image-info":
        return NSKeyedArchiver.ArchivedDataWithRootObject(this);
    case "public.text":
        return new NSString(string.Format("{0}.{1}", Name, ImageType));
    }

    // Failure, return null
    return null;
}

public.text Dla typu zwracamy prosty, sformatowany NSString obiekt. W przypadku typu niestandardowego com.xamarin.image-info używamy NSKeyedArchiver elementu i interfejsu NSCoder w celu zakodowania niestandardowej klasy danych do sparowanego archiwum klucza/wartości. Aby faktycznie obsłużyć kodowanie, musimy zaimplementować następującą metodę:

[Export ("encodeWithCoder:")]
public void EncodeTo (NSCoder encoder) {

    // Encode data
    encoder.Encode(new NSString(Name),"name");
    encoder.Encode(new NSString(ImageType),"imageType");
}

Poszczególne pary klucz/wartość są zapisywane w koderze i zostaną zdekodowane przy użyciu drugiego konstruktora, który dodaliśmy powyżej.

Opcjonalnie możemy uwzględnić następującą metodę, aby zdefiniować dowolne opcje podczas zapisywania danych w tablicy wklejanej:

[Export ("writingOptionsForType:pasteboard:"), CompilerGenerated]
public virtual NSPasteboardWritingOptions GetWritingOptionsForType (string type, NSPasteboard pasteboard) {
    return NSPasteboardWritingOptions.WritingPromised;
}

Obecnie dostępna jest tylko WritingPromised opcja i powinna być używana, gdy dany typ jest obiecany tylko i nie jest zapisywany w tablicy wklejanej. Aby uzyskać więcej informacji, zobacz sekcję Obiecane dane powyżej.

Za pomocą tych metod można użyć następującego kodu, aby napisać naszą klasę niestandardową do tablicy wklejanych:

// Get the standard pasteboard
var pasteboard = NSPasteboard.GeneralPasteboard;

// Empty the current contents
pasteboard.ClearContents();

// Add info to the pasteboard
pasteboard.WriteObjects (new ImageInfo[] { Info });

Odczytywanie z tablicy wklejanej

Zgodnie z interfejsem INSPasteboardReading musimy uwidocznić trzy metody, aby można było odczytać niestandardową klasę danych z tablicy wklejanej.

Najpierw musimy poinformować tablicę wklejającą, jakie reprezentacje typu danych mogą odczytywać klasa niestandardowa ze schowka:

[Export ("readableTypesForPasteboard:")]
public static string[] GetReadableTypesForPasteboard (NSPasteboard pasteboard){
    string[] readableTypes = {"com.xamarin.image-info", "public.text"};
    return readableTypes;
}

Ponownie są one definiowane jako proste identyfikatory UTI i są tymi samymi typami, które zdefiniowaliśmy w sekcji Pisanie do tablicy wklejania powyżej.

Następnie musimy poinformować tablicę wklejaną o tym, jak każdy z typów UTI będzie odczytywany przy użyciu następującej metody:

[Export ("readingOptionsForType:pasteboard:")]
public static NSPasteboardReadingOptions GetReadingOptionsForType (string type, NSPasteboard pasteboard) {

    // Take action based on the requested type
    switch (type) {
    case "com.xamarin.image-info":
        return NSPasteboardReadingOptions.AsKeyedArchive;
    case "public.text":
        return NSPasteboardReadingOptions.AsString;
    }

    // Default to property list
    return NSPasteboardReadingOptions.AsPropertyList;
}

com.xamarin.image-info Dla typu informujemy tablicę wklejającą o dekodowanie pary klucz/wartość, która została utworzona NSKeyedArchiver za pomocą klasy podczas pisania klasy do tablicy wklejającej przez wywołanie initWithCoder: konstruktora dodanego do klasy.

Na koniec musimy dodać następującą metodę, aby odczytać inne reprezentacje danych UTI z tablicy wklejanej:

[Export ("initWithPasteboardPropertyList:ofType:")]
public NSObject InitWithPasteboardPropertyList (NSObject propertyList, string type) {

    // Take action based on the requested type
    switch (type) {
    case "public.text":
        return new ImageInfo();
    }

    // Failure, return null
    return null;
}

Po zastosowaniu wszystkich tych metod niestandardowa klasa danych może być odczytywana z tablicy wklejanej przy użyciu następującego kodu:

// Initialize the pasteboard
NSPasteboard pasteboard = NSPasteboard.GeneralPasteboard;
var classArrayPtrs = new [] { Class.GetHandle (typeof(ImageInfo)) };
NSArray classArray = NSArray.FromIntPtrs (classArrayPtrs);

// NOTE: Sending messages directly to the base Objective-C API because of this defect:
// https://bugzilla.xamarin.com/show_bug.cgi?id=31760
// Check to see if image info is on the pasteboard
ok = bool_objc_msgSend_IntPtr_IntPtr (pasteboard.Handle, Selector.GetHandle ("canReadObjectForClasses:options:"), classArray.Handle, IntPtr.Zero);

if (ok) {
    // Read the image off of the pasteboard
    NSObject [] objectsToPaste = NSArray.ArrayFromHandle<Foundation.NSObject>(IntPtr_objc_msgSend_IntPtr_IntPtr (pasteboard.Handle, Selector.GetHandle ("readObjectsForClasses:options:"), classArray.Handle, IntPtr.Zero));
    ImageInfo info = (ImageInfo)objectsToPaste[0];
}

Używanie elementu NSPasteboardItem

Czasami trzeba napisać elementy niestandardowe do tablicy wklejanej, która nie gwarantuje utworzenia klasy niestandardowej lub chcesz podać dane w typowym formacie, tylko zgodnie z potrzebami. W takich sytuacjach można użyć elementu NSPasteboardItem.

Element zapewnia NSPasteboardItem szczegółową kontrolę nad danymi zapisanymi w tablicy wklejanej i jest przeznaczony do tymczasowego dostępu — powinien zostać usunięty po zapisaniu ich do tablicy wklejanej.

Zapisywanie danych

Aby zapisać dane niestandardowe w kodzie NSPasteboardItem , musisz podać niestandardowy NSPasteboardItemDataProviderelement . Dodaj nową klasę do projektu i wywołaj ją ImageInfoDataProvider.cs. Zmodyfikuj plik i utwórz go w następujący sposób:

using System;
using AppKit;
using Foundation;

namespace MacCopyPaste
{
    [Register("ImageInfoDataProvider")]
    public class ImageInfoDataProvider : NSPasteboardItemDataProvider
    {
        #region Computed Properties
        public string Name { get; set;}
        public string ImageType { get; set;}
        #endregion

        #region Constructors
        [Export ("init")]
        public ImageInfoDataProvider ()
        {
        }

        public ImageInfoDataProvider (string name, string imageType)
        {
            // Initialize
            this.Name = name;
            this.ImageType = imageType;
        }

        protected ImageInfoDataProvider (NSObjectFlag t){
        }

        protected internal ImageInfoDataProvider (IntPtr handle){

        }
        #endregion

        #region Override Methods
        [Export ("pasteboardFinishedWithDataProvider:")]
        public override void FinishedWithDataProvider (NSPasteboard pasteboard)
        {

        }

        [Export ("pasteboard:item:provideDataForType:")]
        public override void ProvideDataForType (NSPasteboard pasteboard, NSPasteboardItem item, string type)
        {

            // Take action based on the type
            switch (type) {
            case "public.text":
                // Encode the data to string
                item.SetStringForType(string.Format("{0}.{1}", Name, ImageType),type);
                break;
            }

        }
        #endregion
    }
}

Podobnie jak w przypadku niestandardowej klasy danych, musimy użyć Register dyrektyw iExport, aby uwidocznić ją na .Objective-C Klasa musi dziedziczyć i NSPasteboardItemDataProvider musi implementować FinishedWithDataProvider metody i ProvideDataForType .

ProvideDataForType Użyj metody , aby podać dane, które zostaną opakowane w NSPasteboardItem następujący sposób:

[Export ("pasteboard:item:provideDataForType:")]
public override void ProvideDataForType (NSPasteboard pasteboard, NSPasteboardItem item, string type)
{

    // Take action based on the type
    switch (type) {
    case "public.text":
        // Encode the data to string
        item.SetStringForType(string.Format("{0}.{1}", Name, ImageType),type);
        break;
    }

}

W tym przypadku przechowujemy dwie informacje o obrazie (Name i ImageType) i zapisujemy je w prostym ciągu (public.text).

Wpisz zapis danych do tablicy wklejania, użyj następującego kodu:

// Get the standard pasteboard
var pasteboard = NSPasteboard.GeneralPasteboard;

// Using a Pasteboard Item
NSPasteboardItem item = new NSPasteboardItem();
string[] writableTypes = {"public.text"};

// Add a data provider to the item
ImageInfoDataProvider dataProvider = new ImageInfoDataProvider (Info.Name, Info.ImageType);
var ok = item.SetDataProviderForTypes (dataProvider, writableTypes);

// Save to pasteboard
if (ok) {
    pasteboard.WriteObjects (new NSPasteboardItem[] { item });
}

Odczytywanie danych

Aby odczytać dane z tablicy wklejanej, użyj następującego kodu:

// Initialize the pasteboard
NSPasteboard pasteboard = NSPasteboard.GeneralPasteboard;
Class [] classArray  = { new Class ("NSImage") };

bool ok = pasteboard.CanReadObjectForClasses (classArray, null);
if (ok) {
    // Read the image off of the pasteboard
    NSObject [] objectsToPaste = pasteboard.ReadObjectsForClasses (classArray, null);
    NSImage image = (NSImage)objectsToPaste[0];

    // Do something with data
    ...
}

Class [] classArray2 = { new Class ("ImageInfo") };
ok = pasteboard.CanReadObjectForClasses (classArray2, null);
if (ok) {
    // Read the image off of the pasteboard
    NSObject [] objectsToPaste = pasteboard.ReadObjectsForClasses (classArray2, null);

    // Do something with data
    ...
}

Podsumowanie

W tym artykule szczegółowo przedstawiono pracę z tablicą wklejaną w aplikacji Xamarin.Mac w celu obsługi operacji kopiowania i wklejania. Najpierw wprowadzono prosty przykład, aby zapoznać się ze standardowymi operacjami wklejania. Następnie szczegółowe spojrzenie na tablicę wklejaną oraz sposób odczytywania i zapisywania danych. Na koniec przyjrzeliśmy się używaniu niestandardowego typu danych do obsługi kopiowania i wklejania złożonych typów danych w aplikacji.