دعم محرر وقت التصميم لجمع الضوابط
-
21-09-2019 - |
سؤال
أرغب في إضافة خاصية تمثل مجموعة من عناصر التحكم إلى مكون ولدي محرر تجميع يمكنني من خلاله تحديد عناصر التحكم التي تنتمي إلى المجموعة بسهولة. مقابل يفعل تقريبيا ما أريده تلقائيًا بالرمز التالي:
Private _controls As New List(Of Control)
<DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
Public ReadOnly Property SelectedControls() As List(Of Control)
Get
Return _controls
End Get
End Property
أحصل على مجموعة CollectionEditor الافتراضية ، ويمكنني إضافة وإزالة عناصر التحكم ، والمجموعة متسلسلة.
المشكلة هي أنني لا أريد أن أضيف الجديد عناصر التحكم ، أريد تحديد عناصر تحكم متعددة من عناصر التحكم الأخرى المتاحة في النموذج. هل هناك أي طريقة سهلة/قياسية للقيام بذلك ، أم أنني سأضطر إلى كتابة محرر التجميع الخاص بي والركض من خلال مجموعة عناصر التحكم؟
على الرغم من وجود الكثير من المواد في محرري التجميع (UityPeeditors) ومواضيع وقت التصميم الأخرى ، لم أتمكن من العثور على أي روابط توضح هذا السلوك الدقيق ، لذلك يتم تقدير أي مساعدة.
المحلول
حسنًا ، في الوقت نفسه تناولت الغداء وكتب المحرر بنفسي. لم يكن مثل هذا الجهد الكبير. سأكون سعيدًا للمشاركة ، إذا كان ذلك يساعد.
تحرير: ملخص الحل
كتبت محررًا (انظر لقطة الشاشة) يسرد بشكل متكرر جميع عناصر التحكم الموجودة في النموذج في TreeView. إذا كانت عناصر التحكم تحتوي على نص أو خصائص صورها ، فسيتم عرض النص/الصورة. يمكن للمستخدم تحديد عناصر تحكم متعددة باستخدام مربعات الاختيار وحتى تصفية القائمة لعرض عناصر تحكم فقط لأنواع معينة.
(يجب أن أعترف ، على الرغم من ذلك ، أنه نظرًا لأن هذا المحرر كان مخصصًا للاستخدام الداخلي فقط ، لم أكن أزعج نفسي بالتحقق من خاصية الصورة بشكل عام ، فأنا أتعامل مع اثنين من أنواع التحكم المعروفة.)
الرمز الموجود في نموذج المحرر هو حقًا واجهة المستخدم ، المسؤولة عن ملء الشجرة ، وتحديد الشيكات في قائمة عناصر التحكم التي تم اختيارها مسبقًا وإعادة قائمة عناصر التحكم المحددة عندما يغلق المستخدم النموذج بموافق.
بعد ذلك ، لدينا فئة تنفذ UityPeeditor ، والتي أسميها FormControlSelectionEditor. تم تعيين هذا الفصل للخصائص التي نريد استخدام المحرر لاستخدام سمة [المحرر]. لا تفعل أكثر من ذلك بكثير من إنشاء مثيل جديد للنموذج عند الحاجة وعرضه كمربع حوار مشروط.
ثم هناك خصائص نفسها ، والتي هي من النوع. لقد اخترت ObservableCollection لأنني بحاجة إلى الرد على التغييرات في القوائم في وقت التشغيل أيضًا ، لكن القوائم الأخرى ستعمل بشكل جيد مع التكيف البسيط.
شيء واحد اكتشفته هو أنه كان عليّ أن أكتب خصائقي ومحررها بحيث يستخدمون نسخًا من قوائم عناصر التحكم. بمعنى آخر ، يقوم رمز UityPeeditor بنسخة من القائمة المخزنة في الخاصية وينقلها إلى نموذج المحرر (لتشكيل الشيكات عند فتح النموذج) ، وعندما يتم إغلاق النموذج ، قمت بمسح قائمة دعم العقار و نسخ فوق كل عنصر تحكم في القائمة التي تم إرجاعها من المحرر. لقد وجدت أنه بخلاف ذلك ، واجهت مشاكل في التسلسل في ملف .designer. لا أعتقد أنه يجب أن يكون بهذه الطريقة ؛ أعتقد أنه من المرجح أن يكون خطأ من جانبي.
رمز خاصية نموذجية:
Private WithEvents _insertButtons As New System.Collections.ObjectModel.ObservableCollection(Of Control)
<DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
<Editor(GetType(Design.FormControlSelectionEditor), GetType(UITypeEditor))> _
Public Property InsertButtons() As System.Collections.ObjectModel.ObservableCollection(Of Control)
Get
Return _insertButtons
End Get
Set(ByVal value As System.Collections.ObjectModel.ObservableCollection(Of Control))
If value Is Nothing Then
RemoveInsertButtonEventHandlers(_insertButtons)
_insertButtons.Clear()
Else
' Copy the list items passed in into the internal list
For i As Integer = _insertButtons.Count - 1 To 0 Step -1
If Not value.Contains(_insertButtons.Item(i)) Then _insertButtons.RemoveAt(i)
Next
For Each ctl As Control In value
If Not _insertButtons.Contains(ctl) Then _insertButtons.Add(ctl)
Next
End If
End Set
End Property
Private Function ShouldSerializeInsertButtons() As Boolean
Return _insertButtons.Count > 0
End Function
Private Sub ResetInsertButtons()
InsertButtons = Nothing
End Sub
لقد وضعت المحرر في ملف مضغوط ؛ قم بتنزيله هنا.
كما ذكرت من قبل ، كان هذا مجرد حل سريع وقذر مخصص للاستخدام الداخلي فقط. مع ذلك ، أقدر أي اقتراحات للتحسين.