我有一个自定义用户控件,上面有一个文本框,我想在自定义控件之外公开基线(文本框中的文本)snapline.我知道您创建了一个设计器(继承自ControlDesigner)并覆盖SnapLines以访问snapline,但我想知道如何获取我自定义用户控件公开的控件的文本基线.
作为Miral答案的更新......这里有一些"缺失的步骤",对于那些正在寻找如何做到这一点的新人.:)上面的C#代码几乎可以"插入",除了更改一些值以引用将被修改的UserControl.
需要的可能参考:
System.Design(@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; } } } }
我只是有类似的需求,我这样解决了:
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; } }
这样它实际上为子控件创建了一个临时子设计器,以便找出"真正的"基线对齐线的位置.
这似乎在测试中具有相当的性能,但如果perf成为一个问题(如果内部文本框不移动),则可以将大部分代码提取到Initialize方法.
这也假定文本框是UserControl的直接子项.如果在其他方式中存在其他影响布局的控件,则偏移计算会变得有点复杂.
感谢所有人的帮助.这是一个艰难的吞下去.在每个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
名字
_
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