سؤال

لدي عنصر تحكم مستخدم مخصص به مربع نص وأرغب في كشف خط الأساس (للنص الموجود في مربع النص) خارج عنصر التحكم المخصص.أعلم أنك تقوم بإنشاء مصمم (موروث من ControlDesigner) وتجاوز SnapLines للوصول إلى خطوط Snaplines، لكنني أتساءل عن كيفية الحصول على الخط الأساسي للنص لعنصر التحكم الذي كشفته من خلال عنصر تحكم المستخدم المخصص الخاص بي.

هل كانت مفيدة؟

المحلول

لقد كانت لدي حاجة مماثلة، وقمت بحلها على النحو التالي:

 public override IList SnapLines
{
    get
    {
        IList snapLines = base.SnapLines;

        MyControl control = Control as MyControl;
        if (control == null) { return snapLines; }

        IDesigner designer = TypeDescriptor.CreateDesigner(
            control.textBoxValue, typeof(IDesigner));
        if (designer == null) { return snapLines; }
        designer.Initialize(control.textBoxValue);

        using (designer)
        {
            ControlDesigner boxDesigner = designer as ControlDesigner;
            if (boxDesigner == null) { return snapLines; }

            foreach (SnapLine line in boxDesigner.SnapLines)
            {
                if (line.SnapLineType == SnapLineType.Baseline)
                {
                    snapLines.Add(new SnapLine(SnapLineType.Baseline,
                        line.Offset + control.textBoxValue.Top,
                        line.Filter, line.Priority));
                    break;
                }
            }
        }

        return snapLines;
    }
}

بهذه الطريقة يتم في الواقع إنشاء مصمم فرعي مؤقت لعنصر التحكم الفرعي من أجل معرفة مكان خط الأساس "الحقيقي".

بدا هذا أداءً معقولًا في الاختبار، ولكن إذا أصبح الأداء مصدر قلق (وإذا لم يتحرك مربع النص الداخلي)، فيمكن استخراج معظم هذا الرمز إلى طريقة التهيئة.

يفترض هذا أيضًا أن مربع النص هو تابع مباشر لـ UserControl.إذا كانت هناك عناصر تحكم أخرى تؤثر على التخطيط في الطريقة، يصبح حساب الإزاحة أكثر تعقيدًا بعض الشيء.

نصائح أخرى

كتحديث لإجابة ميرال ..فيما يلي بعض "الخطوات المفقودة" لشخص جديد يبحث عن كيفية القيام بذلك.:) كود C# أعلاه جاهز للاستخدام تقريبًا، باستثناء تغيير عدد قليل من القيم للإشارة إلى UserControl الذي سيتم تعديله.

المراجع المحتملة المطلوبة:
تصميم النظام (@robyaw)

الاستخدامات اللازمة:

using System.Windows.Forms.Design;
using System.Windows.Forms.Design.Behavior;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections;

في UserControl الخاص بك، تحتاج إلى السمة التالية:

[Designer(typeof(MyCustomDesigner))]

إذن أنت بحاجة إلى فئة "المصمم" التي ستتجاوز SnapLines:

private class MyCustomerDesigner : ControlDesigner {
  public override IList SnapLines {
    get {
     /* Code from above */
    IList snapLines = base.SnapLines;

    // *** This will need to be modified to match your user control
    MyControl control = Control as MyControl;
    if (control == null) { return snapLines; }

    // *** This will need to be modified to match the item in your user control
    // This is the control in your UC that you want SnapLines for the entire UC
    IDesigner designer = TypeDescriptor.CreateDesigner(
        control.textBoxValue, typeof(IDesigner));
    if (designer == null) { return snapLines; }

    // *** This will need to be modified to match the item in your user control
    designer.Initialize(control.textBoxValue);

    using (designer)
    {
        ControlDesigner boxDesigner = designer as ControlDesigner;
        if (boxDesigner == null) { return snapLines; }

        foreach (SnapLine line in boxDesigner.SnapLines)
        {
            if (line.SnapLineType == SnapLineType.Baseline)
            {
                // *** This will need to be modified to match the item in your user control
                snapLines.Add(new SnapLine(SnapLineType.Baseline,
                    line.Offset + control.textBoxValue.Top,
                    line.Filter, line.Priority));
                break;
            }
        }
    }

    return snapLines;
}

    }
  }
}

شكرا لجميع تلك للمساعدة.كان هذا أمرًا صعبًا للابتلاع.لم تكن فكرة وجود فئة فرعية خاصة في كل UserControl مستساغة للغاية.

لقد توصلت إلى هذه الفئة الأساسية للمساعدة..

[Designer(typeof(UserControlSnapLineDesigner))]
public class UserControlBase : UserControl
{
    protected virtual Control SnapLineControl { get { return null; } }

    private class UserControlSnapLineDesigner : ControlDesigner
    {
        public override IList SnapLines
        {
            get
            {
                IList snapLines = base.SnapLines;

                Control targetControl = (this.Control as UserControlBase).SnapLineControl;

                if (targetControl == null)
                    return snapLines;

                using (ControlDesigner controlDesigner = TypeDescriptor.CreateDesigner(targetControl,
                    typeof(IDesigner)) as ControlDesigner)
                {
                    if (controlDesigner == null)
                        return snapLines;

                    controlDesigner.Initialize(targetControl);

                    foreach (SnapLine line in controlDesigner.SnapLines)
                    {
                        if (line.SnapLineType == SnapLineType.Baseline)
                        {
                            snapLines.Add(new SnapLine(SnapLineType.Baseline, line.Offset + targetControl.Top,
                                line.Filter, line.Priority));
                            break;
                        }
                    }
                }
                return snapLines;
            }
        }
    }
}

بعد ذلك، اشتق UserControl الخاص بك من هذه القاعدة:

public partial class MyControl : UserControlBase
{
    protected override Control SnapLineControl
    {
        get
        {
            return txtTextBox;
        }
    }

    ...

}

شكرا مرة أخرى لنشر هذه.

نسخة VB.Net:
ملحوظة:عليك تغيير txtDescription إلى مربع النص أو اسم عنصر تحكم داخلي آخر تستخدمه.و ctlUserControl لك usercontrol اسم

<Designer(GetType(ctlUserControl.MyCustomDesigner))> _
Partial Public Class ctlUserControl
   '... 
   'Your Usercontrol class specific code
   '... 
    Class MyCustomDesigner
        Inherits ControlDesigner
        Public Overloads Overrides ReadOnly Property SnapLines() As IList
            Get
                ' Code from above 

                Dim lines As IList = MyBase.SnapLines

                ' *** This will need to be modified to match your user control
                Dim control__1 As ctlUserControl = TryCast(Me.Control, ctlUserControl)
                If control__1 Is Nothing Then Return lines

                ' *** This will need to be modified to match the item in your user control
                ' This is the control in your UC that you want SnapLines for the entire UC
                Dim designer As IDesigner = TypeDescriptor.CreateDesigner(control__1.txtDescription, GetType(IDesigner))
                If designer Is Nothing Then
                    Return lines
                End If

                ' *** This will need to be modified to match the item in your user control
                designer.Initialize(control__1.txtDescription)

                Using designer
                    Dim boxDesigner As ControlDesigner = TryCast(designer, ControlDesigner)
                    If boxDesigner Is Nothing Then
                        Return lines
                    End If

                    For Each line As SnapLine In boxDesigner.SnapLines
                        If line.SnapLineType = SnapLineType.Baseline Then
                            ' *** This will need to be modified to match the item in your user control
                            lines.Add(New SnapLine(SnapLineType.Baseline, line.Offset + control__1.txtDescription.Top, line.Filter, line.Priority))
                            Exit For
                        End If
                    Next
                End Using

                Return lines
            End Get
        End Property
    End Class

End Class

أنت على الطريق الصحيح.ستحتاج إلى تجاوز خاصية SnapLines في المصمم الخاص بك والقيام بشيء مثل هذا:

Public Overrides ReadOnly Property SnapLines() As System.Collections.IList
    Get
        Dim snapLinesList As ArrayList = TryCast(MyBase.SnapLines, ArrayList)

        Dim offset As Integer
        Dim ctrl As MyControl = TryCast(Me.Control, MyControl)
        If ctrl IsNot Nothing AndAlso ctrl.TextBox1 IsNot Nothing Then
            offset = ctrl.TextBox1.Bottom - 5
        End If

        snapLinesList.Add(New SnapLine(SnapLineType.Baseline, offset, SnapLinePriority.Medium))

        Return snapLinesList

    End Get
End Property

في هذا المثال، يحتوي عنصر تحكم المستخدم على مربع نص.يضيف الكود خطًا جديدًا يمثل الخط الأساسي لمربع النص.الشيء المهم هو حساب الإزاحة بشكل صحيح.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top