Following code snippet update to my previous code snippet. In this code snippet now I have added XML doc comments and CustomPopupPlacementCallback implementation.
Imports System.Windows.Controls.Primitives
Imports System.ComponentModel
''' <summary>
''' A drop-down control control. Drop-down can be shown by clicking on the control.
''' </summary>
Public Class DropDownControl
Inherits System.Windows.Controls.Primitives.ToggleButton
''' <summary>
''' Initializes shared resources of <see cref="DropDownControl"/> class.
''' </summary>
Shared Sub New()
'This OverrideMetadata call tells the system that this element wants to provide a style that is different than its base class.
'This style is defined in themes\generic.xaml
DefaultStyleKeyProperty.OverrideMetadata(GetType(DropDownControl), New FrameworkPropertyMetadata(GetType(DropDownControl)))
End Sub
''' <summary>
''' Initializes a new instance of <see cref="DropDownControl"/> class.
''' </summary>
Public Sub New()
Popup = New Popup()
Popup.StaysOpen = False
Popup.Placement = PlacementMode.Custom
Popup.AllowsTransparency = True
Me.SetBinding(IsCheckedProperty, "Popup.IsOpen")
End Sub
''' <summary>
''' Gets or sets the Popup element.
''' </summary>
Public Property Popup As Popup
Get
Return GetValue(PopupProperty)
End Get
Set(ByVal value As Popup)
SetValue(PopupProperty, value)
End Set
End Property
''' <summary>
''' Identifies the <see cref="Popup"/> dependency property.
''' </summary>
Public Shared ReadOnly PopupProperty As DependencyProperty = _
DependencyProperty.Register("Popup", _
GetType(Popup), GetType(DropDownControl), _
New FrameworkPropertyMetadata(Nothing, New PropertyChangedCallback(AddressOf OnPopupChanged)))
''' <summary>
''' Gets or sets the Drop-down element.
''' </summary>
Public Property DropDown As FrameworkElement
Get
Return GetValue(DropDownProperty)
End Get
Set(ByVal value As FrameworkElement)
SetValue(DropDownProperty, value)
End Set
End Property
''' <summary>
''' Identifies the <see cref="DropDown"/> dependency property.
''' </summary>
''' <remarks></remarks>
Public Shared ReadOnly DropDownProperty As DependencyProperty = _
DependencyProperty.Register("DropDown", _
GetType(FrameworkElement), GetType(DropDownControl), _
New FrameworkPropertyMetadata(Nothing, New PropertyChangedCallback(AddressOf OnDropDownChanged)))
''' <summary>
''' Represents the callback that is invoked when the value of <see cref="DropDown"/> dependency property changes.
''' </summary>
''' <param name="d">The <see cref="DropDownControl"/> on which the property has changed value.</param>
''' <param name="e">Event data that is issued by any event that tracks changes to the effective value of this property.</param>
''' <remarks></remarks>
Private Shared Sub OnDropDownChanged(ByVal d As System.Windows.DependencyObject, ByVal e As System.Windows.DependencyPropertyChangedEventArgs)
Dim ddc As DropDownControl = d
If ddc.Popup IsNot Nothing Then
ddc.Popup.Child = e.NewValue
End If
End Sub
''' <summary>
''' Represents the callback that is invoked when the value of <see cref="DropDown"/> dependency property changes.
''' </summary>
''' <param name="d">The <see cref="DropDownControl"/> on which the property has changed value.</param>
''' <param name="e">Event data that is issued by any event that tracks changes to the effective value of this property.</param>
''' <remarks></remarks>
Private Shared Sub OnPopupChanged(ByVal d As System.Windows.DependencyObject, ByVal e As System.Windows.DependencyPropertyChangedEventArgs)
Dim dropdown As DropDownControl = d
Dim popup As Popup = e.NewValue
Dim oldPopup As Popup = e.OldValue
If oldPopup IsNot Nothing Then
popup.CustomPopupPlacementCallback = Nothing
End If
If popup IsNot Nothing Then
popup.CustomPopupPlacementCallback = New CustomPopupPlacementCallback(AddressOf dropdown.GetCustomPoupPlacement)
End If
End Sub
''' <summary>
''' Represents a method that provides custom positioning for a Popup control.
''' </summary>
''' <param name="popupSize">The System.Windows.Size of the System.Windows.Controls.Primitives.Popup control.</param>
''' <param name="targetSize">The System.Windows.Size of the System.Windows.Controls.Primitives.Popup.PlacementTarget.</param>
''' <param name="offset">The System.Windows.Point computed from the System.Windows.Controls.Primitives.Popup.HorizontalOffset and System.Windows.Controls.Primitives.Popup.VerticalOffset property values.</param>
Private Function GetCustomPoupPlacement(ByVal popupSize As System.Windows.Size, ByVal targetSize As System.Windows.Size, ByVal offset As System.Windows.Point) As CustomPopupPlacement()
Dim sPoint As Point = Me.PointToScreen(New Point(0, 0))
Dim tX As Double = 0
Dim tY As Double = targetSize.Height
If popupSize.Width + sPoint.X > SystemParameters.PrimaryScreenWidth Then
tX = -(popupSize.Width - targetSize.Width)
End If
If popupSize.Height + sPoint.Y > SystemParameters.PrimaryScreenHeight Then
tY = -popupSize.Height
End If
Return New CustomPopupPlacement() {New CustomPopupPlacement(New Point(tX, tY), PopupPrimaryAxis.Horizontal)}
End Function
''' <summary>
''' Called when a control is clicked by the mouse or the keyboard.
''' </summary>
Protected Overrides Sub OnClick()
MyBase.OnClick()
Popup.PlacementTarget = Me
Popup.IsOpen = True
End Sub
End Class
Emoticon Emoticon