문제

텍스트 상자가 있는 사용자 지정 사용자 정의 컨트롤이 있고 사용자 정의 컨트롤 외부에 (텍스트 상자에 있는 텍스트의) 기준선 맞춤선을 노출하고 싶습니다.ControlDesigner에서 상속된 디자이너를 만들고 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의 직접적인 하위 항목이라고 가정합니다.도중에 레이아웃에 영향을 미치는 다른 컨트롤이 있으면 오프셋 계산이 좀 더 복잡해집니다.

다른 팁

Miral의 답변에 대한 업데이트로 ..이 작업을 수행하는 방법을 찾고 있는 새로운 사람을 위한 몇 가지 "누락된 단계"가 있습니다.:) 위의 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

이 예에서 usercontrol에는 텍스트 상자가 포함되어 있습니다.코드는 텍스트 상자의 기준선을 나타내는 새 맞춤선을 추가합니다.중요한 것은 오프셋을 올바르게 계산하는 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top