我有一个带有文本框的自定义用户控件,我想在该自定义控件之外显示(文本框内文本的)基准线。 我知道您创建了一个设计器(从ControlDesigner继承),并且重写了SnapLines以访问细线,但是我想知道如何获取自定义用户控件公开的控件的文本基线。
作为Miral答案的更新,..以下是一些"遗漏步骤",对于正在寻找如何执行此操作的新手。 :)上面的C#代码几乎已准备就绪,只是更改了一些值以引用将要修改的UserControl。
可能需要的参考文献:
System.Design(@robyaw)
需要的用途:
1 2 3 4 5
| using System.Windows.Forms.Design;
using System.Windows.Forms.Design.Behavior;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections; |
在您的UserControl上,您需要以下属性:
1
| [Designer(typeof(MyCustomDesigner))] |
然后,您需要一个"设计器"类,该类将具有SnapLines覆盖:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| 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;
}
}
}
} |
我只是有一个类似的需求,我这样解决了它:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| 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;
}
} |
这样,它实际上为子控件创建了一个临时子设计器,以找出"实际"基线对齐线在哪里。
这似乎在测试中表现合理,但是如果担心性能(并且内部文本框不移动),则可以将大部分代码提取到Initialize方法中。
这也假定文本框是UserControl的直接子级。如果还有其他影响布局的控件,则偏移量计算将变得更加复杂。
感谢所有这些人的帮助。这是一项艰巨的任务。在每个UserControl中都有一个私有子类的想法不是很好。
我想出了这个基础课程来提供帮助。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| [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:
1 2 3 4 5 6 7 8 9 10 11 12 13
| public partial class MyControl : UserControlBase
{
protected override Control SnapLineControl
{
get
{
return txtTextBox;
}
}
...
} |
再次感谢您发布此信息。
VB.Net版本:
注意:您必须将txtDescription更改为文本框或使用的其他内部控件名称。和ctlUserControl到您的usercontrol名称
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| <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属性,并执行以下操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| 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 |
在此示例中,用户控件包含一个文本框。该代码添加了一个新的捕捉线,该捕捉线表示文本框的基线。重要的是要正确计算偏移量。