Frage

Ich habe eine benutzerdefinierte Steuerung mit einem Textfeld auf es und ich mag die Basislinie belichten (des Textes in der Textbox) Ausrichtungslinie außerhalb der benutzerdefinierten Kontrolle. Ich weiß, dass Sie einen Designer (geerbt von Controldesigner) erstellen und Ausrichtungslinien außer Kraft setzen Zugriff auf die Ausrichtungslinien zu bekommen, aber ich frage mich, wie die Textgrundlinie einer Kontrolle zu bekommen, die ich durch meine benutzerdefinierte Kontrolle ausgesetzt.

War es hilfreich?

Lösung

Ich hatte gerade ein ähnliches Bedürfnis, und ich löste es wie folgt aus:

 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;
    }
}

Auf diese Weise ist es tatsächlich einen temporären Unter Designern für das Substeuerelement, um die „echte“ Baseline-Ausrichtungslinie ist, um herauszufinden, wo die Schaffung.

Dies schien in der Prüfung einigermaßen performant, aber wenn perf wird ein Anliegen (und wenn das interne Textfeld bewegt sich nicht), dann können die meisten dieser Code an die Initialize-Methode extrahiert werden.

Dies setzt auch voraus, dass die Textbox ein direkter Nachkomme des Usercontrol ist. Wenn es andere Layout beeinträchtig Kontrollen in der Art und Weise sind dann die Offset-Berechnung wird ein wenig komplizierter.

Andere Tipps

Als ein Update auf die Antwort der Miral .. hier sind ein paar der „fehlenden Schritte“, für jemanden Neues, das schaut, wie dies zu tun. :) Der C # -Code oben ist fast ‚Drop-in‘ bereit, mit Ausnahme von ein paar der Werte Ändern des Usercontrol zu verweisen, die geändert werden sollen.

Mögliche Referenzen benötigt:
    System.Design (@robyaw)

Usings benötigt:

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

Auf Ihrem Usercontrol benötigen Sie folgendes Attribut:

[Designer(typeof(MyCustomDesigner))]

Dann brauchen Sie eine „Designer“ Klasse, die die Ausrichtungslinien außer Kraft setzen müssen:

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;
}

    }
  }
}

Danke an alle, die für die Hilfe. Dies war eine schwierige Frage zu schlucken. Der Gedanke, eine private Unterklasse in jedem Usercontrol mit war nicht sehr schmackhaft.

Ich kam mit dieser Basisklasse bis .. zu helfen

[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;
            }
        }
    }
}

Als nächstes leiten Sie Ihr Benutzersteuerelement von dieser Basis:

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

    ...

}

Nochmals vielen Dank für dieses Posting.

VB.Net Version:
Hinweis: Sie können die txtDescription auf die Textbox oder einem anderen internen Kontroll Namen ändern, die Sie verwenden. und ctlUserControl zu Ihrem usercontrol Namen

<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

Sie sind auf dem richtigen Weg. Sie müssen die Ausrichtungslinien Eigenschaft in Ihrem DesignR außer Kraft zu setzen und so etwas tun:

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

In diesem Beispiel wird die Usercontrol ein Textfeld enthält. Der Code fügt eine neue Ausrichtungslinie, die die Grundlage für die Textbox darstellt. Das Wichtigste ist, die richtig Offset zu berechnen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top