Kopieren und Einfügen in Xamarin.Mac
In diesem Artikel wird die Arbeit mit dem Pasteboard behandelt, um Kopieren und Einfügen in eine Xamarin.Mac-Anwendung bereitzustellen. Es zeigt, wie Sie mit Standarddatentypen arbeiten, die zwischen mehreren Apps gemeinsam genutzt werden können und wie benutzerdefinierte Daten in einer bestimmten App unterstützt werden können.
Überblick
Wenn Sie mit C# und .NET in einer Xamarin.Mac-Anwendung arbeiten, haben Sie Zugriff auf das gleiche Einfügen (Kopieren und Einfügen), die ein Entwickler hat Objective-C .
In diesem Artikel werden wir die beiden wichtigsten Möglichkeiten zur Verwendung des Pasteboards in einer Xamarin.Mac-App behandeln:
- Standarddatentypen – Da Einfügevorgänge in der Regel zwischen zwei nicht verbundenen Apps durchgeführt werden, kennt weder die App die Datentypen, die die andere unterstützt. Um das Potenzial für die Freigabe zu maximieren, kann das Pasteboard mehrere Darstellungen eines bestimmten Elements (mit einem Standardsatz gemeinsamer Datentypen) halten, damit die nutzungsintensive App die für ihre Anforderungen am besten geeignete Version auswählen kann.
- Benutzerdefinierte Daten – Um das Kopieren und Einfügen komplexer Daten in Ihrem Xamarin.Mac zu unterstützen, können Sie einen benutzerdefinierten Datentyp definieren, der vom Einfügenboard behandelt wird. Eine Vektorzeichnungs-App, mit der der Benutzer komplexe Shapes kopieren und einfügen kann, die aus mehreren Datentypen und Punkten bestehen.
In diesem Artikel werden die Grundlagen der Arbeit mit dem Pasteboard in einer Xamarin.Mac-Anwendung behandelt, um Kopieren- und Einfügenvorgänge zu unterstützen. Es wird dringend vorgeschlagen, dass Sie zuerst den Artikel "Hello" und "Mac" durchlaufen, insbesondere die Einführung in Xcode- und Interface-Generator- undAktionsabschnitte , da sie wichtige Konzepte und Techniken behandelt, die wir in diesem Artikel verwenden werden.
Möglicherweise möchten Sie sich die C#-Klassen /Methoden zum Abschnitt "Xamarin.Mac Internals" ansehen, und sie erläutert die und attribute, die verwendet werden, um Objective-CIhre C#-Klassen an Objective-C Objekte und UI-Elemente zu verkabeln.Register
Export
Erste Schritte mit dem Einfügen
Das Pasteboard stellt einen standardisierten Mechanismus zum Austausch von Daten innerhalb einer bestimmten Anwendung oder zwischen Anwendungen dar. Die typische Verwendung für ein Pasteboard in einer Xamarin.Mac-Anwendung besteht darin, Kopieren- und Einfügenvorgänge zu behandeln, aber auch eine Reihe anderer Vorgänge wird unterstützt (z & . B. Drag Drop and Application Services).
Um Sie schnell auf den Boden zu bringen, beginnen wir mit einer einfachen, praktischen Einführung in die Verwendung von Pasteboards in einer Xamarin.Mac-App. Später stellen wir eine ausführliche Erläuterung zur Funktionsweise des Pasteboards und der verwendeten Methoden bereit.
In diesem Beispiel erstellen wir eine einfache dokumentbasierte Anwendung, die ein Fenster verwaltet, das eine Bildansicht enthält. Der Benutzer kann Bilder zwischen Dokumenten in der App und aus anderen Apps oder mehreren Fenstern in derselben App kopieren und einfügen.
Erstellen des Xamarin-Projekts
Zunächst erstellen wir eine neue dokumentbasierte Xamarin.Mac-App, die wir kopieren und einfügen werden.
Gehen Sie folgendermaßen vor:
Starten Sie Visual Studio für Mac, und klicken Sie auf den Link "Neue Project...".
Wählen Sie MacAppCocoa-App>> aus, und klicken Sie dann auf die Schaltfläche "Weiter":
Geben Sie für den Project Namen ein, und behalten Sie
MacCopyPaste
alles andere als Standard. Klicken Sie auf „Weiter:Klicken Sie auf die Schaltfläche "Erstellen ":
Hinzufügen eines NSDocument
Als Nächstes fügen wir benutzerdefinierte NSDocument
Klasse hinzu, die als Hintergrundspeicher für die Benutzeroberfläche der Anwendung fungiert. Es enthält eine einzelne Bildansicht und weiß, wie Sie ein Bild aus der Ansicht in das Standard-Einfügenboard kopieren und ein Bild aus dem Standard-Pasteboard aufnehmen und es in der Bildansicht anzeigen.
Klicken Sie mit der rechten Maustaste auf das Xamarin.Mac-Projekt im Lösungspad, und wählen Sie "Datei hinzufügen>".:
Geben Sie für den NamenImageDocument
ein, und klicken Sie auf Neu. Bearbeiten Sie die ImageDocument.cs-Klasse , und machen Sie es wie folgt aussehen:
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
}
}
Sehen wir uns einige der folgenden Codedetails an.
Der folgende Code stellt eine Eigenschaft bereit, um zu testen, ob Bilddaten im Standard-Pasteboard vorhanden sind, wenn ein Bild verfügbar ist, true
anders false
zurückgegeben wird:
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);
}
}
Der folgende Code kopiert ein Bild aus der angefügten Bildansicht in das Standard-Pasteboard:
[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 });
}
}
}
Und der folgende Code fügt ein Bild aus dem Standard-Pasteboard ein und zeigt es in der angefügten Bildansicht an (wenn das Einfügenboard ein gültiges Bild enthält):
[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]
}
}
Mit diesem Dokument erstellen wir die Benutzeroberfläche für die Xamarin.Mac-App.
Erstellen der Benutzeroberfläche
Doppelklicken Sie auf die Datei "Main.storyboard ", um sie in Xcode zu öffnen. Fügen Sie als Nächstes eine Symbolleiste und ein Bild gut hinzu und konfigurieren Sie sie wie folgt:
Fügen Sie dem Symbolleistenelement "Bildsymbolleiste " eine Kopie hinzu und fügen Sie sie zur linken Seite der Symbolleiste hinzu. Wir verwenden diese als Verknüpfungen zum Kopieren und Einfügen im Menü "Bearbeiten". Fügen Sie als Nächstes vier Bildsymbolleistenelemente zur rechten Seite der Symbolleiste hinzu. Wir verwenden diese, um das Bild gut mit einigen Standardbildern aufzufüllen.
Weitere Informationen zur Arbeit mit Symbolleisten finden Sie in unserer Symbolleistendokumentation .
Als Nächstes zeigen wir die folgenden Verkaufsstellen und Aktionen für unsere Symbolleistenelemente und das Bild gut an:
Weitere Informationen zur Arbeit mit Verkaufsstellen und Aktionen finden Sie im Abschnitt "Outlets und Aktionen" unserer Dokumentation "Hello, Mac ".
Aktivieren der Benutzeroberfläche
Mit unserer benutzeroberfläche, die in Xcode und unserem UI-Element über Verkaufsstellen und Aktionen verfügbar gemacht wurde, müssen wir den Code hinzufügen, um die Benutzeroberfläche zu aktivieren. Doppelklicken Sie auf die Datei "ImageWindow.cs " im Lösungspad , und machen Sie es wie folgt aussehen:
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
}
}
Sehen wir uns diesen Code im Detail unten an.
Zunächst stellen wir eine Instanz der Klasse zur Verfügung, die ImageDocument
wir oben erstellt haben:
private ImageDocument _document;
...
[Export ("Document")]
public ImageDocument Document {
get { return _document; }
set {
WillChangeValue ("Document");
_document = value;
DidChangeValue ("Document");
}
}
Export
Mithilfe von , WillChangeValue
und DidChangeValue
, haben wir die Document
Eigenschaft eingerichtet, um Key-Value Codieren und Datenbindung in Xcode zu ermöglichen.
Wir stellen auch das Bild aus dem Bild bereit, das wir unserer Benutzeroberfläche in Xcode mit der folgenden Eigenschaft hinzugefügt haben:
public ViewController ImageViewController {
get { return ContentViewController as ViewController; }
}
public NSImage Image {
get {
return ImageViewController.Image;
}
set {
ImageViewController.Image = value;
}
}
Wenn das Hauptfenster geladen und angezeigt wird, erstellen wir eine Instanz unserer ImageDocument
Klasse und fügen das Bild der Benutzeroberfläche gut mit dem folgenden Code an:
public override void AwakeFromNib ()
{
base.AwakeFromNib ();
// Create a new document instance
Document = new ImageDocument ();
// Attach to image view
Document.ImageView = ImageViewController.ContentView;
}
Als Reaktion auf den Benutzer, der auf die Symbolleistenelemente kopieren und einfügen klickt, rufen wir die Instanz der ImageDocument
Klasse auf, um die tatsächliche Arbeit zu erledigen:
partial void CopyImage (NSObject sender) {
Document.CopyImage(sender);
}
partial void PasteImage (Foundation.NSObject sender) {
Document.PasteImage(sender);
}
Aktivieren der Menüs "Datei" und "Bearbeiten"
Das letzte, was wir tun müssen, ist die Aktivierung des Neuen Menüelements im Menü "Datei " (zum Erstellen neuer Instanzen unseres Hauptfensters) und zum Aktivieren des Ausschneidens, Kopieren und Einfügen von Menüelementen im Menü "Bearbeiten ".
Zum Aktivieren des Neuen Menüelements bearbeiten Sie die Datei "AppDelegate.cs ", und fügen Sie den folgenden Code hinzu:
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);
}
Weitere Informationen finden Sie im Abschnitt "Arbeiten mit mehreren Windows" unserer Windows Dokumentation.
Um die Menüelemente ausschneiden, kopierenund einfügen zu aktivieren, bearbeiten Sie die Datei "AppDelegate.cs ", und fügen Sie den folgenden Code hinzu:
[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);
}
Für jedes Menüelement erhalten wir das aktuelle, oberste, Schlüsselfenster und casten sie in unsere ImageWindow
Klasse:
var window = NSApplication.SharedApplication.KeyWindow as ImageWindow;
Von dort rufen wir die ImageDocument
Klasseninstanz dieses Fensters auf, um die Aktionen zum Kopieren und Einfügen zu behandeln. Beispiel:
window.Document.CopyImage (sender);
Es werden nur Menüelemente ausschneiden, kopierenund einfügen angezeigt, wenn Bilddaten im Standard-Einfügen oder in der Bildbeschriftung des aktuellen aktiven Fensters vorhanden sind.
Fügen wir der Xamarin.Mac-Projekt eine Datei "EditMenuDelegate.cs " hinzu, und machen Sie es wie folgt aussehen:
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
}
}
Erneut erhalten wir das aktuelle, oberste Fenster und verwenden seine ImageDocument
Klasseninstanz, um zu sehen, ob die erforderlichen Bilddaten vorhanden sind. Anschließend verwenden wir die MenuWillHighlightItem
Methode, um jedes Element basierend auf diesem Zustand zu aktivieren oder zu deaktivieren.
Bearbeiten Sie die Datei "AppDelegate.cs ", und machen Sie die DidFinishLaunching
Methode wie folgt aussehen:
public override void DidFinishLaunching (NSNotification notification)
{
// Disable automatic item enabling on the Edit menu
EditMenu.AutoEnablesItems = false;
EditMenu.Delegate = new EditMenuDelegate ();
}
Zunächst deaktivieren wir die automatische Aktivierung und Deaktivierung von Menüelementen im Menü "Bearbeiten". Als Nächstes fügen wir eine Instanz der klasse an, die EditMenuDelegate
wir oben erstellt haben.
Weitere Informationen finden Sie in der Dokumentation zu Menüs .
Testen der App
Mit allem, was vorhanden ist, sind wir bereit, die Anwendung zu testen. Erstellen und Ausführen der App und die Hauptschnittstelle wird angezeigt:
Wenn Sie das Menü "Bearbeiten" öffnen, beachten Sie, dass "Ausschneiden","Kopieren" und "Einfügen" deaktiviert sind, da es kein Bild im Bild oder im Standard-Einfügen gibt:
Wenn Sie dem Bild ein Bild gut hinzufügen und das Menü "Bearbeiten" erneut öffnen, werden die Elemente jetzt aktiviert:
Wenn Sie das Bild kopieren und im Menü " Neu " auswählen, können Sie dieses Bild in das neue Fenster einfügen:
In den folgenden Abschnitten sehen wir uns die Arbeit mit dem Pasteboard in einer Xamarin.Mac-Anwendung ausführlich an.
Informationen zum Einfügen
In macOS (früher als OS X bezeichnet) bietet das Pasteboard (NSPasteboard
) Unterstützung für mehrere Serverprozesse wie Kopieren & , & Ziehen Drop und Application Services. In den folgenden Abschnitten werden wir einen näheren Blick auf verschiedene Schlüsselpastaturkonzepte nehmen.
Was ist ein Pasteboard?
Die NSPasteboard
Klasse bietet einen standardisierten Mechanismus zum Austausch von Informationen zwischen Anwendungen oder innerhalb einer bestimmten App. Die Hauptfunktion eines Pasteboards dient zum Behandeln von Kopier- und Einfügevorgängen:
- Wenn der Benutzer ein Element in einer App auswählt und das Menüelement "Ausschneiden " oder " Kopieren " verwendet, werden mindestens eine Darstellung des ausgewählten Elements auf dem Einfügen platziert.
- Wenn der Benutzer das Menüelement " Einfügen " (innerhalb derselben App oder einer anderen App) verwendet, wird die Version der Daten, die er verarbeiten kann, aus dem Pasteboard kopiert und der App hinzugefügt.
Weniger offensichtliche Einfügeelemente umfassen Such-, Ziehen-, Ziehen- und Drop- und Anwendungsdienstevorgänge:
- Wenn der Benutzer einen Drag-Vorgang initiiert, wird die Ziehendaten in das Pasteboard kopiert. Wenn der Ziehenvorgang mit einem Drop auf eine andere App endet, kopiert diese App die Daten aus dem Einfügen.
- Für Übersetzungsdienste wird die zu übersetzenden Daten durch die anfordernde App in das Einfügeboard kopiert. Der Anwendungsdienst ruft die Daten aus dem Einfügen ab, führt die Übersetzung aus, fügt dann die Daten wieder in das Pasteboard ein.
In ihrer einfachsten Form werden Pasteboards verwendet, um Daten innerhalb einer bestimmten App oder zwischen Apps zu verschieben und dort in einem speziellen globalen Speicherbereich außerhalb des App-Prozesses vorhanden. Während die Konzepte der Pasteboards leicht zu erfassen sind, gibt es mehrere komplexere Details, die berücksichtigt werden müssen. Dies wird unten ausführlich behandelt.
Benannte Pasteboards
Ein Pasteboard kann öffentlich oder privat sein und kann für eine Vielzahl von Zwecken innerhalb einer Anwendung oder zwischen mehreren Apps verwendet werden. macOS bietet mehrere Standard-Pasteboards, die jeweils eine bestimmte, gut definierte Verwendung enthalten:
NSGeneralPboard
- Das Standard-Pasteboard für Ausschneiden, Kopieren und Einfügen von Vorgängen.NSRulerPboard
- Unterstützt Ausschneiden, Kopieren und Einfügen von Vorgängen in Linealen.NSFontPboard
- Unterstützt Ausschneiden, Kopieren und Einfügen von Vorgängen aufNSFont
Objekten.NSFindPboard
- Unterstützt anwendungsspezifische Suchbereiche, die Suchtext freigeben können.NSDragPboard
- Unterstützt Drag & Drop-Vorgänge .
Für die meisten Situationen verwenden Sie eine der system definierten Pasteboards. Es kann jedoch Situationen geben, in denen Sie eigene Pasteboards erstellen müssen. In diesen Situationen können Sie die FromName (string name)
Methode der NSPasteboard
Klasse verwenden, um ein benutzerdefiniertes Pasteboard mit dem Angegebenen Namen zu erstellen.
Optional können Sie die CreateWithUniqueName
Methode der NSPasteboard
Klasse aufrufen, um ein eindeutig benanntes Pasteboard zu erstellen.
Einfügen von Elementen
Jede Datenmenge, die eine Anwendung in ein Pasteboard schreibt, wird als Einfügeelement angesehen, und ein Einfügeboard kann mehrere Elemente gleichzeitig halten. Auf diese Weise kann eine App mehrere Versionen der Daten schreiben, die in ein Einfügeboard kopiert werden (z. B. nur Text und formatierter Text), und die abgerufene App kann nur die Daten lesen, die sie verarbeiten kann (z. B. nur nur den nur Text).
Datendarstellungen und einheitliche Typbezeichner
Einfügevorgänge werden in der Regel zwischen zwei (oder mehr) Anwendungen durchgeführt, die keine Kenntnisse übereinander oder die Typen von Daten haben, die jeder behandeln kann. Wie im obigen Abschnitt angegeben, kann ein Pasteboard mehrere Darstellungen der Daten enthalten, die kopiert und eingefügt werden.
Jede Darstellung wird über einen Uniform Type Identifier (UTI) identifiziert, der nichts mehr als eine einfache Zeichenfolge ist, die den Typ des angezeigten Datums eindeutig identifiziert (weitere Informationen finden Sie in der Dokumentation zur Übersicht über die Einheitliche Typbezeichner von Apple).
Wenn Sie einen benutzerdefinierten Datentyp erstellen (z. B. ein Zeichnungsobjekt in einer Vektorzeichnungs-App), können Sie eigene UTI erstellen, um sie eindeutig in Kopieren- und Einfügen-Vorgängen zu identifizieren.
Wenn eine App auf das Einfügen von Daten vorbereitet, die aus einem Pasteboard kopiert wurden, muss sie die Darstellung finden, die am besten zu ihren Fähigkeiten passt (falls vorhanden). Normalerweise ist dies der reichste Typ, der verfügbar ist (z. B. formatierter Text für eine Textverarbeitungs-App), zurück auf die einfachsten Formulare zurück, die als erforderlich verfügbar sind (Nur-Text für einen einfachen Text-Editor).
Zugesagte Daten
Im Allgemeinen sollten Sie so viele Darstellungen der Daten bereitstellen, die wie möglich kopiert werden, um die Freigabe zwischen Apps zu maximieren. Aufgrund von Zeit- oder Speichereinschränkungen kann es jedoch unpraktisch sein, jeden Datentyp tatsächlich in das Pasteboard zu schreiben.
In dieser Situation können Sie die erste Datendarstellung auf dem Pasteboard platzieren, und die empfangende App kann eine andere Darstellung anfordern, die direkt vor dem Einfügenvorgang generiert werden kann.
Wenn Sie das ursprüngliche Element in das Einfügenboard platzieren, geben Sie an, dass eine oder mehrere der verfügbaren Darstellungen von einem Objekt bereitgestellt werden, das der NSPasteboardItemDataProvider
Schnittstelle entspricht. Diese Objekte stellen die zusätzlichen Darstellungen nach Bedarf bereit, wie von der empfangenden App angefordert.
Anzahl ändern
Jedes Pasteboard verwaltet eine Änderungsanzahl , die jedes Mal, wenn ein neuer Besitzer deklariert wird. Eine App kann bestimmen, ob sich der Inhalt des Einfügens seit dem letzten Mal geändert hat, indem der Wert der Änderungsanzahl überprüft wird.
Verwenden Sie die Methoden und ClearContents
Methoden der NSPasteboard
Klasse, um die ChangeCount
Änderungsanzahl eines bestimmten Pasteboards zu ändern.
Kopieren von Daten in ein Einfügeboard
Sie führen einen Kopiervorgang aus, indem Sie zuerst auf ein Pasteboard zugreifen, alle vorhandenen Inhalte löschen und so viele Darstellungen der Daten schreiben, wie für das Einfügen erforderlich sind.
Beispiel:
// 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});
Normalerweise schreiben Sie einfach an das allgemeine Einfügen, wie wir im obigen Beispiel ausgeführt haben. Jedes Objekt, das Sie an die Methode senden, muss der INSPasteboardWriting
WriteObjects
Schnittstelle entsprechen. Mehrere integrierte Klassen (zNSString
. B. , NSColor
NSAttributedString
NSImage
NSURL
und NSPasteboardItem
) entsprechen dieser Schnittstelle automatisch.
Wenn Sie eine benutzerdefinierte Datenklasse in das Pasteboard schreiben, muss sie der INSPasteboardWriting
Schnittstelle entsprechen oder in eine Instanz der NSPasteboardItem
Klasse umgebrochen werden (siehe Abschnitt " Benutzerdefinierte Datentypen " unten).
Lesen von Daten aus einem Pasteboard
Wie oben erwähnt, können mehrere Darstellungen der kopierten Daten in das Pasteboard geschrieben werden, um das Potenzial für die Freigabe von Daten zwischen Apps zu maximieren. Es ist bis zur empfangenden App möglich, die höchste Version für ihre Funktionen auszuwählen (falls vorhanden).
Einfacher Einfügevorgang
Sie lesen Daten aus dem Pasteboard mithilfe der ReadObjectsForClasses
Methode. Es erfordert zwei Parameter:
- Ein Array basierender
NSObject
Klassentypen, die Sie aus dem Pasteboard lesen möchten. Sie sollten dies zuerst mit dem gewünschten Datentyp bestellen, wobei alle verbleibenden Typen in der Verringerung der Einstellung vorhanden sind. - Ein Wörterbuch mit zusätzlichen Einschränkungen (z. B. einschränken auf bestimmte URL-Inhaltstypen) oder ein leeres Wörterbuch, wenn keine weiteren Einschränkungen erforderlich sind.
Die Methode gibt ein Array von Elementen zurück, die die von uns übergebenen Kriterien erfüllen und daher die gleiche Anzahl von Datentypen enthalten, die angefordert werden. Es ist auch möglich, dass keine der angeforderten Typen vorhanden sind und ein leeres Array zurückgegeben wird.
Im folgenden Code wird beispielsweise überprüft, ob eine NSImage
in der allgemeinen Einfügeseite vorhanden ist und in einem Bild gut angezeigt wird, wenn dies der Fall ist:
[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];
}
}
Anfordern mehrerer Datentypen
Basierend auf dem Typ der erstellten Xamarin.Mac-Anwendung kann es mehrere Darstellungen der eingefügten Daten behandeln. In dieser Situation gibt es zwei Szenarien zum Abrufen von Daten aus dem Pasteboard:
- Rufen Sie eine einzelne Aufrufe der
ReadObjectsForClasses
Methode auf und geben Sie ein Array aller gewünschten Darstellungen (in der bevorzugten Reihenfolge) an. - Führen Sie mehrere Aufrufe an die Methode aus, die
ReadObjectsForClasses
jedes Mal ein anderes Array von Typen fordert.
Weitere Informationen zum Abrufen von Daten aus einem Pasteboard finden Sie oben im Abschnitt " Einfaches Einfügen" .
Überprüfen auf vorhandene Datentypen
Es gibt Zeiten, in denen Sie überprüfen möchten, ob ein Pasteboard eine bestimmte Datendarstellung enthält, ohne tatsächlich die Daten aus dem Pasteboard zu lesen (z. B. das Aktivieren des Menüelements "Einfügen", nur wenn gültige Daten vorhanden sind).
Rufen Sie die CanReadObjectForClasses
Methode des Pasteboards auf, um zu sehen, ob es einen bestimmten Typ enthält.
Der folgende Code bestimmt beispielsweise, ob das allgemeine Einfügen eine NSImage
Instanz enthält:
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);
}
}
Lese-URLs aus dem Einfügenboard
Basierend auf der Funktion einer bestimmten Xamarin.Mac-App kann es erforderlich sein, URLs aus einem Einfügen zu lesen, aber nur, wenn sie einen bestimmten Satz von Kriterien erfüllen (z. B. auf Dateien oder URLs eines bestimmten Datentyps). In dieser Situation können Sie zusätzliche Suchkriterien mithilfe des zweiten Parameters der CanReadObjectForClasses
Methoden angeben ReadObjectsForClasses
.
Benutzerdefinierte Datentypen
Es gibt Zeiten, in denen Sie Ihre eigenen benutzerdefinierten Typen aus einer Xamarin.Mac-App speichern müssen. So kann beispielsweise eine Vektorzeichnungs-App, mit der der Benutzer Zeichnungsobjekte kopieren und einfügen kann.
In dieser Situation müssen Sie Ihre benutzerdefinierte Datenklasse so entwerfen, dass sie von ihnen erbtNSObject
, und sie entspricht einigen Schnittstellen (INSCoding
INSPasteboardWriting
und INSPasteboardReading
). Optional können Sie eine NSPasteboardItem
Kapselung der Daten verwenden, die kopiert oder eingefügt werden sollen.
Beide Optionen werden unten ausführlich behandelt.
Verwenden einer benutzerdefinierten Klasse
In diesem Abschnitt werden wir die einfache Beispiel-App erweitern, die wir am Anfang dieses Dokuments erstellt haben und eine benutzerdefinierte Klasse hinzufügen, um Informationen zu dem Bild nachzuverfolgen, das wir zwischen Fenstern kopieren und einfügen.
Fügen Sie dem Projekt eine neue Klasse hinzu, und rufen Sie es ImageInfo.cs auf. Bearbeiten Sie die Datei, und machen Sie es wie folgt aussehen:
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
}
}
In den folgenden Abschnitten sehen wir uns diese Klasse ausführlich an.
Vererbung und Schnittstellen
Bevor eine benutzerdefinierte Datenklasse in ein Pasteboard geschrieben oder gelesen werden kann, muss sie den und den INSPastebaordWriting
INSPasteboardReading
Schnittstellen entsprechen. Darüber hinaus muss er von der INSCoding
Schnittstelle erben NSObject
und auch entsprechen:
[Register("ImageInfo")]
public class ImageInfo : NSObject, INSCoding, INSPasteboardWriting, INSPasteboardReading
...
Die Klasse muss auch für die Verwendung der Register
Richtlinie verfügbar Objective-C gemacht werden, und sie muss alle erforderlichen Eigenschaften oder Methoden mithilfe Export
verfügbar machen. Beispiel:
[Export("name")]
public string Name { get; set; }
[Export("imageType")]
public string ImageType { get; set; }
Wir stellen die beiden Datenfelder dar, die diese Klasse enthält – den Namen des Bilds und seinen Typ (jpg, png usw.).
Weitere Informationen finden Sie im Abschnitt "Xamarin.Mac Internals"-Dokumentation über die Exposing C#-Klassen /MethodenObjective-C, die Register
Export
verwendet werden, um Ihre C#-Klassen an Objective-C Objekte und UI-Elemente zu verkabeln.
Konstruktoren
Zwei Konstruktoren (ordnungsgemäß verfügbar Objective-Cgemacht) sind für unsere benutzerdefinierte Datenklasse erforderlich, damit sie aus einem Pasteboard gelesen werden kann:
[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 ();
}
Zunächst stellen wir den leeren Konstruktor unter der Standardmethode Objective-C von init
.
Als Nächstes stellen wir einen kompatiblen Konstruktor zur Erstellung einer NSCoding
neuen Instanz des Objekts aus dem Pasteboard zur Verfügung, wenn er unter dem exportierten Namen initWithCoder
eingefügt wird.
Dieser Konstruktor verwendet NSCoder
eine (wie von einem NSKeyedArchiver
beim Schreiben in das Pasteboard erstellte), extrahiert die Schlüssel-/Wert-paarten Daten und speichert sie in die Eigenschaftenfelder der Datenklasse.
Schreiben an das Einfügeboard
Durch die Übereinstimmung mit der Schnittstelle müssen wir zwei Methoden verfügbar machen und optional eine dritte Methode bereitstellen, sodass die Klasse in das INSPasteboardWriting
Pasteboard geschrieben werden kann.
Zunächst müssen wir dem Einfügen mitteilen, in welche Datentypdarstellungen die benutzerdefinierte Klasse geschrieben werden kann:
[Export ("writableTypesForPasteboard:")]
public virtual string[] GetWritableTypesForPasteboard (NSPasteboard pasteboard) {
string[] writableTypes = {"com.xamarin.image-info", "public.text"};
return writableTypes;
}
Jede Darstellung wird über einen Uniform Type Identifier (UTI) identifiziert, der nichts mehr als eine einfache Zeichenfolge ist, die den Typ der angezeigten Daten eindeutig identifiziert (weitere Informationen finden Sie in der Dokumentation zur Übersicht über die Einheitliche Typbezeichner von Apple).
Für unser benutzerdefiniertes Format erstellen wir unsere eigene UTI: "com.xamarin.image-info" (beachten Sie, dass sich die umgekehrte Notation wie ein App-Bezeichner befindet). Unsere Klasse ist auch in der Lage, eine Standardzeichenfolge in das Pasteboard (public.text
) zu schreiben.
Als Nächstes müssen wir das Objekt im angeforderten Format erstellen, das tatsächlich in das Pasteboard geschrieben wird:
[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;
}
Für den public.text
Typ geben wir ein einfaches, formatiertes NSString
Objekt zurück. Für den benutzerdefinierten Typ verwenden wir eine NSKeyedArchiver
und die NSCoder
Schnittstelle, um die benutzerdefinierte com.xamarin.image-info
Datenklasse in ein schlüssel-/wertpaares Archiv zu codieren. Wir müssen die folgende Methode implementieren, um die Codierung tatsächlich zu behandeln:
[Export ("encodeWithCoder:")]
public void EncodeTo (NSCoder encoder) {
// Encode data
encoder.Encode(new NSString(Name),"name");
encoder.Encode(new NSString(ImageType),"imageType");
}
Die einzelnen Schlüssel-/Wertpaare werden in den Encoder geschrieben und mithilfe des zweiten Konstruktors dekodiert, den wir oben hinzugefügt haben.
Optional können wir die folgende Methode einschließen, um alle Optionen beim Schreiben von Daten in das Pasteboard zu definieren:
[Export ("writingOptionsForType:pasteboard:"), CompilerGenerated]
public virtual NSPasteboardWritingOptions GetWritingOptionsForType (string type, NSPasteboard pasteboard) {
return NSPasteboardWritingOptions.WritingPromised;
}
Derzeit ist nur die WritingPromised
Option verfügbar und sollte verwendet werden, wenn ein bestimmter Typ nur zugesagt und nicht tatsächlich in das Pasteboard geschrieben wird. Weitere Informationen finden Sie im Abschnitt "Zugesagte Daten " weiter oben.
Mit diesen Methoden kann der folgende Code verwendet werden, um unsere benutzerdefinierte Klasse in das Pasteboard zu schreiben:
// Get the standard pasteboard
var pasteboard = NSPasteboard.GeneralPasteboard;
// Empty the current contents
pasteboard.ClearContents();
// Add info to the pasteboard
pasteboard.WriteObjects (new ImageInfo[] { Info });
Lesen aus dem Einfügebrett
Durch die Einhaltung der INSPasteboardReading
Schnittstelle müssen drei Methoden verfügbar gemacht werden, damit die benutzerdefinierte Datenklasse aus dem Pasteboard gelesen werden kann.
Zunächst müssen wir dem Pasteboard mitteilen, welche Datentypdarstellungen die benutzerdefinierte Klasse aus der Zwischenablage lesen kann:
[Export ("readableTypesForPasteboard:")]
public static string[] GetReadableTypesForPasteboard (NSPasteboard pasteboard){
string[] readableTypes = {"com.xamarin.image-info", "public.text"};
return readableTypes;
}
Auch hier werden diese als einfache UTIs definiert und sind die gleichen Typen, die wir im Abschnitt "Schreiben in das Pasteboard " oben definiert haben.
Als Nächstes müssen wir dem Pasteboard mitteilen , wie jede der UTI-Typen mithilfe der folgenden Methode gelesen wird:
[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;
}
Für den com.xamarin.image-info
Typ geben wir dem Pasteboard an, das Schlüssel-Wert-Paar zu decodieren, das wir beim NSKeyedArchiver
Schreiben der Klasse in das Pasteboard erstellt haben, indem wir den initWithCoder:
Konstruktor aufrufen, den wir der Klasse hinzugefügt haben.
Schließlich müssen wir die folgende Methode hinzufügen, um die anderen UTI-Datendarstellungen aus dem Pasteboard zu lesen:
[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;
}
Mit allen diesen Methoden kann die benutzerdefinierte Datenklasse mithilfe des folgenden Codes aus dem Pasteboard gelesen werden:
// 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];
}
Verwenden eines NSPasteboardItem
Es kann vorkommen, dass Sie benutzerdefinierte Elemente in das Einfügebrett schreiben müssen, das nicht die Erstellung einer benutzerdefinierten Klasse garantiert oder Sie Daten in einem gemeinsamen Format bereitstellen möchten, nur wie erforderlich. Für diese Situationen können Sie eine NSPasteboardItem
.
Eine NSPasteboardItem
bietet eine feine Kontrolle über die Daten, die in das Einfügebrett geschrieben werden und für temporären Zugriff ausgelegt sind – es sollte nach dem Schreiben in das Pasteboard entfernt werden.
Schreiben von Daten
Um Ihre benutzerdefinierten Daten in eine NSPasteboardItem
zu schreiben, müssen Sie einen benutzerdefinierten NSPasteboardItemDataProvider
Code bereitstellen. Fügen Sie dem Projekt eine neue Klasse hinzu, und rufen Sie sie ImageInfoDataProvider.cs auf. Bearbeiten Sie die Datei, und sehen Sie wie folgt aus:
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
}
}
Wie bei der benutzerdefinierten Datenklasse müssen wir die Register
Und-Direktiven Export
verwenden, um sie verfügbar Objective-Czu machen. Die Klasse muss von NSPasteboardItemDataProvider
der Klasse erben und die FinishedWithDataProvider
methoden ProvideDataForType
implementieren.
Verwenden Sie die ProvideDataForType
Methode, um die Daten bereitzustellen, die wie NSPasteboardItem
folgt umschlossen werden:
[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;
}
}
In diesem Fall speichern wir zwei Informationen zu unserem Bild (Name und ImageType) und schreiben diese in eine einfache Zeichenfolge (public.text
).
Geben Sie die Daten in das Pasteboard ein, verwenden Sie den folgenden Code:
// 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 });
}
Lesen von Daten
Verwenden Sie den folgenden Code, um die Daten aus dem Pasteboard zurückzulesen:
// 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
...
}
Zusammenfassung
Dieser Artikel hat einen detaillierten Blick auf die Arbeit mit dem Pasteboard in einer Xamarin.Mac-Anwendung unternommen, um Kopier- und Einfügevorgänge zu unterstützen. Zunächst wurde ein einfaches Beispiel eingeführt, um Sie mit Standard-Pasteboards-Vorgängen vertraut zu machen. Als Nächstes hat es einen detaillierten Blick auf das Pasteboard und das Lesen und Schreiben von Daten darauf gedauert. Schließlich wurde die Verwendung eines benutzerdefinierten Datentyps untersucht, um das Kopieren und Einfügen komplexer Datentypen in einer App zu unterstützen.