Pertanyaan Komponen .NET (non-visual)


Saya perlu membuat komponen non-visual, FooComponent, yang akan melakukan manajemen untuk semua kontrol tipe Bar yang berada dalam bentuknya.

Saya memiliki batasan berikut:

  1. Itu FooComponent hanya dapat ditambahkan ke formulir.
  2. Hanya satu FooComponent per bentuk diizinkan.
  3. FooComponent harus mendaftar ke acara penutupan formulir, dan ketika kebakaran dan untuk beberapa fungsi pada semua Bardan mengirim e.Cancel nilai berdasarkan nilai yang dikembalikan.

# 1 dan # 2 di atas harus diberlakukan pada saat run-time serta waktu desain. # 3 pendaftaran acara harus dilakukan secara otomatis dan bukan oleh FooComponentpengguna.

Saya mencari Google dan MSDN untuk bantuan dan membaca tentang Component dan ComponentDesigner kelas, tetapi saya tidak menemukan apa pun untuk menyelamatkan.

Apa yang harus saya lakukan?


7
2017-11-16 14:10


asal


Jawaban:


(1) Untuk mengontrol bahwa komponen hanya dapat ditambahkan ke formulir, gunakan a FooComponent konstruktor yang melewati formulir, dan tidak mendefinisikan konstruktor default. Ini disebut seperti:

FooComponent component = new FooComponent(this);

dimana komponen dibuat dari dalam bentuk itu sendiri. Dengan tidak mendefinisikan konstruktor default, ini:

FooComponent component = new FooComponent();

tidak akan dikompilasi.


(2) Mengekspos a FooComponent properti pada formulir itu sendiri, dan di konstruktor dari FooComponent, atur formulir yang diteruskan FooComponent untuk this.


(3) Hal yang sama, di konstruktor untuk FooComponent, daftar dengan acara penutupan untuk formulir yang Anda lewati


Satukan semuanya dan Anda mendapatkan:

public class MyForm : Form {
    public FooComponent OwnedComponent { get; set; }
}


public class FooComponent {

    public FooComponent (MyForm OwnerForm) {
        OwnerForm.OwnedComponent = this;
        OwnerForm.FormClosing += MyCallback;
    }

    private void MyCallback(object sender, FormClosingEventArgs e) {
        ...
    }

}



EDIT
Sayangnya, jika Anda memerlukan konstruktor default, dan jika itu harus menjadi Komponen drop-on-the-form yang benar, tidak ada cara untuk menegakkan bahwa komponen hanya dibuat pada Formulir, atau bahwa Formulir hanya memiliki satu contoh dari komponen (bukan dari dalam komponen, anyway).

Masalahnya ada dua:
(1) Menjatuhkan komponen tidak menambahkan komponen ke formulir, itu menambahkannya ke formulir components koleksi. Jadi bahkan jika Anda bisa mendapatkan pegangan ke orang tua / pemilik, itu tidak akan pernah menjadi bentuk.

(2) Seperti yang ditunjukkan Neil, menjatuhkan komponen ke bentuk memanggil konstruktor default, yang tidak melewati parameter, dan, tentu saja, tidak ada properti komponen (seperti situs atau wadah) yang diisi.


Mungkin membantu: Sebuah komponen dapat dirancang untuk diberi tahu ketika dibuat dalam beberapa cara:

(1) Dengan menerapkan konstruktor yang membutuhkan IContainer parameter. Ketika komponen dijatuhkan pada formulir, kode yang dihasilkan akan memanggil konstruktor ini, sebagai gantinya. Namun, ini hanya akan melakukan ini saat runtime, bukan waktu desain. Tetapi wadah akan menjadi pegangan untuk bentuk itu components koleksi.

public FooComponent(IContainer container) {...}

(2) Dengan menerapkan ISupportInitialize. Ketika komponen dijatuhkan pada formulir, kode yang dihasilkan juga akan dipanggil BeginInit() dan EndInit(). Di EndInit(), Anda dapat mengakses properti seperti Site dan Container. Sekali lagi, Anda hanya akan mendapatkan ini saat runtime, bukan waktu desain, dan melemparkan pengecualian di sini tidak akan menghentikan komponen dari yang dibuat.

Tua, tetapi artikel yang sangat baik tentang Komponen dan Kontrol dari Majalah MSDN oleh Michael Weinhardt dan Chris Sells.
April 2003 Membangun Kontrol dan Komponen Bentuk Windows dengan Fitur Desain-Waktu Kaya
Mei 2003 Membangun Kontrol dan Komponen Bentuk Windows dengan Fitur Desain-Waktu Kaya, Bagian 2

Ini sekarang .chm membantu file. Anda harus membatalkan pemblokiran di halaman properti file untuk mengaktifkan pembacaan konten setelah mengunduh.


3
2017-11-16 16:25



Saya tidak berpikir itu mungkin untuk mendefinisikan dengan tepat apa yang terkandung dalam kelas terkandung. Saya sudah pasti tidak pernah melihat contoh di mana saya mendapat kesalahan (atau bahkan peringatan) untuk mengatur properti dari satu jenis yang lain, bahkan di WinForms.

Sesuatu yang mungkin bisa Anda lakukan adalah mendefinisikan asal muasal Formulir untuk formulir Anda yang berisi referensi ke FooComponent Anda (yang terlihat secara internal), menginisialisasinya pada instantiasi, dan melampirkan penangan. Untuk hasil terbaik, harus tanpa parameter dan satu-satunya konstruktor yang berlebihan, sehingga membentuk basis untuk konstruktor apa pun yang dihasilkan oleh konsumen Anda. Kemudian, buatlah aturan rumah yang berasal dari kelas leluhur Anda dan tidak langsung dari Formulir (Anda mungkin dapat menggunakan alat pemeriksaan kode seperti FxCop atau yang serupa untuk menerapkan ini ketika kode berkomitmen untuk kontrol sumber). Pengguna Anda sekarang mendapatkan FooComponent di setiap Formulir yang mereka buat, tidak dapat membuatnya sendiri (itu internal dan harus berada dalam proyek lain dengan leluhur Formulir Anda) dan tidak perlu melakukan apa pun selain berasal dari kelas baru untuk membuat bentuk mereka berperilaku. seperti yang kamu inginkan.


1
2017-11-16 15:22



Anda banyak meminta. Secara umum, membuat komponen-komponen yang sadar akan bentuk yang dijatuhkan pada mereka cukup sulit. Jawaban ini dapat membantu Anda membuat event handler diimplementasikan. Anda harus mengimplementasikan ISupportInitialize untuk mendapatkan panggilan EndInit () untuk mengatur event handler.

Mencegah kelipatan juga cukup sulit, saya hanya bisa memikirkan desainer kustom yang dapat melangkah cukup awal untuk mencegah yang kedua dari yang ditambahkan.


1
2017-11-16 20:17