Практическое руководство. Реализация конструктора для элемента управления
В данном разделе рассматривается реализация конструктора (HelpLabelDesigner) для элемента управления поставщика расширителей HelpLabel, описанного в разделе Практическое руководство. Реализация поставщика расширителей HelpLabel. Конструктор является вложенным классом в элементе управления HelpLabel. В следующем примере кода конструктора демонстрируются следующие положения:
HelpLabelDesigner является производным от ControlDesigner.
HelpLabelDesigner предоставляет доступ к команде конструктора с помощью переопределения свойства Verbs, заданного в интерфейсе IDesigner. Во время разработки команды конструктора отображаются в виде команд объекта, связанного с данным конструктором. Дополнительные сведения см. в разделе Команды конструктора.
HelpLabelDesigner добавляет в HelpLabel свойство времени разработки (TrackSelection) с помощью переопределения метода PreFilterProperties, заданного интерфейсом IDesignerFilter. Дополнительные сведения о добавлении или замене свойств и событий см. в разделе Фильтрация метаданных.
Пример
В следующем примере кода содержится код конструктора.
Примечание
Приведенный ниже код конструктора не следует компилировать отдельно.Вместо этого скомпилируйте пример из раздела Практическое руководство. Реализация поставщика расширителей HelpLabel, где код конструктора является вложенным классом.
'
' <doc>
' <desc>
' This is a designer for the HelpLabel. This designer provides
' design time feedback for the label. The help label responds
' to changes in the active control, but these events do not
' occur at design time. In order to provide some usable feedback
' that the control is working the right way, this designer listens
' to selection change events and uses those events to trigger active
' control changes.
' </desc>
' </doc>
'
<System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.Demand, Name:="FullTrust")> _
Public Class HelpLabelDesigner
Inherits System.Windows.Forms.Design.ControlDesigner
Private _trackSelection As Boolean = True
' <summary>
' This property is added to the control's set of properties in the method
' PreFilterProperties below. Note that on designers, properties that are
' explictly declared by TypeDescriptor.CreateProperty can be declared as
' private on the designer. This helps to keep the designer's public
' object model clean.
' </summary>
<DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _
Private Property TrackSelection() As Boolean
Get
Return _trackSelection
End Get
Set(ByVal Value As Boolean)
_trackSelection = Value
If _trackSelection Then
Dim ss As ISelectionService = CType(GetService(GetType(ISelectionService)), ISelectionService)
If (ss IsNot Nothing) Then
UpdateHelpLabelSelection(ss)
End If
Else
Dim helpLabel As HelpLabel = CType(Control, HelpLabel)
If (helpLabel.activeControl IsNot Nothing) Then
helpLabel.activeControl = Nothing
helpLabel.Invalidate()
End If
End If
End Set
End Property
Public Overrides ReadOnly Property Verbs() As DesignerVerbCollection
Get
Dim myVerbs() As DesignerVerb = {New DesignerVerb("Sample Verb", AddressOf OnSampleVerb)}
Return New DesignerVerbCollection(myVerbs)
End Get
End Property
'
' <doc>
' <desc>
' Overrides Dispose. Here we remove our handler for the selection changed
' event. With designers, it is critical that they clean up any events they
' have attached. Otherwise, during the course of an editing session many
' designers might get created and never destroyed.
' </desc>
' </doc>
'
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
Dim ss As ISelectionService = CType(GetService(GetType(ISelectionService)), ISelectionService)
If (ss IsNot Nothing) Then
RemoveHandler ss.SelectionChanged, AddressOf OnSelectionChanged
End If
End If
MyBase.Dispose(disposing)
End Sub
'
' <doc>
' <desc>
' Overrides initialize. Here we add an event handler to the selection service.
' Notice that we are very careful not to assume that the selection service is
' available. It is entirely optional that a service is available and you should
' always degrade gracefully if a service cannot be found.
' </desc>
' </doc>
'
Public Overrides Sub Initialize(ByVal component As IComponent)
MyBase.Initialize(component)
Dim ss As ISelectionService = CType(GetService(GetType(ISelectionService)), ISelectionService)
If (ss IsNot Nothing) Then
AddHandler ss.SelectionChanged, AddressOf OnSelectionChanged
End If
End Sub
Private Sub OnSampleVerb(ByVal sender As Object, ByVal e As EventArgs)
MessageBox.Show("You have just invoked a sample verb. Normally, this would do something interesting.")
End Sub
'
' <doc>
' <desc>
' The handler for the selection change event. Here we update the active control within
' the help label.
' </desc>
' </doc>
'
Private Sub OnSelectionChanged(ByVal sender As Object, ByVal e As EventArgs)
If _trackSelection Then
Dim ss As ISelectionService = CType(sender, ISelectionService)
UpdateHelpLabelSelection(ss)
End If
End Sub
Protected Overrides Sub PreFilterProperties(ByVal properties As IDictionary)
' Always call base first in PreFilter* methods, and last in PostFilter*
' methods.
MyBase.PreFilterProperties(properties)
' We add a design-time property called TrackSelection that is used to track
' the active selection. If the user sets this to true (the default), then
' we will listen to selection change events and update the control's active
' control to point to the current primary selection.
properties("TrackSelection") = TypeDescriptor.CreateProperty( _
Me.GetType(), _
"TrackSelection", _
GetType(Boolean), _
New Attribute() {CategoryAttribute.Design})
End Sub
' <summary>
' This is a helper method that, given a selection service, will update the active control
' of the help label with the currently active selection.
' </summary>
' <param name="ss"></param>
Private Sub UpdateHelpLabelSelection(ByVal ss As ISelectionService)
Dim c As Control = CType(ss.PrimarySelection, Control)
Dim helpLabel As HelpLabel = CType(Control, HelpLabel)
If (c IsNot Nothing) Then
helpLabel.activeControl = c
helpLabel.Invalidate()
Else
If (helpLabel.activeControl IsNot Nothing) Then
helpLabel.activeControl = Nothing
helpLabel.Invalidate()
End If
End If
End Sub
Public Sub New()
End Sub
End Class
//
// <doc>
// <desc>
// This is a designer for the HelpLabel. This designer provides
// design time feedback for the label. The help label responds
// to changes in the active control, but these events do not
// occur at design time. In order to provide some usable feedback
// that the control is working the right way, this designer listens
// to selection change events and uses those events to trigger active
// control changes.
// </desc>
// </doc>
//
[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
public class HelpLabelDesigner : System.Windows.Forms.Design.ControlDesigner
{
private bool trackSelection = true;
/// <summary>
/// This property is added to the control's set of properties in the method
/// PreFilterProperties below. Note that on designers, properties that are
/// explictly declared by TypeDescriptor.CreateProperty can be declared as
/// private on the designer. This helps to keep the designer's publi
/// object model clean.
/// </summary>
[DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )]
private bool TrackSelection
{
get
{
return trackSelection;
}
set
{
trackSelection = value;
if (trackSelection)
{
ISelectionService ss = (ISelectionService)GetService(typeof(ISelectionService));
if (ss != null)
{
UpdateHelpLabelSelection(ss);
}
}
else
{
HelpLabel helpLabel = (HelpLabel)Control;
if (helpLabel.activeControl != null)
{
helpLabel.activeControl = null;
helpLabel.Invalidate();
}
}
}
}
public override DesignerVerbCollection Verbs
{
get
{
DesignerVerb[] verbs = new DesignerVerb[] {
new DesignerVerb("Sample Verb", new EventHandler(OnSampleVerb))
};
return new DesignerVerbCollection(verbs);
}
}
//
// <doc>
// <desc>
// Overrides Dispose. Here we remove our handler for the selection changed
// event. With designers, it is critical that they clean up any events they
// have attached. Otherwise, during the course of an editing session many
// designers may get created and never destroyed.
// </desc>
// </doc>
//
protected override void Dispose(bool disposing)
{
if (disposing)
{
ISelectionService ss = (ISelectionService)GetService(typeof(ISelectionService));
if (ss != null)
{
ss.SelectionChanged -= new EventHandler(OnSelectionChanged);
}
}
base.Dispose(disposing);
}
//
// <doc>
// <desc>
// Overrides initialize. Here we add an event handler to the selection service.
// Notice that we are very careful not to assume that the selection service is
// available. It is entirely optional that a service is available and you should
// always degrade gracefully if a service could not be found.
// </desc>
// </doc>
//
public override void Initialize(IComponent component)
{
base.Initialize(component);
ISelectionService ss = (ISelectionService)GetService(typeof(ISelectionService));
if (ss != null)
{
ss.SelectionChanged += new EventHandler(OnSelectionChanged);
}
}
private void OnSampleVerb(object sender, EventArgs e)
{
MessageBox.Show("You have just invoked a sample verb. Normally, this would do something interesting.");
}
//
// <doc>
// <desc>
// Our handler for the selection change event. Here we update the active control within
// the help label.
// </desc>
// </doc>
//
private void OnSelectionChanged(object sender, EventArgs e)
{
if (trackSelection)
{
ISelectionService ss = (ISelectionService)sender;
UpdateHelpLabelSelection(ss);
}
}
protected override void PreFilterProperties(IDictionary properties)
{
// Always call base first in PreFilter* methods, and last in PostFilter*
// methods.
base.PreFilterProperties(properties);
// We add a design-time property called "TrackSelection" that is used to track
// the active selection. If the user sets this to true (the default), then
// we will listen to selection change events and update the control's active
// control to point to the current primary selection.
properties["TrackSelection"] = TypeDescriptor.CreateProperty(
this.GetType(), // the type this property is defined on
"TrackSelection", // the name of the property
typeof(bool), // the type of the property
new Attribute[] {CategoryAttribute.Design}); // attributes
}
/// <summary>
/// This is a helper method that, given a selection service, will update the active control
/// of our help label with the currently active selection.
/// </summary>
/// <param name="ss"></param>
private void UpdateHelpLabelSelection(ISelectionService ss)
{
Control c = ss.PrimarySelection as Control;
HelpLabel helpLabel = (HelpLabel)Control;
if (c != null)
{
helpLabel.activeControl = c;
helpLabel.Invalidate();
}
else
{
if (helpLabel.activeControl != null)
{
helpLabel.activeControl = null;
helpLabel.Invalidate();
}
}
}
}
См. также
Задачи
Практическое руководство. Реализация поставщика расширителей HelpLabel