我通过创建自定义控件(类型为内容控件,在模板中带有边框、按钮和弹出窗口)并覆盖内容控件的 MouseEnter 和 MouseLeave 事件来使其工作。
这是我使用的自定义控件类(vb.net):
Imports System.Windows.Controls.Primitives
Imports System.Collections.ObjectModel
Imports System.Text
<TemplatePart(Name:="PART_TargetContentBorder", Type:=GetType(Border))> _
<TemplatePart(Name:="PART_MenuButton", Type:=GetType(Button))> _
<TemplatePart(Name:="PART_Popup", Type:=GetType(Popup))> _
Public Class HoverMenuButton
Inherits ContentControl
#Region "DECLARATIONS"
Private HoverPopUp As Popup
Private TargetBorder As Border
Private TargetButton As Button
#End Region
#Region "PROPERTIES"
#End Region
#Region "DEPENDENCY PROPERTIES "
''' <summary>
''' BORDER STYLE: The Style of the Border the wraps the Popup and PopUp's Target Placement Element
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property BorderStyle As Style
Get
Return GetValue(BorderStyleProperty)
End Get
Set(ByVal value As Style)
SetValue(BorderStyleProperty, value)
End Set
End Property
Public Shared ReadOnly BorderStyleProperty As DependencyProperty = DependencyProperty.Register( _
"BorderStyle", GetType(Style), GetType(HoverMenuButton), _
New FrameworkPropertyMetadata(Nothing, FrameworkPropertyMetadataOptions.AffectsRender))
''' <summary>
''' POPUP STYLE: The Style of the Popup
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property PopUpStyle As Style
Get
Return GetValue(PopUpStyleProperty)
End Get
Set(ByVal value As Style)
SetValue(PopUpStyleProperty, value)
End Set
End Property
Public Shared ReadOnly PopUpStyleProperty As DependencyProperty = DependencyProperty.Register( _
"PopUpStyle", GetType(Style), GetType(HoverMenuButton), _
New FrameworkPropertyMetadata(Nothing, FrameworkPropertyMetadataOptions.AffectsRender))
''' <summary>
''' BUTTON STYLE: The Style of the Button
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property ButtonStyle As Style
Get
Return GetValue(ButtonStyleProperty)
End Get
Set(ByVal value As Style)
SetValue(ButtonStyleProperty, value)
End Set
End Property
Public Shared ReadOnly ButtonStyleProperty As DependencyProperty = DependencyProperty.Register( _
"ButtonStyle", GetType(Style), GetType(HoverMenuButton), _
New FrameworkPropertyMetadata(Nothing, FrameworkPropertyMetadataOptions.AffectsRender))
''' <summary>
''' BUTTON CONTENT: The Text of the Button
''' </summary>
''' <remarks></remarks>
Public Property ButtonContent As String
Get
Return GetValue(ButtonContentProperty)
End Get
Set(ByVal value As String)
SetValue(ButtonContentProperty, value)
End Set
End Property
Public Shared ReadOnly ButtonContentProperty As DependencyProperty = DependencyProperty.Register( _
"ButtonContent", GetType(String), GetType(HoverMenuButton), _
New FrameworkPropertyMetadata(Nothing, FrameworkPropertyMetadataOptions.AffectsRender))
''' <summary>
''' BUTTON COMMAND: The iCommand of the button
''' </summary>
''' <remarks></remarks>
Public Property ButtonComand As ICommand
Get
Return GetValue(ButtonComandProperty)
End Get
Set(ByVal value As ICommand)
SetValue(ButtonComandProperty, value)
End Set
End Property
Public Shared ReadOnly ButtonComandProperty As DependencyProperty = DependencyProperty.Register( _
"ButtonComand", GetType(ICommand), GetType(HoverMenuButton), _
New FrameworkPropertyMetadata(Nothing, FrameworkPropertyMetadataOptions.AffectsRender))
''' <summary>
''' BUTTON COMMAND: The iCommand of the button
''' </summary>
''' <remarks></remarks>
Public Property ButtonComandParameter As String
Get
Return GetValue(ButtonComandParameterProperty)
End Get
Set(ByVal value As String)
SetValue(ButtonComandParameterProperty, value)
End Set
End Property
Public Shared ReadOnly ButtonComandParameterProperty As DependencyProperty = DependencyProperty.Register( _
"ButtonComandParameter", GetType(String), GetType(HoverMenuButton), _
New FrameworkPropertyMetadata(Nothing, FrameworkPropertyMetadataOptions.AffectsRender))
#End Region
#Region "INITIALIZE CONTROLS"
Private Sub InitializePopup()
If HoverPopUp Is Nothing Then
HoverPopUp = TryCast(Me.Template.FindName("PART_Popup", Me), Popup)
End If
End Sub
Private Sub InitializeTargetBorder()
If TargetBorder Is Nothing Then
TargetBorder = TryCast(Me.Template.FindName("PART_TargetContentBorder", Me), Border)
End If
End Sub
Private Sub InitializeTargetButton()
If TargetButton Is Nothing Then
TargetButton = TryCast(Me.Template.FindName("PART_MenuButton", Me), Button)
End If
End Sub
#End Region
#Region "POPUP METHODS"
Private Sub PopupOpen()
If HoverPopUp IsNot Nothing Then
HoverPopUp.IsOpen = True
End If
End Sub
Private Sub PopupClose()
If HoverPopUp IsNot Nothing AndAlso HoverPopUp.IsOpen = True Then
HoverPopUp.IsOpen = False
Else
Return
End If
End Sub
#End Region
#Region "CLASS METHODS"
#End Region
#Region "BASE CONTENT CONTROL EVENT HANDELRS"
Protected Overrides Sub OnMouseLeave(e As MouseEventArgs)
MyBase.OnMouseLeave(e)
PopupClose()
End Sub
Protected Overrides Sub OnMouseEnter(e As MouseEventArgs)
MyBase.OnMouseEnter(e)
PopupOpen()
End Sub
#End Region
#Region "APPLY TEMPLATE"
Public Overrides Sub OnApplyTemplate()
MyBase.OnApplyTemplate()
'' if template is not nothing then initialize controls and wire up the event handlers
If Me.Template IsNot Nothing Then
InitializePopup()
InitializeTargetBorder()
InitializeTargetButton()
''Apply any styles / properties defined
If TargetButton IsNot Nothing Then
If ButtonStyle IsNot Nothing Then
TargetButton.Style = ButtonStyle
End If
If ButtonContent IsNot Nothing Then
TargetButton.Content = ButtonContent
End If
If ButtonComand IsNot Nothing Then
TargetButton.Command = ButtonComand
If ButtonComandParameter IsNot Nothing Then
TargetButton.CommandParameter = ButtonComandParameter
End If
End If
End If
If HoverPopUp IsNot Nothing AndAlso PopUpStyle IsNot Nothing Then
HoverPopUp.Style = PopUpStyle
End If
If TargetBorder IsNot Nothing AndAlso BorderStyle IsNot Nothing Then
TargetBorder.Style = BorderStyle
End If
End If
End Sub
#End Region
#Region "CONSTRUCTOR"
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(HoverMenuButton), New FrameworkPropertyMetadata(GetType(HoverMenuButton)))
End Sub
#End Region
End Class
这是通用模板的 xaml:
<Style TargetType="{x:Type local:HoverMenuButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:HoverMenuButton}">
<Border x:Name="PART_ControlBorder" SnapsToDevicePixels="true">
<StackPanel>
<Button x:Name="PART_MenuButton" />
<Popup x:Name="PART_Popup" PlacementTarget="{Binding ElementName=PART_MenuButton}" >
<ContentPresenter Content="{TemplateBinding Content}" Margin="{TemplateBinding Padding}"/>
</Popup>
</StackPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
它是在自己的项目中定义的,所以这是我在 wpf mvvm 应用程序中使用它的方式:
<CustomControl:HoverMenuButton ButtonContent="Test" ButtonStyle="{StaticResource NavChildButton}">
<Border Style="{StaticResource FTC_ButtonBorders}" >
<WrapPanel Orientation="Vertical" >
<Button Content="Vie_w Jobs" Style="{StaticResource NavSubButton}" Command="{Binding NavigateSubCommand}" CommandParameter="jobview" ToolTip="Job Details" />
<Button Content="Add _New Job" Style="{StaticResource NavSubButton}" Command="{Binding NavigateSubCommand}" CommandParameter="jobadd" ToolTip="Add New Job" />
<Button Content="Job _Reports" Style="{StaticResource NavSubButton}" Command="{Binding NavigateSubCommand}" CommandParameter="jobreport" ToolTip="Display and Print Job Reports" />
</WrapPanel>
</Border>
</CustomControl:HoverMenuButton>
这将创建与我的屏幕截图完全相同的布局,但是现在如果鼠标输入按钮文本,弹出窗口将打开,如果鼠标移入弹出窗口则保持打开状态,并在鼠标离开弹出窗口和按钮文本后自动关闭。
我希望这对其他人有用
JK