Bagikan melalui


Dialog di Xamarin.Mac

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

Dialog muncul sebagai respons terhadap tindakan pengguna dan biasanya menyediakan cara pengguna dapat menyelesaikan tindakan. Dialog memerlukan respons dari pengguna sebelum dapat ditutup.

Windows dapat digunakan dalam status Modeless (seperti editor teks yang dapat membuka beberapa dokumen sekaligus) atau Modal (seperti dialog Ekspor yang harus ditutup sebelum aplikasi dapat dilanjutkan).

Kotak dialog buka

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

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

Pengantar Dialog

Dialog muncul sebagai respons terhadap tindakan pengguna (seperti menyimpan file) dan menyediakan cara bagi pengguna untuk menyelesaikan tindakan tersebut. Dialog memerlukan respons dari pengguna sebelum dapat ditutup.

Menurut Apple, ada tiga cara untuk menyajikan Dialog:

  • Modal Dokumen - Dialog Modal Dokumen mencegah pengguna melakukan hal lain dalam dokumen tertentu hingga diberhentikan.
  • App Modal - Dialog App Modal mencegah pengguna berinteraksi dengan aplikasi hingga diberhentikan.
  • Dialog Modeless A Modeless memungkinkan pengguna mengubah pengaturan dalam dialog saat masih berinteraksi dengan jendela dokumen.

NSWindow Standar apa pun dapat digunakan sebagai dialog yang disesuaikan dengan menampilkannya secara modal:

Contoh jendela modal

Lembar Dialog Modal Dokumen

Lembar adalah dialog modal yang dilampirkan ke jendela dokumen tertentu, mencegah pengguna berinteraksi dengan jendela hingga mereka menutup dialog. Lembar dilampirkan ke jendela tempat lembar muncul dan hanya satu lembar yang dapat dibuka untuk jendela kapan saja.

Contoh lembar modal

Preferensi Windows

Jendela Preferensi adalah dialog tanpa mode yang berisi pengaturan aplikasi yang jarang berubah oleh pengguna. Preferensi Windows sering menyertakan Toolbar yang memungkinkan pengguna beralih di antara grup pengaturan yang berbeda:

Contoh jendela preferensi

Buka Dialog

Dialog Buka memberi pengguna cara yang konsisten untuk menemukan dan membuka item dalam aplikasi:

Kotak dialog terbuka

macOS menyediakan Dialog Pengaturan Cetak dan Halaman standar yang dapat ditampilkan aplikasi Anda sehingga pengguna dapat memiliki pengalaman pencetakan yang konsisten di setiap aplikasi yang mereka gunakan.

Dialog Cetak dapat ditampilkan sebagai kotak dialog mengambang bebas:

Kotak dialog cetak

Atau dapat ditampilkan sebagai Lembar:

Lembar cetak

Dialog Penyetelan Halaman dapat ditampilkan sebagai kotak dialog mengambang gratis:

Dialog penyetelan halaman

Atau dapat ditampilkan sebagai Lembar:

Lembar penyetelan halaman

Simpan Dialog

Dialog Simpan memberi pengguna cara yang konsisten untuk menyimpan item dalam aplikasi. Dialog Simpan memiliki dua status: Minimal (juga dikenal sebagai Diciutkan):

Dialog simpan

Dan status Diperluas :

Dialog penyimpanan yang diperluas

Dialog Simpan Minimal juga dapat ditampilkan sebagai Lembar:

Lembar penyimpanan minimal

Seperti halnya Dialog Simpan yang Diperluas :

Lembar penyimpanan yang diperluas

Untuk informasi selengkapnya, lihat bagian Dialog dari Pedoman Antarmuka Manusia OS X Apple

Menambahkan Jendela Modal ke Proyek

Selain jendela dokumen utama, aplikasi Xamarin.Mac mungkin perlu menampilkan jenis jendela lain kepada pengguna, seperti Preferensi atau Panel Pemeriksa.

Untuk menambahkan jendela baru, lakukan hal berikut:

  1. Di Penjelajah Solusi, buka Main.storyboard file untuk pengeditan di Penyusun Antarmuka Xcode.

  2. Seret Pengontrol Tampilan baru ke Permukaan Desain:

    Memilih Pengontrol Tampilan dari Pustaka

  3. Di Pemeriksa Identitas, masukkan CustomDialogController untuk Nama Kelas:

    Mengatur nama kelas ke CustomDialogController.

  4. Beralih kembali ke Visual Studio untuk Mac, izinkan untuk disinkronkan dengan Xcode dan buat CustomDialogController.h file.

  5. Kembali ke Xcode dan desain antarmuka Anda:

    Merancang UI dalam Xcode

  6. Buat Modal Segue dari Jendela Utama aplikasi Anda ke Pengontrol Tampilan baru dengan menyeret kontrol dari elemen UI yang akan membuka dialog ke jendela dialog. Tetapkan PengidentifikasiModalSegue:

    Segue modal

  7. Kawat Tindakan dan Outlet apa pun:

    Mengonfigurasi Tindakan

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

CustomDialogController.cs Buat file terlihat seperti berikut ini:

using System;
using Foundation;
using AppKit;

namespace MacDialog
{
    public partial class CustomDialogController : NSViewController
    {
        #region Private Variables
        private string _dialogTitle = "Title";
        private string _dialogDescription = "Description";
        private NSViewController _presentor;
        #endregion

        #region Computed Properties
        public string DialogTitle {
            get { return _dialogTitle; }
            set { _dialogTitle = value; }
        }

        public string DialogDescription {
            get { return _dialogDescription; }
            set { _dialogDescription = value; }
        }

        public NSViewController Presentor {
            get { return _presentor; }
            set { _presentor = value; }
        }
        #endregion

        #region Constructors
        public CustomDialogController (IntPtr handle) : base (handle)
        {
        }
        #endregion

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

            // Set initial title and description
            Title.StringValue = DialogTitle;
            Description.StringValue = DialogDescription;
        }
        #endregion

        #region Private Methods
        private void CloseDialog() {
            Presentor.DismissViewController (this);
        }
        #endregion

        #region Custom Actions
        partial void AcceptDialog (Foundation.NSObject sender) {
            RaiseDialogAccepted();
            CloseDialog();
        }

        partial void CancelDialog (Foundation.NSObject sender) {
            RaiseDialogCanceled();
            CloseDialog();
        }
        #endregion

        #region Events
        public EventHandler DialogAccepted;

        internal void RaiseDialogAccepted() {
            if (this.DialogAccepted != null)
                this.DialogAccepted (this, EventArgs.Empty);
        }

        public EventHandler DialogCanceled;

        internal void RaiseDialogCanceled() {
            if (this.DialogCanceled != null)
                this.DialogCanceled (this, EventArgs.Empty);
        }
        #endregion
    }
}

Kode ini mengekspos beberapa properti untuk mengatur judul dan deskripsi dialog dan beberapa peristiwa untuk bereaksi terhadap dialog yang dibatalkan atau diterima.

Selanjutnya, edit ViewController.cs file, ambil alih PrepareForSegue metode dan buat terlihat seperti berikut ini:

public override void PrepareForSegue (NSStoryboardSegue segue, NSObject sender)
{
    base.PrepareForSegue (segue, sender);

    // Take action based on the segue name
    switch (segue.Identifier) {
    case "ModalSegue":
        var dialog = segue.DestinationController as CustomDialogController;
        dialog.DialogTitle = "MacDialog";
        dialog.DialogDescription = "This is a sample dialog.";
        dialog.DialogAccepted += (s, e) => {
            Console.WriteLine ("Dialog accepted");
            DismissViewController (dialog);
        };
        dialog.Presentor = this;
        break;
    }
}

Kode ini menginisialisasi segue yang kami tentukan dalam Penyusun Antarmuka Xcode ke dialog kami dan menyiapkan judul dan deskripsi. Ini juga menangani pilihan yang dilakukan pengguna dalam kotak dialog.

Kita dapat menjalankan aplikasi kita dan menampilkan dialog kustom:

Contoh dialog

Untuk informasi selengkapnya tentang menggunakan windows dalam aplikasi Xamarin.Mac, silakan lihat dokumentasi Bekerja dengan Windows kami.

Membuat Lembar Kustom

Lembar adalah dialog modal yang dilampirkan ke jendela dokumen tertentu, mencegah pengguna berinteraksi dengan jendela hingga mereka menutup dialog. Lembar dilampirkan ke jendela tempat lembar muncul dan hanya satu lembar yang dapat dibuka untuk jendela kapan saja.

Untuk membuat Lembar Kustom di Xamarin.Mac, mari kita lakukan hal berikut:

  1. Di Penjelajah Solusi, buka Main.storyboard file untuk pengeditan di Penyusun Antarmuka Xcode.

  2. Seret Pengontrol Tampilan baru ke Permukaan Desain:

    Memilih Pengontrol Tampilan dari Pustaka

  3. Desain antarmuka pengguna Anda:

    Desain UI

  4. Buat Lembar Segue dari Jendela Utama Anda ke Pengontrol Tampilan baru:

    Memilih jenis segue Lembar

  5. Di Pemeriksa Identitas, beri nama KelasSheetViewController Pengontrol Tampilan:

    Mengatur nama kelas ke SheetViewController.

  6. Tentukan Outlet dan Tindakan yang diperlukan:

    Menentukan Outlet dan Tindakan yang diperlukan

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

Selanjutnya, edit SheetViewController.cs file dan buat terlihat seperti berikut ini:

using System;
using Foundation;
using AppKit;

namespace MacDialog
{
    public partial class SheetViewController : NSViewController
    {
        #region Private Variables
        private string _userName = "";
        private string _password = "";
        private NSViewController _presentor;
        #endregion

        #region Computed Properties
        public string UserName {
            get { return _userName; }
            set { _userName = value; }
        }

        public string Password {
            get { return _password;}
            set { _password = value;}
        }

        public NSViewController Presentor {
            get { return _presentor; }
            set { _presentor = value; }
        }
        #endregion

        #region Constructors
        public SheetViewController (IntPtr handle) : base (handle)
        {
        }
        #endregion

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

            // Set initial values
            NameField.StringValue = UserName;
            PasswordField.StringValue = Password;

            // Wireup events
            NameField.Changed += (sender, e) => {
                UserName = NameField.StringValue;
            };
            PasswordField.Changed += (sender, e) => {
                Password = PasswordField.StringValue;
            };
        }
        #endregion

        #region Private Methods
        private void CloseSheet() {
            Presentor.DismissViewController (this);
        }
        #endregion

        #region Custom Actions
        partial void AcceptSheet (Foundation.NSObject sender) {
            RaiseSheetAccepted();
            CloseSheet();
        }

        partial void CancelSheet (Foundation.NSObject sender) {
            RaiseSheetCanceled();
            CloseSheet();
        }
        #endregion

        #region Events
        public EventHandler SheetAccepted;

        internal void RaiseSheetAccepted() {
            if (this.SheetAccepted != null)
                this.SheetAccepted (this, EventArgs.Empty);
        }

        public EventHandler SheetCanceled;

        internal void RaiseSheetCanceled() {
            if (this.SheetCanceled != null)
                this.SheetCanceled (this, EventArgs.Empty);
        }
        #endregion
    }
}

Selanjutnya, edit ViewController.cs file, edit PrepareForSegue metode dan buat terlihat seperti berikut ini:

public override void PrepareForSegue (NSStoryboardSegue segue, NSObject sender)
{
    base.PrepareForSegue (segue, sender);

    // Take action based on the segue name
    switch (segue.Identifier) {
    case "ModalSegue":
        var dialog = segue.DestinationController as CustomDialogController;
        dialog.DialogTitle = "MacDialog";
        dialog.DialogDescription = "This is a sample dialog.";
        dialog.DialogAccepted += (s, e) => {
            Console.WriteLine ("Dialog accepted");
            DismissViewController (dialog);
        };
        dialog.Presentor = this;
        break;
    case "SheetSegue":
        var sheet = segue.DestinationController as SheetViewController;
        sheet.SheetAccepted += (s, e) => {
            Console.WriteLine ("User Name: {0} Password: {1}", sheet.UserName, sheet.Password);
        };
        sheet.Presentor = this;
        break;
    }
}

Jika kita menjalankan aplikasi kita dan membuka Lembar, itu akan dilampirkan ke jendela:

Contoh lembar

Membuat Dialog Preferensi

Sebelum kita menjabarkan Tampilan Preferensi di Penyusun Antarmuka, kita harus menambahkan jenis segue kustom untuk menangani peralihan preferensi. Tambahkan kelas baru ke proyek Anda dan sebut saja ReplaceViewSeque. Edit kelas dan buat terlihat seperti berikut ini:

using System;
using AppKit;
using Foundation;

namespace MacWindows
{
    [Register("ReplaceViewSeque")]
    public class ReplaceViewSeque : NSStoryboardSegue
    {
        #region Constructors
        public ReplaceViewSeque() {

        }

        public ReplaceViewSeque (string identifier, NSObject sourceController, NSObject destinationController) : base(identifier,sourceController,destinationController) {

        }

        public ReplaceViewSeque (IntPtr handle) : base(handle) {
        }

        public ReplaceViewSeque (NSObjectFlag x) : base(x) {
        }
        #endregion

        #region Override Methods
        public override void Perform ()
        {
            // Cast the source and destination controllers
            var source = SourceController as NSViewController;
            var destination = DestinationController as NSViewController;

            // Is there a source?
            if (source == null) {
                // No, get the current key window
                var window = NSApplication.SharedApplication.KeyWindow;

                // Swap the controllers
                window.ContentViewController = destination;

                // Release memory
                window.ContentViewController?.RemoveFromParentViewController ();
            } else {
                // Swap the controllers
                source.View.Window.ContentViewController = destination;

                // Release memory
                source.RemoveFromParentViewController ();
            }

        }
        #endregion

    }

}

Dengan segue kustom yang dibuat, kita dapat menambahkan jendela baru di Interface Builder Xcode untuk menangani preferensi kita.

Untuk menambahkan jendela baru, lakukan hal berikut:

  1. Di Penjelajah Solusi, buka Main.storyboard file untuk pengeditan di Penyusun Antarmuka Xcode.

  2. Seret Pengontrol Jendela baru ke Permukaan Desain:

    Pilih Pengontrol Jendela dari Pustaka

  3. Atur Jendela di dekat perancang Bilah Menu:

    Menambahkan Jendela baru

  4. Buat salinan Pengontrol Tampilan terlampir karena akan ada tab dalam tampilan preferensi Anda:

    Menambahkan Pengontrol Tampilan yang diperlukan

  5. Seret Pengontrol Bilah Alat baru dari Pustaka:

    Pilih Pengontrol Toolbar dari Pustaka

  6. Dan letakkan di Jendela di Permukaan Desain:

    Menambahkan Pengontrol Bilah Alat baru

  7. Tata letak desain toolbar Anda:

    Tata letak toolbar

  8. Klik Kontrol dan seret dari setiap Tombol Toolbar ke Tampilan yang Anda buat di atas. Pilih Jenis segue kustom:

    Mengatur jenis Segue kustom.

  9. Pilih Segue baru dan atur Kelas ke ReplaceViewSegue:

    Mengatur kelas segue

  10. Di Perancang Bilah Menu di Permukaan Desain, dari Menu Aplikasi pilih Preferensi... , klik kontrol dan seret ke Jendela Preferensi untuk membuat Tampilkan segue:

    Mengatur jenis segue dengan menyeret Preferensi ke Jendela Preferensi.

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

Jika kita menjalankan kode dan memilih Preferensi... dari Menu Aplikasi, jendela akan ditampilkan:

Contoh jendela preferensi yang menampilkan kata Profil.

Untuk informasi selengkapnya tentang bekerja dengan Windows dan Bilah Alat, silakan lihat dokumentasi Windows dan Bilah Alat kami.

Menyimpan dan Memuat Preferensi

Di App macOS biasa, saat pengguna membuat perubahan pada Salah satu Preferensi Pengguna Aplikasi, perubahan tersebut disimpan secara otomatis. Cara term mudah untuk menangani ini di aplikasi Xamarin.Mac, adalah dengan membuat satu kelas untuk mengelola semua preferensi pengguna dan membagikannya di seluruh sistem.

Pertama, tambahkan kelas baru AppPreferences ke proyek dan warisi dari NSObject. Preferensi akan dirancang untuk menggunakan Pengikatan Data dan Pengodean Kunci-Nilai yang akan membuat proses pembuatan dan pemeliharaan bentuk preferensi jauh lebih sederhana. Karena Preferensi akan terdiri dari sejumlah kecil jenis data sederhana, gunakan bawaan NSUserDefaults untuk menyimpan dan mengambil nilai.

AppPreferences.cs Edit file dan buat terlihat seperti berikut ini:

using System;
using Foundation;
using AppKit;

namespace SourceWriter
{
    [Register("AppPreferences")]
    public class AppPreferences : NSObject
    {
        #region Computed Properties
        [Export("DefaultLanguage")]
        public int DefaultLanguage {
            get {
                var value = LoadInt ("DefaultLanguage", 0);
                return value;
            }
            set {
                WillChangeValue ("DefaultLanguage");
                SaveInt ("DefaultLanguage", value, true);
                DidChangeValue ("DefaultLanguage");
            }
        }

        [Export("SmartLinks")]
        public bool SmartLinks {
            get { return LoadBool ("SmartLinks", true); }
            set {
                WillChangeValue ("SmartLinks");
                SaveBool ("SmartLinks", value, true);
                DidChangeValue ("SmartLinks");
            }
        }

        // Define any other required user preferences in the same fashion
        ...

        [Export("EditorBackgroundColor")]
        public NSColor EditorBackgroundColor {
            get { return LoadColor("EditorBackgroundColor", NSColor.White); }
            set {
                WillChangeValue ("EditorBackgroundColor");
                SaveColor ("EditorBackgroundColor", value, true);
                DidChangeValue ("EditorBackgroundColor");
            }
        }
        #endregion

        #region Constructors
        public AppPreferences ()
        {
        }
        #endregion

        #region Public Methods
        public int LoadInt(string key, int defaultValue) {
            // Attempt to read int
            var number = NSUserDefaults.StandardUserDefaults.IntForKey(key);

            // Take action based on value
            if (number == null) {
                return defaultValue;
            } else {
                return (int)number;
            }
        }

        public void SaveInt(string key, int value, bool sync) {
            NSUserDefaults.StandardUserDefaults.SetInt(value, key);
            if (sync) NSUserDefaults.StandardUserDefaults.Synchronize ();
        }

        public bool LoadBool(string key, bool defaultValue) {
            // Attempt to read int
            var value = NSUserDefaults.StandardUserDefaults.BoolForKey(key);

            // Take action based on value
            if (value == null) {
                return defaultValue;
            } else {
                return value;
            }
        }

        public void SaveBool(string key, bool value, bool sync) {
            NSUserDefaults.StandardUserDefaults.SetBool(value, key);
            if (sync) NSUserDefaults.StandardUserDefaults.Synchronize ();
        }

        public string NSColorToHexString(NSColor color, bool withAlpha) {
            //Break color into pieces
            nfloat red=0, green=0, blue=0, alpha=0;
            color.GetRgba (out red, out green, out blue, out alpha);

            // Adjust to byte
            alpha *= 255;
            red *= 255;
            green *= 255;
            blue *= 255;

            //With the alpha value?
            if (withAlpha) {
                return String.Format ("#{0:X2}{1:X2}{2:X2}{3:X2}", (int)alpha, (int)red, (int)green, (int)blue);
            } else {
                return String.Format ("#{0:X2}{1:X2}{2:X2}", (int)red, (int)green, (int)blue);
            }
        }

        public NSColor NSColorFromHexString (string hexValue)
        {
            var colorString = hexValue.Replace ("#", "");
            float red, green, blue, alpha;

            // Convert color based on length
            switch (colorString.Length) {
            case 3 : // #RGB
                red = Convert.ToInt32(string.Format("{0}{0}", colorString.Substring(0, 1)), 16) / 255f;
                green = Convert.ToInt32(string.Format("{0}{0}", colorString.Substring(1, 1)), 16) / 255f;
                blue = Convert.ToInt32(string.Format("{0}{0}", colorString.Substring(2, 1)), 16) / 255f;
                return NSColor.FromRgba(red, green, blue, 1.0f);
            case 6 : // #RRGGBB
                red = Convert.ToInt32(colorString.Substring(0, 2), 16) / 255f;
                green = Convert.ToInt32(colorString.Substring(2, 2), 16) / 255f;
                blue = Convert.ToInt32(colorString.Substring(4, 2), 16) / 255f;
                return NSColor.FromRgba(red, green, blue, 1.0f);
            case 8 : // #AARRGGBB
                alpha = Convert.ToInt32(colorString.Substring(0, 2), 16) / 255f;
                red = Convert.ToInt32(colorString.Substring(2, 2), 16) / 255f;
                green = Convert.ToInt32(colorString.Substring(4, 2), 16) / 255f;
                blue = Convert.ToInt32(colorString.Substring(6, 2), 16) / 255f;
                return NSColor.FromRgba(red, green, blue, alpha);
            default :
                throw new ArgumentOutOfRangeException(string.Format("Invalid color value '{0}'. It should be a hex value of the form #RBG, #RRGGBB or #AARRGGBB", hexValue));
            }
        }

        public NSColor LoadColor(string key, NSColor defaultValue) {

            // Attempt to read color
            var hex = NSUserDefaults.StandardUserDefaults.StringForKey(key);

            // Take action based on value
            if (hex == null) {
                return defaultValue;
            } else {
                return NSColorFromHexString (hex);
            }
        }

        public void SaveColor(string key, NSColor color, bool sync) {
            // Save to default
            NSUserDefaults.StandardUserDefaults.SetString(NSColorToHexString(color,true), key);
            if (sync) NSUserDefaults.StandardUserDefaults.Synchronize ();
        }
        #endregion
    }
}

Kelas ini berisi beberapa rutinitas pembantu seperti SaveInt, , LoadInt, SaveColorLoadColor, dll. untuk mempermudah bekerjaNSUserDefaults. Selain itu, karena NSUserDefaults tidak memiliki cara bawaan untuk menangani NSColors, NSColorToHexString metode dan NSColorFromHexString digunakan untuk mengonversi warna ke string heksa berbasis web (#RRGGBBAA di mana AA adalah transparansi alfa) yang dapat dengan mudah disimpan dan diambil.

AppDelegate.cs Dalam file, buat instans objek AppPreferences yang akan digunakan di seluruh aplikasi:

using AppKit;
using Foundation;
using System.IO;
using System;

namespace SourceWriter
{
    [Register ("AppDelegate")]
    public class AppDelegate : NSApplicationDelegate
    {
        #region Computed Properties
        public int NewWindowNumber { get; set;} = -1;

        public AppPreferences Preferences { get; set; } = new AppPreferences();
        #endregion

        #region Constructors
        public AppDelegate ()
        {
        }
        #endregion

        ...

Preferensi Kabel ke Tampilan Preferensi

Selanjutnya, sambungkan kelas Preferensi ke elemen UI pada Jendela Preferensi dan Tampilan yang dibuat di atas. Di Penyusun Antarmuka, pilih Pengontrol Tampilan Preferensi dan beralih ke Pemeriksa Identitas, buat kelas kustom untuk pengontrol:

Pemeriksa Identitas

Beralih kembali ke Visual Studio untuk Mac untuk menyinkronkan perubahan Anda dan buka kelas yang baru dibuat untuk pengeditan. Buat kelas terlihat seperti berikut:

using System;
using Foundation;
using AppKit;

namespace SourceWriter
{
    public partial class EditorPrefsController : NSViewController
    {
        #region Application Access
        public static AppDelegate App {
            get { return (AppDelegate)NSApplication.SharedApplication.Delegate; }
        }
        #endregion

        #region Computed Properties
        [Export("Preferences")]
        public AppPreferences Preferences {
            get { return App.Preferences; }
        }
        #endregion

        #region Constructors
        public EditorPrefsController (IntPtr handle) : base (handle)
        {
        }
        #endregion
    }
}

Perhatikan bahwa kelas ini telah melakukan dua hal di sini: Pertama, ada properti pembantu Appuntuk mempermudah akses AppDelegate . Kedua, Preferences properti mengekspos kelas AppPreferences global untuk pengikatan data dengan kontrol UI apa pun yang ditempatkan pada Tampilan ini.

Selanjutnya, klik dua kali file Storyboard untuk membukanya kembali di Interface Builder (dan lihat perubahan yang baru saja dilakukan di atas). Seret kontrol UI apa pun yang diperlukan untuk membangun antarmuka preferensi ke dalam Tampilan. Untuk setiap kontrol, beralihlah ke Pemeriksa Pengikatan dan ikat ke properti individual kelas AppPreference :

Pemeriksa Pengikatan

Ulangi langkah-langkah di atas untuk semua panel (Lihat Pengontrol) dan Properti Preferensi yang diperlukan.

Menerapkan Perubahan Preferensi ke Semua Windows yang Terbuka

Seperti yang dinyatakan di atas, dalam Aplikasi macOS umum, ketika pengguna membuat perubahan pada salah satu Preferensi Pengguna Aplikasi, perubahan tersebut disimpan secara otomatis dan diterapkan ke jendela apa pun yang mungkin telah dibuka pengguna di aplikasi.

Perencanaan dan desain yang cermat dari preferensi dan jendela aplikasi Anda akan memungkinkan proses ini terjadi dengan lancar dan transparan kepada pengguna akhir, dengan sejumlah kecil pekerjaan pengkodan.

Untuk Jendela apa pun yang akan menggunakan Preferensi Aplikasi, tambahkan properti pembantu berikut ke Pengontrol Tampilan Kontennya untuk mempermudah akses AppDelegate kami:

#region Application Access
public static AppDelegate App {
    get { return (AppDelegate)NSApplication.SharedApplication.Delegate; }
}
#endregion

Selanjutnya, tambahkan kelas untuk mengonfigurasi konten atau perilaku berdasarkan preferensi pengguna:

public void ConfigureEditor() {

    // General Preferences
    TextEditor.AutomaticLinkDetectionEnabled = App.Preferences.SmartLinks;
    TextEditor.AutomaticQuoteSubstitutionEnabled = App.Preferences.SmartQuotes;
    ...

}

Anda perlu memanggil metode konfigurasi saat Jendela pertama kali dibuka untuk memastikannya sesuai dengan preferensi pengguna:

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

    // Configure editor from user preferences
    ConfigureEditor ();
    ...
}

Selanjutnya, edit AppDelegate.cs file dan tambahkan metode berikut untuk menerapkan perubahan preferensi apa pun ke semua jendela yang terbuka:

public void UpdateWindowPreferences() {

    // Process all open windows
    for(int n=0; n<NSApplication.SharedApplication.Windows.Length; ++n) {
        var content = NSApplication.SharedApplication.Windows[n].ContentViewController as ViewController;
        if (content != null ) {
            // Reformat all text
            content.ConfigureEditor ();
        }
    }

}

Selanjutnya, tambahkan PreferenceWindowDelegate kelas ke proyek dan buat terlihat seperti berikut ini:

using System;
using AppKit;
using System.IO;
using Foundation;

namespace SourceWriter
{
    public class PreferenceWindowDelegate : NSWindowDelegate
    {
        #region Application Access
        public static AppDelegate App {
            get { return (AppDelegate)NSApplication.SharedApplication.Delegate; }
        }
        #endregion

        #region Computed Properties
        public NSWindow Window { get; set;}
        #endregion

        #region constructors
        public PreferenceWindowDelegate (NSWindow window)
        {
            // Initialize
            this.Window = window;

        }
        #endregion

        #region Override Methods
        public override bool WindowShouldClose (Foundation.NSObject sender)
        {

            // Apply any changes to open windows
            App.UpdateWindowPreferences();

            return true;
        }
        #endregion
    }
}

Ini akan menyebabkan perubahan preferensi dikirim ke semua Windows yang terbuka ketika Jendela preferensi ditutup.

Terakhir, edit Pengontrol Jendela Preferensi dan tambahkan delegasi yang dibuat di atas:

using System;
using Foundation;
using AppKit;

namespace SourceWriter
{
    public partial class PreferenceWindowController : NSWindowController
    {
        #region Constructors
        public PreferenceWindowController (IntPtr handle) : base (handle)
        {
        }
        #endregion

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

            // Initialize
            Window.Delegate = new PreferenceWindowDelegate(Window);
            Toolbar.SelectedItemIdentifier = "General";
        }
        #endregion
    }
}

Dengan semua perubahan ini di tempat, jika pengguna mengedit Preferensi Aplikasi dan menutup Jendela Preferensi, perubahan akan diterapkan ke semua Windows yang terbuka:

Contoh Jendela Preferensi, ditampilkan dengan beberapa jendela terbuka lainnya.

Dialog Buka

Dialog Buka memberi pengguna cara yang konsisten untuk menemukan dan membuka item dalam aplikasi. Untuk menampilkan Dialog Buka di aplikasi Xamarin.Mac, gunakan kode berikut:

var dlg = NSOpenPanel.OpenPanel;
dlg.CanChooseFiles = true;
dlg.CanChooseDirectories = false;
dlg.AllowedFileTypes = new string[] { "txt", "html", "md", "css" };

if (dlg.RunModal () == 1) {
    // Nab the first file
    var url = dlg.Urls [0];

    if (url != null) {
        var path = url.Path;

        // Create a new window to hold the text
        var newWindowController = new MainWindowController ();
        newWindowController.Window.MakeKeyAndOrderFront (this);

        // Load the text into the window
        var window = newWindowController.Window as MainWindow;
        window.Text = File.ReadAllText(path);
        window.SetTitleWithRepresentedFilename (Path.GetFileName(path));
        window.RepresentedUrl = url;

    }
}

Dalam kode di atas, kami membuka jendela dokumen baru untuk menampilkan konten file. Anda harus mengganti kode ini dengan fungsionalitas diperlukan oleh aplikasi Anda.

Properti berikut ini tersedia saat bekerja dengan NSOpenPanel:

  • CanChooseFiles - Jika true pengguna dapat memilih file.
  • CanChooseDirectories - Jika true pengguna dapat memilih direktori.
  • AllowsMultipleSelection - Jika true pengguna dapat memilih lebih dari satu file pada satu waktu.
  • ResolveAliases - Jika true memilih dan alias, menyelesaikannya ke jalur file asli.
  • AllowedFileTypes - Adalah array string jenis file yang dapat dipilih pengguna sebagai ekstensi atau UTI. Nilai defaultnya adalah null, yang memungkinkan file apa pun dibuka.

Metode RunModal () menampilkan Dialog Buka dan memungkinkan pengguna untuk memilih file atau direktori (seperti yang ditentukan oleh properti) dan mengembalikan 1 jika pengguna mengklik tombol Buka .

Dialog Buka mengembalikan file atau direktori yang dipilih pengguna sebagai array URL di URL properti .

Jika kita menjalankan program dan memilih item Buka... dari menu File , berikut ini ditampilkan:

Kotak dialog buka

Dialog Penyetelan Cetak dan Halaman

macOS menyediakan Dialog Pengaturan Cetak dan Halaman standar yang dapat ditampilkan aplikasi Anda sehingga pengguna dapat memiliki pengalaman pencetakan yang konsisten di setiap aplikasi yang mereka gunakan.

Kode berikut akan menampilkan Dialog Cetak standar:

public bool ShowPrintAsSheet { get; set;} = true;
...

[Export ("showPrinter:")]
void ShowDocument (NSObject sender) {
    var dlg = new NSPrintPanel();

    // Display the print dialog as dialog box
    if (ShowPrintAsSheet) {
        dlg.BeginSheet(new NSPrintInfo(),this,this,null,new IntPtr());
    } else {
        if (dlg.RunModalWithPrintInfo(new NSPrintInfo()) == 1) {
            var alert = new NSAlert () {
                AlertStyle = NSAlertStyle.Critical,
                InformativeText = "We need to print the document here...",
                MessageText = "Print Document",
            };
            alert.RunModal ();
        }
    }
}

Jika kita mengatur ShowPrintAsSheet properti ke false, jalankan aplikasi dan tampilkan dialog cetak, berikut ini akan ditampilkan:

Kotak dialog cetak

Jika atur ShowPrintAsSheet properti ke true, jalankan aplikasi dan tampilkan dialog cetak, berikut ini akan ditampilkan:

Lembar cetak

Kode berikut akan menampilkan Dialog Tata Letak Halaman:

[Export ("showLayout:")]
void ShowLayout (NSObject sender) {
    var dlg = new NSPageLayout();

    // Display the print dialog as dialog box
    if (ShowPrintAsSheet) {
        dlg.BeginSheet (new NSPrintInfo (), this);
    } else {
        if (dlg.RunModal () == 1) {
            var alert = new NSAlert () {
                AlertStyle = NSAlertStyle.Critical,
                InformativeText = "We need to print the document here...",
                MessageText = "Print Document",
            };
            alert.RunModal ();
        }
    }
}

Jika kita mengatur ShowPrintAsSheet properti ke false, jalankan aplikasi dan tampilkan dialog tata letak cetak, berikut ini akan ditampilkan:

Dialog penyetelan halaman

Jika atur ShowPrintAsSheet properti ke true, jalankan aplikasi dan tampilkan dialog tata letak cetak, berikut ini akan ditampilkan:

Lembar penyetelan halaman

Untuk informasi selengkapnya tentang bekerja dengan Dialog Pengaturan Cetak dan Halaman, silakan lihat dokumentasi NSPrintPanel dan NSPageLayout Apple.

Dialog Simpan

Dialog Simpan memberi pengguna cara yang konsisten untuk menyimpan item dalam aplikasi.

Kode berikut akan menampilkan Dialog Simpan standar:

public bool ShowSaveAsSheet { get; set;} = true;
...

[Export("saveDocumentAs:")]
void ShowSaveAs (NSObject sender)
{
    var dlg = new NSSavePanel ();
    dlg.Title = "Save Text File";
    dlg.AllowedFileTypes = new string[] { "txt", "html", "md", "css" };

    if (ShowSaveAsSheet) {
        dlg.BeginSheet(mainWindowController.Window,(result) => {
            var alert = new NSAlert () {
                AlertStyle = NSAlertStyle.Critical,
                InformativeText = "We need to save the document here...",
                MessageText = "Save Document",
            };
            alert.RunModal ();
        });
    } else {
        if (dlg.RunModal () == 1) {
            var alert = new NSAlert () {
                AlertStyle = NSAlertStyle.Critical,
                InformativeText = "We need to save the document here...",
                MessageText = "Save Document",
            };
            alert.RunModal ();
        }
    }

}

Properti AllowedFileTypes adalah array string jenis file yang dapat dipilih pengguna untuk menyimpan file sebagai. Jenis file dapat ditentukan sebagai ekstensi atau UTI. Nilai defaultnya adalah null, yang memungkinkan jenis file apa pun digunakan.

Jika kita mengatur ShowSaveAsSheet properti ke false, jalankan aplikasi dan pilih Simpan Sebagai... dari menu File , berikut ini akan ditampilkan:

Kotak dialog simpan

Pengguna dapat memperluas dialog:

Kotak dialog penyimpanan yang diperluas

Jika kita mengatur ShowSaveAsSheet properti ke true, jalankan aplikasi dan pilih Simpan Sebagai... dari menu File , berikut ini akan ditampilkan:

Lembar penyimpanan

Pengguna dapat memperluas dialog:

Lembar penyimpanan yang diperluas

Untuk informasi selengkapnya tentang bekerja dengan Dialog Simpan, silakan lihat dokumentasi NSSavePanel Apple.

Ringkasan

Artikel ini telah melihat secara rinci bekerja dengan Modal Windows, Spreadsheet, dan Kotak Dialog sistem standar dalam aplikasi Xamarin.Mac. Kami melihat berbagai jenis dan penggunaan Modal Windows, Lembar dan Dialog, cara membuat dan memelihara Windows modal dan Lembar di Penyusun Antarmuka Xcode dan cara bekerja dengan Windows Modal, Lembar dan Dialog dalam kode C#.