Adakah yang menemukan solusi yang berguna untuk masalah DesignMode saat mengembangkan kontrol?
Masalahnya adalah jika Anda menumpuk kontrol maka DesignMode hanya berfungsi untuk tingkat pertama. DesignMode tingkat kedua dan yang lebih rendah akan selalu mengembalikan FALSE.
Peretasan standar adalah untuk melihat nama proses yang sedang berjalan dan jika itu adalah "DevEnv.EXE" maka itu harus studio sehingga DesignMode benar-benar BENAR.
Masalah dengan yang mencari ProcessName bekerja melalui registri dan bagian aneh lainnya dengan hasil akhir bahwa pengguna mungkin tidak memiliki hak yang diperlukan untuk melihat nama proses. Selain itu, rute aneh ini sangat lambat. Jadi kami harus menumpuk peretasan tambahan untuk menggunakan singleton dan jika kesalahan muncul saat meminta nama proses, maka asumsikan bahwa DesignMode adalah FALSE.
Cara bersih yang bagus untuk menentukan DesignMode sudah beres. Sebenarnya meminta Microsoft untuk memperbaikinya secara internal ke kerangka akan lebih baik!
sumber
Jawaban:
Meninjau kembali pertanyaan ini, saya sekarang telah 'menemukan' 5 cara berbeda untuk melakukan ini, yaitu sebagai berikut:
System.ComponentModel.DesignMode property System.ComponentModel.LicenseManager.UsageMode property private string ServiceString() { if (GetService(typeof(System.ComponentModel.Design.IDesignerHost)) != null) return "Present"; else return "Not present"; } public bool IsDesignerHosted { get { Control ctrl = this; while(ctrl != null) { if((ctrl.Site != null) && ctrl.Site.DesignMode) return true; ctrl = ctrl.Parent; } return false; } } public static bool IsInDesignMode() { return System.Reflection.Assembly.GetExecutingAssembly() .Location.Contains("VisualStudio")) }
Untuk mencoba dan memahami tiga solusi yang diusulkan, saya membuat sedikit solusi uji - dengan tiga proyek:
Saya kemudian menyematkan SubSubControl di SubControl, lalu salah satu dari masing-masing di TestApp.Form.
Tangkapan layar ini menunjukkan hasil saat dijalankan.
Tangkapan layar ini menunjukkan hasil dengan formulir terbuka di Visual Studio:
Kesimpulan: Tampaknya tanpa refleksi satu-satunya yang dapat diandalkan dalam konstruktor adalah LicenseUsage, dan satu-satunya yang dapat diandalkan di luar konstruktor adalah 'IsDesignedHosted' (oleh BlueRaja di bawah)
NB: Lihat komentar ToolmakerSteve di bawah ini (yang belum saya uji): "Perhatikan bahwa jawaban IsDesignerHosted telah diperbarui untuk menyertakan LicenseUsage ..., jadi sekarang pengujiannya dapat berupa if (IsDesignerHosted). Pendekatan alternatif adalah menguji LicenseManager di konstruktor dan menyimpan hasilnya ke dalam cache . "
sumber
if(LicenseUseage == LicenseUsageMode.Designtime || IsDesignerHosted)
akan menjadi pendekatan yang 100% benar?LicenseUsage...
, jadi sekarang tesnya bisa jadiif (IsDesignerHosted)
. Pendekatan alternatif adalah menguji LicenseManager di konstruktor dan menyimpan hasilnya ke dalam cache .Dari halaman ini :
( [Sunting 2013] Diedit untuk bekerja di konstruktor, menggunakan metode yang disediakan oleh @hopla)
/// <summary> /// The DesignMode property does not correctly tell you if /// you are in design mode. IsDesignerHosted is a corrected /// version of that property. /// (see https://connect.microsoft.com/VisualStudio/feedback/details/553305 /// and http://stackoverflow.com/a/2693338/238419 ) /// </summary> public bool IsDesignerHosted { get { if (LicenseManager.UsageMode == LicenseUsageMode.Designtime) return true; Control ctrl = this; while (ctrl != null) { if ((ctrl.Site != null) && ctrl.Site.DesignMode) return true; ctrl = ctrl.Parent; } return false; } }
Saya telah mengirimkan laporan bug dengan Microsoft; Saya ragu itu akan pergi ke mana pun, tetapi pilihlah itu, karena ini jelas bug (apakah itu "berdasarkan desain" atau tidak ).
sumber
Mengapa Anda tidak memeriksa LicenseManager.UsageMode. Properti ini dapat memiliki nilai LicenseUsageMode.Runtime atau LicenseUsageMode.Designtime.
Apakah Anda ingin kode hanya dijalankan di runtime, gunakan kode berikut:
if (LicenseManager.UsageMode == LicenseUsageMode.Runtime) { bla bla bla... }
sumber
Ini adalah metode yang saya gunakan di dalam formulir:
/// <summary> /// Gets a value indicating whether this instance is in design mode. /// </summary> /// <value> /// <c>true</c> if this instance is in design mode; otherwise, <c>false</c>. /// </value> protected bool IsDesignMode { get { return DesignMode || LicenseManager.UsageMode == LicenseUsageMode.Designtime; } }
Dengan cara ini, hasilnya akan benar, meskipun salah satu properti DesignMode atau LicenseManager gagal.
sumber
Saya menggunakan metode LicenseManager, tetapi menyimpan nilai dari konstruktor untuk digunakan selama masa pakai instance.
public MyUserControl() { InitializeComponent(); m_IsInDesignMode = (LicenseManager.UsageMode == LicenseUsageMode.Designtime); } private bool m_IsInDesignMode = true; public bool IsInDesignMode { get { return m_IsInDesignMode; } }
Versi VB:
Sub New() InitializeComponent() m_IsInDesignMode = (LicenseManager.UsageMode = LicenseUsageMode.Designtime) End Sub Private ReadOnly m_IsInDesignMode As Boolean = True Public ReadOnly Property IsInDesignMode As Boolean Get Return m_IsInDesignMode End Get End Property
sumber
Kami menggunakan kode ini dengan sukses:
public static bool IsRealDesignerMode(this Control c) { if (System.ComponentModel.LicenseManager.UsageMode == System.ComponentModel.LicenseUsageMode.Designtime) return true; else { Control ctrl = c; while (ctrl != null) { if (ctrl.Site != null && ctrl.Site.DesignMode) return true; ctrl = ctrl.Parent; } return System.Diagnostics.Process.GetCurrentProcess().ProcessName == "devenv"; } }
sumber
Saran saya adalah optimalisasi @ blueraja-danny-pflughoeft balasan . Solusi ini tidak menghitung hasil setiap kali tetapi hanya pertama kali (objek tidak dapat mengubah UsageMode dari desain ke runtime)
private bool? m_IsDesignerHosted = null; //contains information about design mode state /// <summary> /// The DesignMode property does not correctly tell you if /// you are in design mode. IsDesignerHosted is a corrected /// version of that property. /// (see https://connect.microsoft.com/VisualStudio/feedback/details/553305 /// and https://stackoverflow.com/a/2693338/238419 ) /// </summary> [Browsable(false)] public bool IsDesignerHosted { get { if (m_IsDesignerHosted.HasValue) return m_IsDesignerHosted.Value; else { if (LicenseManager.UsageMode == LicenseUsageMode.Designtime) { m_IsDesignerHosted = true; return true; } Control ctrl = this; while (ctrl != null) { if ((ctrl.Site != null) && ctrl.Site.DesignMode) { m_IsDesignerHosted = true; return true; } ctrl = ctrl.Parent; } m_IsDesignerHosted = false; return false; } } }
sumber
Saya tidak pernah terperangkap oleh ini sendiri, tetapi tidak bisakah Anda berjalan kembali ke rantai Induk dari kontrol untuk melihat apakah DesignMode disetel di mana saja di atas Anda?
sumber
Karena tidak ada metode yang dapat diandalkan (DesignMode, LicenseManager) atau efisien (Proses, pemeriksaan rekursif), saya menggunakan
public static bool Runtime { get; private set }
pada tingkat program dan secara eksplisit mengaturnya di dalam metode Main ().sumber
DesignMode adalah milik pribadi (dari apa yang saya tahu). Jawabannya adalah menyediakan properti publik yang mengekspos prop DesignMode. Kemudian Anda dapat membuat cadangan rantai kontrol pengguna hingga Anda menjalankan kontrol non-pengguna atau kontrol yang ada dalam mode desain. Sesuatu seperti ini....
public bool RealDesignMode() { if (Parent is MyBaseUserControl) { return (DesignMode ? true : (MyBaseUserControl) Parent.RealDesignMode; } return DesignMode; }
Di mana semua UserControl Anda diwarisi dari MyBaseUserControl. Atau Anda dapat menerapkan antarmuka yang mengekspos "RealDeisgnMode".
Harap dicatat bahwa kode ini bukanlah kode langsung, hanya sekedar renungan. :)
sumber
Saya tidak menyadari bahwa Anda tidak dapat memanggil Parent.DesignMode (dan saya telah belajar sesuatu tentang 'dilindungi' di C # juga ...)
Berikut adalah versi reflektifnya: (Saya menduga mungkin ada keuntungan kinerja untuk menjadikan designModeProperty bidang statis)
static bool IsDesignMode(Control control) { PropertyInfo designModeProperty = typeof(Component). GetProperty("DesignMode", BindingFlags.Instance | BindingFlags.NonPublic); while (designModeProperty != null && control != null) { if((bool)designModeProperty.GetValue(control, null)) { return true; } control = control.Parent; } return false; }
sumber
Saya harus mengatasi masalah ini baru-baru ini di Visual Studio 2017 saat menggunakan UserControls bersarang. Saya menggabungkan beberapa pendekatan yang disebutkan di atas dan di tempat lain, kemudian mengubah kode sampai saya memiliki metode ekstensi yang layak yang berfungsi dengan baik sejauh ini. Ini melakukan urutan pemeriksaan, menyimpan hasilnya dalam variabel boolean statis sehingga setiap pemeriksaan hanya dilakukan paling banyak hanya sekali pada waktu proses. Prosesnya mungkin berlebihan, tetapi mencegah kode dijalankan di studio. Semoga ini bisa membantu seseorang.
public static class DesignTimeHelper { private static bool? _isAssemblyVisualStudio; private static bool? _isLicenseDesignTime; private static bool? _isProcessDevEnv; private static bool? _mIsDesignerHosted; /// <summary> /// Property <see cref="Form.DesignMode"/> does not correctly report if a nested <see cref="UserControl"/> /// is in design mode. InDesignMode is a corrected that property which . /// (see https://connect.microsoft.com/VisualStudio/feedback/details/553305 /// and https://stackoverflow.com/a/2693338/238419 ) /// </summary> public static bool InDesignMode( this Control userControl, string source = null) => IsLicenseDesignTime || IsProcessDevEnv || IsExecutingAssemblyVisualStudio || IsDesignerHosted(userControl); private static bool IsExecutingAssemblyVisualStudio => _isAssemblyVisualStudio ?? (_isAssemblyVisualStudio = Assembly .GetExecutingAssembly() .Location.Contains(value: "VisualStudio")) .Value; private static bool IsLicenseDesignTime => _isLicenseDesignTime ?? (_isLicenseDesignTime = LicenseManager.UsageMode == LicenseUsageMode.Designtime) .Value; private static bool IsDesignerHosted( Control control) { if (_mIsDesignerHosted.HasValue) return _mIsDesignerHosted.Value; while (control != null) { if (control.Site?.DesignMode == true) { _mIsDesignerHosted = true; return true; } control = control.Parent; } _mIsDesignerHosted = false; return false; } private static bool IsProcessDevEnv => _isProcessDevEnv ?? (_isProcessDevEnv = Process.GetCurrentProcess() .ProcessName == "devenv") .Value; }
sumber