来自ampedZ的博客园,原文地址:http://www.cnblogs.com/ampedZ/p/PopupButton_ComboButton.html
Silverlight的弹出式控件PopupButton,以及类似ComboBox的ComboButton。
实现了OverlayBrush、OverlayOpacity,弹出位置可随着应用程序的大小智能改变,屏蔽了Silverlight右键菜单。
ComboButton实现了类似于ComboBox的功能,没有加入TextSearch功能,其他的也差不多,好像更轻便。
键盘、滚轮的操作也有跟进。
Option Explicit On Option Strict Off Imports System.Collections Imports System.Collections.ObjectModel Imports System.Collections.Specialized Imports System.Math Imports System.Windows.Controls.Primitives Imports System.Windows.Markup Namespace ampedZUserControl <TemplatePart(Name:="ToggleButton", Type:=GetType(ToggleButton)), TemplatePart(Name:="Popup", Type:=GetType(Popup)), TemplateVisualState(Name:="Normal", GroupName:="CommonStates"), TemplateVisualState(Name:="Disabled", GroupName:="CommonStates"), TemplateVisualState(Name:="Unfocused", GroupName:="FocusStates"), TemplateVisualState(Name:="Focused", GroupName:="FocusStates"), TemplateVisualState(Name:="FocusedPopup", GroupName:="FocusStates")> _ Public MustInherit Class PopupBase Inherits Control Private _Root As FrameworkElement Private _ToggleButton As ToggleButton Private _Popup As Popup Private _Canvas As Canvas Private _PopupCanvas As Canvas Private _PopupChild As FrameworkElement Private _IsFocused As Boolean Public Shared ReadOnly IsPopupOpenProperty As DependencyProperty = DependencyProperty.Register("IsPopupOpen", GetType(Boolean), GetType(PopupBase), New PropertyMetadata(False, New PropertyChangedCallback(AddressOf OnIsPopupOpenPropertyChanged))) Public Shared ReadOnly PlacementProperty As DependencyProperty = DependencyProperty.Register("Placement", GetType(PlacementMode), GetType(PopupBase), New PropertyMetadata(PlacementMode.Mouse, New PropertyChangedCallback(AddressOf OnPlacementPropertyChanged))) Public Shared ReadOnly OverlayBrushProperty As DependencyProperty = DependencyProperty.Register("OverlayBrush", GetType(Brush), GetType(PopupBase), New PropertyMetadata(New SolidColorBrush(Colors.Transparent), New PropertyChangedCallback(AddressOf OnOverlayBrushPropertyChanged))) Public Shared ReadOnly OverlayOpacityProperty As DependencyProperty = DependencyProperty.Register("OverlayOpacity", GetType(Double), GetType(PopupBase), New PropertyMetadata(1.0, New PropertyChangedCallback(AddressOf OnOverlayOpacityPropertyChanged))) Public Shared ReadOnly AutoCloseProperty As DependencyProperty = DependencyProperty.Register("AutoClose", GetType(Boolean), GetType(PopupBase), New PropertyMetadata(True, New PropertyChangedCallback(AddressOf OnAutoClosePropertyChanged))) Public Property IsPopupOpen As Boolean Get Return CType(GetValue(IsPopupOpenProperty), Boolean) End Get Set(ByVal value As Boolean) SetValue(IsPopupOpenProperty, value) End Set End Property Public Property Placement As PlacementMode Get Return CType(GetValue(PlacementProperty), PlacementMode) End Get Set(ByVal value As PlacementMode) SetValue(PlacementProperty, value) End Set End Property Public Property OverlayBrush As Brush Get Return CType(GetValue(OverlayBrushProperty), Brush) End Get Set(ByVal value As Brush) SetValue(OverlayBrushProperty, value) End Set End Property Public Property OverlayOpacity As Double Get Return CType(GetValue(OverlayOpacityProperty), Double) End Get Set(ByVal value As Double) SetValue(OverlayOpacityProperty, value) End Set End Property Public Property AutoClose As Boolean Get Return CType(GetValue(AutoCloseProperty), Boolean) End Get Set(ByVal value As Boolean) SetValue(AutoCloseProperty, value) End Set End Property Public ReadOnly Property IsFocused As Boolean Get Return _IsFocused End Get End Property Private Shared Sub OnIsPopupOpenPropertyChanged(d As System.Windows.DependencyObject, e As System.Windows.DependencyPropertyChangedEventArgs) CType(d, PopupBase).OnIsPopupOpenChanged() End Sub Private Shared Sub OnPlacementPropertyChanged(d As System.Windows.DependencyObject, e As System.Windows.DependencyPropertyChangedEventArgs) CType(d, PopupBase).OnPlacementChanged() End Sub Private Shared Sub OnOverlayBrushPropertyChanged(d As System.Windows.DependencyObject, e As System.Windows.DependencyPropertyChangedEventArgs) CType(d, PopupBase).OnOverlayBrushChanged() End Sub Private Shared Sub OnOverlayOpacityPropertyChanged(d As System.Windows.DependencyObject, e As System.Windows.DependencyPropertyChangedEventArgs) CType(d, PopupBase).OnOverlayOpacityChanged() End Sub Private Shared Sub OnAutoClosePropertyChanged(d As System.Windows.DependencyObject, e As System.Windows.DependencyPropertyChangedEventArgs) CType(d, PopupBase).OnAutoCloseChanged() End Sub Protected Overridable Sub OnIsPopupOpenChanged() If Me.IsPopupOpen Then If _ToggleButton IsNot Nothing Then _ToggleButton.IsChecked = True If _Popup IsNot Nothing Then _Popup.IsOpen = True Else If _ToggleButton IsNot Nothing Then _ToggleButton.IsChecked = False If _Popup IsNot Nothing Then _Popup.IsOpen = False End If Me.ChangeVisualState(True) End Sub Protected Overridable Sub OnPlacementChanged() ArrangePopup() End Sub Protected Overridable Sub OnOverlayBrushChanged() If _PopupCanvas IsNot Nothing Then _PopupCanvas.Background = Me.OverlayBrush End Sub Protected Overridable Sub OnOverlayOpacityChanged() If _PopupCanvas IsNot Nothing Then _PopupCanvas.Opacity = Me.OverlayOpacity End Sub Protected Overridable Sub OnAutoCloseChanged() If _PopupCanvas IsNot Nothing Then _PopupCanvas.IsHitTestVisible = Me.AutoClose End Sub Public Overrides Sub OnApplyTemplate() MyBase.OnApplyTemplate() _Root = GetRootVisual(Me) AddHandler _Root.SizeChanged, New SizeChangedEventHandler(AddressOf PopupChild_SizeChanged) _ToggleButton = TryCast(MyBase.GetTemplateChild("ToggleButton"), ToggleButton) _Popup = TryCast(MyBase.GetTemplateChild("Popup"), Popup) If _ToggleButton IsNot Nothing Then _ToggleButton.IsChecked = Me.IsPopupOpen _ToggleButton.IsTabStop = False AddHandler _ToggleButton.Click, New RoutedEventHandler(AddressOf ToggleButton_Click) End If If _Popup IsNot Nothing Then _PopupCanvas = New Canvas With {.Background = Me.OverlayBrush, .Opacity = Me.OverlayOpacity, .IsHitTestVisible = Me.AutoClose} _PopupCanvas.SetValue(Canvas.ZIndexProperty, (CInt(_Popup.GetValue(Canvas.ZIndexProperty)) - 1)) AddHandler _PopupCanvas.MouseLeftButtonDown, New MouseButtonEventHandler(AddressOf PopupCanvas_MouseLeftButtonDown) AddHandler _PopupCanvas.MouseRightButtonDown, New MouseButtonEventHandler(AddressOf PopupCanvas_MouseRightButtonDown) AddHandler _PopupCanvas.MouseWheel, New MouseWheelEventHandler(AddressOf PopupCanvas_MouseWheel) _PopupChild = _Popup.Child AddHandler _PopupChild.SizeChanged, New SizeChangedEventHandler(AddressOf PopupChild_SizeChanged) AddHandler _PopupChild.MouseRightButtonDown, New MouseButtonEventHandler(AddressOf PopupChild_MouseRightButtonDown) _Canvas = New Canvas _Popup.Child = _Canvas _Canvas.Children.Add(_PopupCanvas) _Canvas.Children.Add(_PopupChild) _Popup.IsOpen = Me.IsPopupOpen End If AddHandler MyBase.SizeChanged, New SizeChangedEventHandler(AddressOf PopupChild_SizeChanged) Me.ChangeVisualState(False) End Sub Private Shared Function GetRootVisual(ByVal Element As FrameworkElement) As FrameworkElement If Not Application.Current.IsRunningOutOfBrowser Then Return CType(Application.Current.RootVisual, FrameworkElement) Dim w As Window = Window.GetWindow(Element) If w Is Application.Current.MainWindow Then Return CType(Application.Current.RootVisual, FrameworkElement) Return w.Content End Function Protected Overridable Sub ChangeVisualState(ByVal UseTransitions As Boolean) If Not Me.IsEnabled Then VisualStateManager.GoToState(Me, "Disabled", UseTransitions) Else VisualStateManager.GoToState(Me, "Normal", UseTransitions) End If If Me.IsEnabled AndAlso _IsFocused Then If Me.IsPopupOpen Then VisualStateManager.GoToState(Me, "FocusedPopup", UseTransitions) Else VisualStateManager.GoToState(Me, "Focused", UseTransitions) End If Else VisualStateManager.GoToState(Me, "Unfocused", UseTransitions) End If End Sub Protected Overrides Function ArrangeOverride(FinalSize As Size) As Size ArrangePopup() Return MyBase.ArrangeOverride(FinalSize) End Function Protected Overridable Sub ArrangePopup() If Me.IsPopupOpen Then Dim t As GeneralTransform = Nothing Try t = _ToggleButton.TransformToVisual(Nothing) Catch ex As Exception If Me.IsPopupOpen Then Me.IsPopupOpen = False End Try If t IsNot Nothing Then Dim p As Point = t.Transform(New Point(0, 0)) Dim z As Double = If(Application.Current.Host.Settings.EnableAutoZoom, Application.Current.Host.Content.ZoomFactor, 1) Dim x As Double = p.X * z, y As Double = p.Y * z Dim tw As Double = _ToggleButton.ActualWidth * z, th As Double = _ToggleButton.ActualHeight * z Dim pw As Double = _PopupChild.ActualWidth * z, ph As Double = _PopupChild.ActualHeight * z Dim aw As Double = _Root.ActualWidth, ah As Double = _Root.ActualHeight _PopupCanvas.RenderTransform = New TranslateTransform With {.X = -x, .Y = -y} _PopupCanvas.Width = aw : _PopupCanvas.Height = ah If pw <> 0 AndAlso ph <> 0 Then Select Case Me.Placement Case PlacementMode.Mouse If aw - x >= pw AndAlso ah - y - th >= ph Then Canvas.SetLeft(_PopupChild, 0) : Canvas.SetTop(_PopupChild, th) ElseIf x + tw >= pw AndAlso ah - y - th >= ph Then Canvas.SetLeft(_PopupChild, tw - pw) : Canvas.SetTop(_PopupChild, th) ElseIf aw - x >= pw AndAlso y >= ph Then Canvas.SetLeft(_PopupChild, 0) : Canvas.SetTop(_PopupChild, -ph) ElseIf x + tw >= pw AndAlso y >= ph Then Canvas.SetLeft(_PopupChild, tw - pw) : Canvas.SetTop(_PopupChild, -ph) ElseIf aw - x - tw >= pw AndAlso ah - y >= ph Then Canvas.SetLeft(_PopupChild, tw) : Canvas.SetTop(_PopupChild, 0) ElseIf aw - x - tw >= pw AndAlso y + th >= ph Then Canvas.SetLeft(_PopupChild, tw) : Canvas.SetTop(_PopupChild, th - ph) ElseIf x >= pw AndAlso ah - y >= ph Then Canvas.SetLeft(_PopupChild, -pw) : Canvas.SetTop(_PopupChild, 0) ElseIf x >= pw AndAlso y + th > ph Then Canvas.SetLeft(_PopupChild, -pw) : Canvas.SetTop(_PopupChild, th - ph) Else Dim Area() As Double = {(aw - x) * (ah - y - th), (x + tw) * (ah - y - th), (aw - x) * (y), (x + tw) * (y), (aw - x - tw) * (ah - y), (aw - x - tw) * (y + th), (x) * (ah - y), (x) * (y + th)} Select Case MaxDouble(Area) Case Area(0) Canvas.SetLeft(_PopupChild, 0) : Canvas.SetTop(_PopupChild, th) Case Area(1) Canvas.SetLeft(_PopupChild, tw - pw) : Canvas.SetTop(_PopupChild, th) Case Area(2) Canvas.SetLeft(_PopupChild, 0) : Canvas.SetTop(_PopupChild, -ph) Case Area(3) Canvas.SetLeft(_PopupChild, tw - pw) : Canvas.SetTop(_PopupChild, -ph) Case Area(4) Canvas.SetLeft(_PopupChild, tw) : Canvas.SetTop(_PopupChild, 0) Case Area(5) Canvas.SetLeft(_PopupChild, tw) : Canvas.SetTop(_PopupChild, th - ph) Case Area(6) Canvas.SetLeft(_PopupChild, -pw) : Canvas.SetTop(_PopupChild, 0) Case Area(7) Canvas.SetLeft(_PopupChild, -pw) : Canvas.SetTop(_PopupChild, th - ph) Case Else Canvas.SetLeft(_PopupChild, 0) : Canvas.SetTop(_PopupChild, th) End Select End If Case PlacementMode.Bottom If x <= Round((aw - tw) / 2, 0) Then Canvas.SetLeft(_PopupChild, 0) : Canvas.SetTop(_PopupChild, th) Else Canvas.SetLeft(_PopupChild, tw - pw) : Canvas.SetTop(_PopupChild, th) End If Case PlacementMode.Top If x <= Round((aw - tw) / 2, 0) Then Canvas.SetLeft(_PopupChild, 0) : Canvas.SetTop(_PopupChild, -ph) Else Canvas.SetLeft(_PopupChild, tw - pw) : Canvas.SetTop(_PopupChild, -ph) End If Case PlacementMode.Right If y <= Round((ah - th) / 2, 0) Then Canvas.SetLeft(_PopupChild, tw) : Canvas.SetTop(_PopupChild, 0) Else Canvas.SetLeft(_PopupChild, tw) : Canvas.SetTop(_PopupChild, th - ph) End If Case PlacementMode.Left If y <= Round((ah - th) / 2, 0) Then Canvas.SetLeft(_PopupChild, -pw) : Canvas.SetTop(_PopupChild, 0) Else Canvas.SetLeft(_PopupChild, -pw) : Canvas.SetTop(_PopupChild, th - ph) End If End Select End If End If End If End Sub Protected Overrides Sub OnGotFocus(e As System.Windows.RoutedEventArgs) MyBase.OnGotFocus(e) If Not _IsFocused Then _IsFocused = True : Me.ChangeVisualState(True) End Sub Protected Overrides Sub OnLostFocus(e As System.Windows.RoutedEventArgs) MyBase.OnLostFocus(e) If _IsFocused Then _IsFocused = False : Me.ChangeVisualState(True) End Sub Protected Overrides Sub OnMouseWheel(e As MouseWheelEventArgs) If Not e.Handled AndAlso Me.IsEnabled Then If Not Me.IsPopupOpen Then ToggleButtonMouseWheel(e) Else PopupMouseWheel(e) e.Handled = True End If MyBase.OnMouseWheel(e) End Sub Protected Overridable Sub ToggleButtonMouseWheel(ByVal e As MouseWheelEventArgs) End Sub Protected Overridable Sub PopupMouseWheel(ByVal e As MouseWheelEventArgs) End Sub Protected Overrides Sub OnKeyDown(ByVal e As KeyEventArgs) MyBase.OnKeyDown(e) If Not e.Handled AndAlso Me.IsEnabled Then If Not Me.IsPopupOpen Then ToggleButtonKeyDown(e) Else PopupKeyDown(e) End If End Sub Protected Overridable Sub ToggleButtonKeyDown(ByVal e As KeyEventArgs) Select Case e.Key Case Key.Enter, Key.Space If Not Me.IsPopupOpen Then Me.IsPopupOpen = True Case Key.F4 Me.IsPopupOpen = Not Me.IsPopupOpen End Select End Sub Protected Overridable Sub PopupKeyDown(ByVal e As KeyEventArgs) Select Case e.Key Case Key.Tab e.Handled = True Case Key.Escape If Me.IsPopupOpen Then Me.IsPopupOpen = False Case Key.F4 Me.IsPopupOpen = Not Me.IsPopupOpen End Select End Sub Private Sub ToggleButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) If Not _IsFocused Then Me.Focus() Me.IsPopupOpen = _ToggleButton.IsChecked End Sub Private Sub PopupCanvas_MouseLeftButtonDown(ByVal sender As Object, ByVal e As MouseButtonEventArgs) If Me.IsPopupOpen Then Me.IsPopupOpen = False End Sub Private Sub PopupCanvas_MouseRightButtonDown(ByVal sender As Object, ByVal e As MouseButtonEventArgs) e.Handled = True End Sub Private Sub PopupCanvas_MouseWheel(ByVal sender As Object, ByVal e As MouseWheelEventArgs) OnMouseWheel(e) End Sub Private Sub PopupChild_SizeChanged(ByVal sender As Object, ByVal e As SizeChangedEventArgs) ArrangePopup() End Sub Private Sub PopupChild_MouseRightButtonDown(ByVal sender As Object, ByVal e As MouseButtonEventArgs) e.Handled = True End Sub Private Function MaxDouble(ByVal Target As Double()) As Double Dim Result As Double = 0 For i As Integer = 0 To Target.Length - 1 Result = Max(Result, Target(i)) Next Return Result End Function End Class <ContentProperty("Child")> _ Public Class PopupButton Inherits PopupBase Public Shared ReadOnly ChildProperty As DependencyProperty = DependencyProperty.Register("Child", GetType(Object), GetType(PopupButton), New PropertyMetadata(Nothing)) Public Shared ReadOnly ChildTemplateProperty As DependencyProperty = DependencyProperty.Register("ChildTemplate", GetType(DataTemplate), GetType(PopupButton), New PropertyMetadata(Nothing)) Public Shared ReadOnly ContentProperty As DependencyProperty = DependencyProperty.Register("Content", GetType(Object), GetType(PopupButton), New PropertyMetadata(Nothing)) Public Shared ReadOnly ContentTemplateProperty As DependencyProperty = DependencyProperty.Register("ContentTemplate", GetType(DataTemplate), GetType(PopupButton), New PropertyMetadata(Nothing)) Public Property Child As Object Get Return CType(GetValue(ChildProperty), Object) End Get Set(ByVal value As Object) SetValue(ChildProperty, value) End Set End Property Public Property ChildTemplate As DataTemplate Get Return CType(GetValue(ChildTemplateProperty), DataTemplate) End Get Set(ByVal value As DataTemplate) SetValue(ChildTemplateProperty, value) End Set End Property Public Property Content As Object Get Return CType(GetValue(ContentProperty), Object) End Get Set(ByVal value As Object) SetValue(ContentProperty, value) End Set End Property Public Property ContentTemplate As DataTemplate Get Return CType(GetValue(ContentTemplateProperty), DataTemplate) End Get Set(ByVal value As DataTemplate) SetValue(ContentTemplateProperty, value) End Set End Property End Class <ContentProperty("Items")> _ Public Class ComboButton Inherits PopupBase Private _Panel As Panel WithEvents _Items As ComboButtonItemCollection Private _IsSynacWidth As Boolean Private _IsSynacHeight As Boolean Public Shared ReadOnly ChildProperty As DependencyProperty = DependencyProperty.Register("Child", GetType(Object), GetType(ComboButton), New PropertyMetadata(Nothing)) Public Shared ReadOnly ContentProperty As DependencyProperty = DependencyProperty.Register("Content", GetType(Object), GetType(ComboButton), New PropertyMetadata(Nothing)) Public Shared ReadOnly ItemsProperty As DependencyProperty = DependencyProperty.Register("Items", GetType(ComboButtonItemCollection), GetType(ComboButton), New PropertyMetadata(New ComboButtonItemCollection, New PropertyChangedCallback(AddressOf OnItemsPropertyChanged))) Public Shared ReadOnly ItemsSourceProperty As DependencyProperty = DependencyProperty.Register("ItemsSource", GetType(IEnumerable), GetType(ComboButton), New PropertyMetadata(Nothing, New PropertyChangedCallback(AddressOf OnItemsSourcePropertyChanged))) Public Shared ReadOnly ItemsPanelProperty As DependencyProperty = DependencyProperty.Register("ItemsPanel", GetType(Panel), GetType(ComboButton), New PropertyMetadata(Nothing, New PropertyChangedCallback(AddressOf OnItemsPanelPropertyChanged))) Public Shared ReadOnly ItemsTemplateProperty As DependencyProperty = DependencyProperty.Register("ItemsTemplate", GetType(DataTemplate), GetType(ComboButton), New PropertyMetadata(Nothing, New PropertyChangedCallback(AddressOf OnItemsTemplatePropertyChanged))) Public Shared ReadOnly SelectedIndexProperty As DependencyProperty = DependencyProperty.Register("SelectedIndex", GetType(Integer), GetType(ComboButton), New PropertyMetadata(-1, New PropertyChangedCallback(AddressOf OnSelectedIndexPropertyChanged))) Public Shared ReadOnly FocusedIndexProperty As DependencyProperty = DependencyProperty.Register("FocusedIndex", GetType(Integer), GetType(ComboButton), New PropertyMetadata(-1, New PropertyChangedCallback(AddressOf OnFocusedIndexPropertyChanged))) Public Shared ReadOnly ItemsWidthProperty As DependencyProperty = DependencyProperty.Register("ItemsWidth", GetType(Double), GetType(ComboButton), New PropertyMetadata(Double.NaN, New PropertyChangedCallback(AddressOf OnChildWidthPropertyChanged))) Public Shared ReadOnly ItemsHeightProperty As DependencyProperty = DependencyProperty.Register("ItemsHeight", GetType(Double), GetType(ComboButton), New PropertyMetadata(Double.NaN, New PropertyChangedCallback(AddressOf OnChildHeightPropertyChanged))) Public Shared ReadOnly AutoItemsWidthProperty As DependencyProperty = DependencyProperty.Register("AutoItemsWidth", GetType(Boolean), GetType(ComboButton), New PropertyMetadata(True, New PropertyChangedCallback(AddressOf OnAutoItemsWidthPropertyChanged))) Public Shared ReadOnly AutoItemsHeightProperty As DependencyProperty = DependencyProperty.Register("AutoItemsHeight", GetType(Boolean), GetType(ComboButton), New PropertyMetadata(False, New PropertyChangedCallback(AddressOf OnAutoItemsHeightPropertyChanged))) Public ReadOnly Property Child As Object Get Return CType(GetValue(ChildProperty), Object) End Get End Property Public ReadOnly Property Content As Object Get Return CType(GetValue(ContentProperty), Object) End Get End Property Public ReadOnly Property Items As ComboButtonItemCollection Get Return _Items End Get End Property Public Property ItemsSource As IEnumerable Get Return CType(GetValue(ItemsSourceProperty), IEnumerable) End Get Set(ByVal value As IEnumerable) SetValue(ItemsSourceProperty, value) End Set End Property Public Property ItemsPanel As Panel Get Return CType(GetValue(ItemsPanelProperty), Panel) End Get Set(ByVal value As Panel) SetValue(ItemsPanelProperty, value) End Set End Property Public Property ItemsTemplate As DataTemplate Get Return CType(GetValue(ItemsTemplateProperty), DataTemplate) End Get Set(ByVal value As DataTemplate) SetValue(ItemsTemplateProperty, value) End Set End Property Public Property SelectedIndex As Integer Get Return CType(GetValue(SelectedIndexProperty), Integer) End Get Set(ByVal value As Integer) SetValue(SelectedIndexProperty, value) End Set End Property Public Property FocusedIndex As Integer Get Return CType(GetValue(FocusedIndexProperty), Integer) End Get Set(ByVal value As Integer) SetValue(FocusedIndexProperty, value) End Set End Property Public Property ItemsWidth As Double Get Return CType(GetValue(ItemsWidthProperty), Double) End Get Set(ByVal value As Double) SetValue(ItemsWidthProperty, value) End Set End Property Public Property ItemsHeight As Double Get Return CType(GetValue(ItemsHeightProperty), Double) End Get Set(ByVal value As Double) SetValue(ItemsHeightProperty, value) End Set End Property Public Property AutoItemsWidth As Boolean Get Return CType(GetValue(AutoItemsWidthProperty), Boolean) End Get Set(ByVal value As Boolean) SetValue(AutoItemsWidthProperty, value) End Set End Property Public Property AutoItemsHeight As Boolean Get Return CType(GetValue(AutoItemsHeightProperty), Boolean) End Get Set(ByVal value As Boolean) SetValue(AutoItemsHeightProperty, value) End Set End Property Public ReadOnly Property HasItems As Boolean Get Return Me.Items IsNot Nothing AndAlso Me.Items.Count > 0 End Get End Property Private Shared Sub OnItemsPropertyChanged(d As System.Windows.DependencyObject, e As System.Windows.DependencyPropertyChangedEventArgs) CType(d, ComboButton).OnItemsChanged() End Sub Private Shared Sub OnItemsSourcePropertyChanged(d As System.Windows.DependencyObject, e As System.Windows.DependencyPropertyChangedEventArgs) CType(d, ComboButton).OnItemsSourceChanged() End Sub Private Shared Sub OnItemsPanelPropertyChanged(d As System.Windows.DependencyObject, e As System.Windows.DependencyPropertyChangedEventArgs) CType(d, ComboButton).OnItemsPanelChanged() End Sub Private Shared Sub OnItemsTemplatePropertyChanged(d As System.Windows.DependencyObject, e As System.Windows.DependencyPropertyChangedEventArgs) CType(d, ComboButton).OnItemsTemplateChanged() End Sub Private Shared Sub OnSelectedIndexPropertyChanged(d As System.Windows.DependencyObject, e As System.Windows.DependencyPropertyChangedEventArgs) CType(d, ComboButton).OnSelectedIndexChanged() End Sub Private Shared Sub OnFocusedIndexPropertyChanged(d As System.Windows.DependencyObject, e As System.Windows.DependencyPropertyChangedEventArgs) CType(d, ComboButton).OnFocusedIndexChanged() End Sub Private Shared Sub OnChildWidthPropertyChanged(d As System.Windows.DependencyObject, e As System.Windows.DependencyPropertyChangedEventArgs) CType(d, ComboButton).OnItemsWidthChanged() End Sub Private Shared Sub OnChildHeightPropertyChanged(d As System.Windows.DependencyObject, e As System.Windows.DependencyPropertyChangedEventArgs) CType(d, ComboButton).OnItemsHeightChanged() End Sub Private Shared Sub OnAutoItemsWidthPropertyChanged(d As System.Windows.DependencyObject, e As System.Windows.DependencyPropertyChangedEventArgs) CType(d, ComboButton).OnAutoItemsWidthChanged() End Sub Private Shared Sub OnAutoItemsHeightPropertyChanged(d As System.Windows.DependencyObject, e As System.Windows.DependencyPropertyChangedEventArgs) CType(d, ComboButton).OnAutoItemsHeightChanged() End Sub Protected Overrides Sub OnIsPopupOpenChanged() If Me.IsPopupOpen AndAlso Me.HasItems Then If Me.FocusedIndex <> Me.SelectedIndex Then Me.FocusedIndex = Me.SelectedIndex SetContent(Nothing) Else If Me.FocusedIndex <> -1 Then Me.FocusedIndex = -1 If Me.HasItems AndAlso Me.Items.Contains(Me.SelectedIndex) Then If Me.Content Is Nothing Then SetContent(Me.Items.Item(Me.SelectedIndex)) End If End If MyBase.OnIsPopupOpenChanged() End Sub Protected Overridable Sub OnItemsChanged() End Sub Protected Overridable Sub OnItemsSourceChanged() If Me.ItemsSource IsNot Nothing Then Me.Items.Clear() Me.Items.AddRange(Me.ItemsSource) End If End Sub Protected Overridable Sub OnItemsPanelChanged() If Me.HasItems Then For Each t As ComboButtonItem In Me.Items _Panel.Children.Remove(t) Next _Panel = Me.ItemsPanel For Each t As ComboButtonItem In Me.Items _Panel.Children.Add(t) Next SetValue(ChildProperty, _Panel) OnSelectedIndexChanged() End If End Sub Protected Overridable Sub OnItemsTemplateChanged() If Me.HasItems Then For Each t As ComboButtonItem In Me.Items t.ContentTemplate = Me.ItemsTemplate Next End If End Sub Protected Overridable Sub OnSelectedIndexChanged() If Not Me.Items.Contains(Me.SelectedIndex) Then If Me.HasItems Then If Me.SelectedIndex <> 0 Then Me.SelectedIndex = 0 Else If Me.SelectedIndex <> -1 Then Me.SelectedIndex = -1 End If End If If Me.SelectedIndex = -1 Then If Me.FocusedIndex <> -1 Then Me.FocusedIndex = -1 SetContent(Nothing) Else If Me.HasItems Then If Not Me.Items.Item(Me.SelectedIndex).IsChecked Then Me.Items.Item(Me.SelectedIndex).IsChecked = True Else Me.SelectedIndex = -1 End If End If End Sub Protected Overridable Sub OnFocusedIndexChanged() If Me.IsPopupOpen AndAlso Me.HasItems Then If Me.Items.Contains(Me.FocusedIndex) Then If Not Me.Items.Item(Me.FocusedIndex).IsFocused Then Me.Items.Item(Me.FocusedIndex).Focus() Else If Not Me.Items.Item(0).IsFocused Then Me.Items.Item(0).Focus() End If Else If Me.FocusedIndex <> -1 Then Me.FocusedIndex = -1 Me.Focus() End If End Sub Protected Overridable Sub OnItemsWidthChanged() If _Panel IsNot Nothing Then _Panel.Width = Me.ItemsWidth End Sub Protected Overridable Sub OnItemsHeightChanged() If _Panel IsNot Nothing Then _Panel.Height = Me.ItemsHeight End Sub Protected Overridable Sub OnAutoItemsWidthChanged() If Me.AutoItemsWidth Then If Double.IsNaN(Me.ItemsWidth) Then If Not Double.IsNaN(Me.Width) Then Me.ItemsWidth = Me.Width : _IsSynacWidth = True Else If _IsSynacWidth Then Me.ItemsWidth = Double.NaN : _IsSynacWidth = False End If End Sub Protected Overridable Sub OnAutoItemsHeightChanged() If Me.AutoItemsHeight Then If Double.IsNaN(Me.ItemsHeight) Then If Not Double.IsNaN(Me.Height) Then Me.ItemsHeight = Me.Height : _IsSynacHeight = True Else If _IsSynacHeight Then Me.ItemsHeight = Double.NaN : _IsSynacHeight = False End If End Sub Public Sub New() _Panel = Me.ItemsPanel If _Panel Is Nothing Then _Panel = New StackPanel _Panel.Width = Me.ItemsWidth : _Panel.Height = Me.ItemsHeight SetValue(ChildProperty, _Panel) _Items = New ComboButtonItemCollection End Sub Protected Overrides Function ArrangeOverride(FinalSize As System.Windows.Size) As System.Windows.Size OnAutoItemsWidthChanged() OnAutoItemsHeightChanged() Return MyBase.ArrangeOverride(FinalSize) End Function Protected Overrides Sub ToggleButtonMouseWheel(e As MouseWheelEventArgs) MyBase.ToggleButtonMouseWheel(e) If e.Delta < 0 Then Me.SelectNext() Else Me.SelectPrev() End Sub Protected Overrides Sub PopupMouseWheel(e As MouseWheelEventArgs) MyBase.PopupMouseWheel(e) If e.Delta < 0 Then Me.FocusNext() Else Me.FocusPrev() End Sub Private Sub SelectNext() If Me.HasItems Then If Me.SelectedIndex = Me.Items.Count - 1 Then Me.SelectedIndex = 0 Else Me.SelectedIndex += 1 End If End Sub Private Sub SelectPrev() If Me.HasItems Then If Me.SelectedIndex = 0 OrElse Me.SelectedIndex = -1 Then Me.SelectedIndex = Me.Items.Count - 1 Else Me.SelectedIndex -= 1 End If End Sub Protected Overrides Sub ToggleButtonKeyDown(ByVal e As KeyEventArgs) MyBase.ToggleButtonKeyDown(e) If Not e.Handled AndAlso Me.HasItems Then Select Case e.Key Case Key.Up, Key.Left SelectPrev() Case Key.Down, Key.Right SelectNext() Case Key.PageUp, Key.Home Me.SelectedIndex = 0 Case Key.PageDown, Key.End Me.SelectedIndex = Me.Items.Count - 1 End Select End If End Sub Protected Overrides Sub PopupKeyDown(ByVal e As KeyEventArgs) MyBase.PopupKeyDown(e) If Not e.Handled AndAlso Me.HasItems Then Select Case e.Key Case Key.Up, Key.Left FocusPrev() Case Key.Down, Key.Right FocusNext() Case Key.PageUp, Key.Home Me.FocusedIndex = 0 Case Key.PageDown, Key.End Me.FocusedIndex = Me.Items.Count - 1 Case Key.Enter, Key.Space If Me.SelectedIndex <> Me.FocusedIndex Then Me.SelectedIndex = Me.FocusedIndex If Me.IsPopupOpen Then Me.IsPopupOpen = False End Select End If End Sub Private Sub FocusNext() If Me.HasItems Then If Me.FocusedIndex = Me.Items.Count - 1 Then Me.FocusedIndex = 0 Else Me.FocusedIndex += 1 End If End Sub Private Sub FocusPrev() If Me.HasItems Then If Me.FocusedIndex = 0 OrElse Me.FocusedIndex = -1 Then Me.FocusedIndex = Me.Items.Count - 1 Else Me.FocusedIndex -= 1 End If End Sub Private Sub ComboButtonItem_KeyDown(ByVal sender As Object, ByVal e As KeyEventArgs) Select Case e.Key Case Key.Tab FocusNext() End Select PopupKeyDown(e) End Sub Private Sub ComboButtonItem_MouseWheel(ByVal sender As Object, ByVal e As MouseWheelEventArgs) OnMouseWheel(e) End Sub Private Sub ComboButtonItem_Checked(ByVal sender As Object, ByVal e As RoutedEventArgs) For i As Integer = 0 To Me.Items.Count - 1 If Me.Items.Item(i).IsChecked Then If Me.SelectedIndex <> i Then Me.SelectedIndex = i If Me.Content IsNot Me.Items.Item(i).Content Then SetContent(Me.Items.Item(i)) Exit For End If Next End Sub Private Sub ComboButtonItem_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) If Me.IsPopupOpen Then Me.IsPopupOpen = False End Sub Protected Overridable Sub OnItemsCollectionChanged(sender As Object, e As NotifyCollectionChangedEventArgs) Handles _Items.CollectionChanged Select Case e.Action Case NotifyCollectionChangedAction.Add AddItems(e.NewItems) Case NotifyCollectionChangedAction.Remove RemoveItems(e.OldItems) Case NotifyCollectionChangedAction.Replace RemoveItems(e.OldItems) AddItems(e.NewItems) Case (NotifyCollectionChangedAction.Reset) ClearItems() AddItems(_Items) End Select If Not Me.Items.Contains(Me.SelectedIndex) Then Me.SelectedIndex = 0 End Sub Private Sub SetContent(ByVal Target As ComboButtonItem) If Me.HasItems Then For Each t As ComboButtonItem In Me.Items If t.Content Is Nothing Then Dim r As Object = Me.Content SetValue(ContentProperty, Nothing) t.Content = r Exit For End If Next If Target Is Nothing Then SetValue(ContentProperty, Nothing) Else Dim r As Object = Target.Content Target.Content = Nothing SetValue(ContentProperty, r) End If Else SetValue(ContentProperty, Nothing) End If End Sub Private Sub AddItem(ByVal Item As ComboButtonItem) AddHandler Item.KeyDown, New KeyEventHandler(AddressOf ComboButtonItem_KeyDown) AddHandler Item.MouseWheel, New MouseWheelEventHandler(AddressOf ComboButtonItem_MouseWheel) AddHandler Item.Checked, New RoutedEventHandler(AddressOf ComboButtonItem_Checked) AddHandler Item.Click, New RoutedEventHandler(AddressOf ComboButtonItem_Click) _Panel.Children.Add(Item) OnSelectedIndexChanged() End Sub Private Sub AddItems(ByVal Items As IList) For Each t As Object In Items If t.GetType IsNot GetType(ComboButtonItem) Then t = New ComboButtonItem With {.Content = t} AddItem(t) Next End Sub Private Sub RemoveItem(ByVal Item As ComboButtonItem) _Panel.Children.Remove(Item) RemoveHandler Item.KeyDown, New KeyEventHandler(AddressOf ComboButtonItem_KeyDown) RemoveHandler Item.MouseWheel, New MouseWheelEventHandler(AddressOf ComboButtonItem_MouseWheel) RemoveHandler Item.Checked, New RoutedEventHandler(AddressOf ComboButtonItem_Checked) RemoveHandler Item.Click, New RoutedEventHandler(AddressOf ComboButtonItem_Click) If Me.HasItems Then If Not Me.Items.Contains(Me.SelectedIndex) Then Me.SelectedIndex = Me.Items.Count - 1 Else Me.SelectedIndex = -1 End If End Sub Private Sub RemoveItems(ByVal Items As IList) For Each t As Object In Items If t.GetType IsNot GetType(ComboButtonItem) Then t = New ComboButtonItem With {.Content = t} RemoveItem(t) Next End Sub Private Sub ClearItems() For Each t As ComboButtonItem In _Panel.Children _Panel.Children.Remove(t) RemoveHandler t.KeyDown, New KeyEventHandler(AddressOf ComboButtonItem_KeyDown) RemoveHandler t.MouseWheel, New MouseWheelEventHandler(AddressOf ComboButtonItem_MouseWheel) RemoveHandler t.Checked, New RoutedEventHandler(AddressOf ComboButtonItem_Checked) RemoveHandler t.Click, New RoutedEventHandler(AddressOf ComboButtonItem_Click) Next End Sub End Class Public Class ComboButtonItem Inherits RadioButton Private Sub ComboButtonItem_Loaded(sender As Object, e As System.Windows.RoutedEventArgs) Handles Me.Loaded If MyBase.IsChecked Then MyBase.Focus() End Sub End Class Public Class ComboButtonItemCollection Inherits ObservableCollection(Of Object) Public Sub New() Me.Clear() End Sub Public Sub New(ByVal Collection As IEnumerable) For Each t As Object In Collection If t.GetType IsNot GetType(ComboButtonItem) Then t = New ComboButtonItem With {.Content = t} MyBase.Add(t) Next End Sub Protected Overrides Sub InsertItem(Index As Integer, Item As Object) If Item.GetType IsNot GetType(ComboButtonItem) Then Item = New ComboButtonItem With {.Content = Item} MyBase.InsertItem(Index, Item) End Sub Protected Overrides Sub SetItem(Index As Integer, Item As Object) If Item.GetType IsNot GetType(ComboButtonItem) Then Item = New ComboButtonItem With {.Content = Item} MyBase.SetItem(Index, Item) End Sub Public Sub AddRange(ByVal Collection As IEnumerable) For Each t As Object In Collection If t.GetType IsNot GetType(ComboButtonItem) Then t = New ComboButtonItem With {.Content = t} MyBase.Add(t) Next End Sub Public Overloads Function Contains(ByVal Index As Integer) As Boolean If Me Is Nothing AndAlso Me.Items.Count <> 0 Then Return False If Index >= 0 AndAlso Index <= Me.Items.Count - 1 Then Return True Else Return False End Function End Class End Namespace
<Application x:Class="SilverlightApplication1.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:u="clr-namespace:SilverlightApplication1.ampedZUserControl"> <Application.Resources> <SolidColorBrush x:Name="BackgroundBrush" Color="#6614A600"/> <SolidColorBrush x:Name="MaskgroundBrush" Color="#80555555"/> <SolidColorBrush x:Name="ForegroundBrush" Color="#FFFFFFFF"/> <SolidColorBrush x:Name="ReadOnlyBrush" Color="#54FCFCFC"/> <SolidColorBrush x:Name="FocusBrush" Color="#6B74B8FC"/> <SolidColorBrush x:Name="CheckBrush" Color="#66FF0099"/> <SolidColorBrush x:Name="SelectBrush" Color="#856E3BA1"/> <SolidColorBrush x:Name="PressBrush" Color="#A8CE0F0F"/> <SolidColorBrush x:Name="MouseOverBrush" Color="#8032CDCD"/> <SolidColorBrush x:Name="DisableBrush" Color="#80555555"/> <LinearGradientBrush x:Name="BorderBrush" StartPoint="0,1" EndPoint="1,0"> <GradientStop Color="#A8CE0F0F" Offset="0.000"/> <GradientStop Color="#80FF9C00" Offset="0.143"/> <GradientStop Color="#54FADC0E" Offset="0.256"/> <GradientStop Color="#6614A600" Offset="0.429"/> <GradientStop Color="#8032CDCD" Offset="0.571"/> <GradientStop Color="#A80046AD" Offset="0.714"/> <GradientStop Color="#856E3BA1" Offset="0.857"/> <GradientStop Color="#A8CE0F0F" Offset="1.000"/> </LinearGradientBrush> <Style TargetType="ToggleButton"> <Setter Property="Background" Value="Transparent"/> <Setter Property="BorderBrush" Value="{StaticResource BorderBrush}"/> <Setter Property="BorderThickness" Value="1"/> <Setter Property="Foreground" Value="{StaticResource ForegroundBrush}"/> <Setter Property="FontFamily" Value="FZDaHei-B02S, HYGothic-Extra, Lucida Sans"/> <Setter Property="FontSize" Value="14"/> <Setter Property="Padding" Value="0"/> <Setter Property="IsTabStop" Value="True"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="ToggleButton"> <Grid> <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> <Grid> <Rectangle Name="FocusVisualElement" Fill="{StaticResource FocusBrush}" Opacity="0"/> <Rectangle Name="CheckVisualElement" Fill="{StaticResource CheckBrush}" Opacity="0"/> <Rectangle Name="PressVisualElement" Fill="{StaticResource PressBrush}" Opacity="0"/> <Rectangle Name="MouseOverVisualElement" Fill="{StaticResource MouseOverBrush}" Opacity="0"/> <ContentPresenter Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Margin="{TemplateBinding Padding}" Cursor="{TemplateBinding Cursor}"/> </Grid> </Border> <Rectangle Name="DisableVisualElement" Fill="{StaticResource DisableBrush}" IsHitTestVisible="False" Visibility="Collapsed"/> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="CommonStates"> <VisualState x:Name="Normal"/> <VisualState x:Name="Pressed"> <Storyboard> <DoubleAnimation Storyboard.TargetName="PressVisualElement" Storyboard.TargetProperty="Opacity" To="1" Duration="00:00:00.05"/> </Storyboard> </VisualState> <VisualState x:Name="MouseOver"> <Storyboard> <DoubleAnimation Storyboard.TargetName="MouseOverVisualElement" Storyboard.TargetProperty="Opacity" To="1" Duration="00:00:00.05"/> </Storyboard> </VisualState> <VisualState x:Name="Disabled"> <Storyboard> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="DisableVisualElement" Storyboard.TargetProperty="Visibility"> <DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/> </ObjectAnimationUsingKeyFrames> </Storyboard> </VisualState> </VisualStateGroup> <VisualStateGroup x:Name="CheckStates"> <VisualState x:Name="Unchecked"/> <VisualState x:Name="Checked"> <Storyboard> <DoubleAnimation Storyboard.TargetName="CheckVisualElement" Storyboard.TargetProperty="Opacity" To="1" Duration="00:00:00.2"/> </Storyboard> </VisualState> <VisualState x:Name="Indeterminate"/> </VisualStateGroup> <VisualStateGroup x:Name="FocusStates"> <VisualState x:Name="Unfocused"/> <VisualState x:Name="Focused"> <Storyboard> <DoubleAnimation Storyboard.TargetName="FocusVisualElement" Storyboard.TargetProperty="Opacity" To="1" Duration="00:00:00.2"/> </Storyboard> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style TargetType="u:PopupButton"> <Setter Property="Background" Value="Transparent"/> <Setter Property="BorderBrush" Value="{StaticResource BorderBrush}"/> <Setter Property="BorderThickness" Value="0"/> <Setter Property="OverlayBrush" Value="{StaticResource MaskgroundBrush}"/> <Setter Property="OverlayOpacity" Value="1"/> <Setter Property="Foreground" Value="{StaticResource ForegroundBrush}"/> <Setter Property="FontFamily" Value="FZDaHei-B02S, HYGothic-Extra, Lucida Sans"/> <Setter Property="FontSize" Value="14"/> <Setter Property="HorizontalContentAlignment" Value="Center"/> <Setter Property="VerticalContentAlignment" Value="Center"/> <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/> <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="u:PopupButton"> <Grid> <Rectangle Name="FocusVisualElement" Fill="{StaticResource FocusBrush}" Opacity="0"/> <ToggleButton x:Name="ToggleButton" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"> <ContentPresenter Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Margin="{TemplateBinding Padding}" Cursor="{TemplateBinding Cursor}"/> </ToggleButton> <Popup x:Name="Popup"> <Border Background="{StaticResource BackgroundBrush}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" HorizontalAlignment="Left" VerticalAlignment="Top"> <ScrollViewer> <ContentPresenter Content="{TemplateBinding Child}" ContentTemplate="{TemplateBinding ChildTemplate}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Margin="{TemplateBinding Padding}" Cursor="{TemplateBinding Cursor}"/> </ScrollViewer> </Border> </Popup> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="CommonStates"> <VisualState x:Name="Normal"/> <VisualState x:Name="Disabled"/> </VisualStateGroup> <VisualStateGroup x:Name="FocusStates"> <VisualState x:Name="Unfocused"/> <VisualState x:Name="Focused"> <Storyboard> <DoubleAnimation Storyboard.TargetName="FocusVisualElement" Storyboard.TargetProperty="Opacity" To="1" Duration="00:00:00.2"/> </Storyboard> </VisualState> <VisualState x:Name="FocusedPopup"/> </VisualStateGroup> </VisualStateManager.VisualStateGroups> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style TargetType="u:ComboButton"> <Setter Property="Background" Value="Transparent"/> <Setter Property="BorderBrush" Value="{StaticResource BorderBrush}"/> <Setter Property="BorderThickness" Value="0"/> <Setter Property="OverlayBrush" Value="{StaticResource MaskgroundBrush}"/> <Setter Property="OverlayOpacity" Value="1"/> <Setter Property="Foreground" Value="{StaticResource ForegroundBrush}"/> <Setter Property="FontFamily" Value="FZDaHei-B02S, HYGothic-Extra, Lucida Sans"/> <Setter Property="FontSize" Value="14"/> <Setter Property="HorizontalContentAlignment" Value="Center"/> <Setter Property="VerticalContentAlignment" Value="Center"/> <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/> <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="u:ComboButton"> <Grid> <Rectangle Name="FocusVisualElement" Fill="{StaticResource FocusBrush}" Opacity="0"/> <ToggleButton x:Name="ToggleButton" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"> <ContentPresenter Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ItemsTemplate}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Margin="{TemplateBinding Padding}" Cursor="{TemplateBinding Cursor}"/> </ToggleButton> <Popup x:Name="Popup"> <Border Background="{StaticResource BackgroundBrush}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" HorizontalAlignment="Left" VerticalAlignment="Top"> <ScrollViewer> <ContentPresenter Content="{TemplateBinding Child}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Margin="{TemplateBinding Padding}" Cursor="{TemplateBinding Cursor}"/> </ScrollViewer> </Border> </Popup> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="CommonStates"> <VisualState x:Name="Normal"/> <VisualState x:Name="Disabled"/> </VisualStateGroup> <VisualStateGroup x:Name="FocusStates"> <VisualState x:Name="Unfocused"/> <VisualState x:Name="Focused"> <Storyboard> <DoubleAnimation Storyboard.TargetName="FocusVisualElement" Storyboard.TargetProperty="Opacity" To="1" Duration="00:00:00.2"/> </Storyboard> </VisualState> <VisualState x:Name="FocusedPopup"/> </VisualStateGroup> </VisualStateManager.VisualStateGroups> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style TargetType="u:ComboButtonItem"> <Setter Property="Background" Value="Transparent"/> <Setter Property="BorderBrush" Value="{StaticResource BorderBrush}"/> <Setter Property="BorderThickness" Value="0"/> <Setter Property="Foreground" Value="{StaticResource ForegroundBrush}"/> <Setter Property="FontFamily" Value="FZDaHei-B02S, HYGothic-Extra, Lucida Sans"/> <Setter Property="FontSize" Value="14"/> <Setter Property="HorizontalContentAlignment" Value="Center"/> <Setter Property="VerticalContentAlignment" Value="Center"/> <Setter Property="Padding" Value="0"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="u:ComboButtonItem"> <Grid> <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> <Grid> <Rectangle Name="FocusVisualElement" Fill="{StaticResource FocusBrush}" Opacity="0"/> <Rectangle Name="CheckVisualElement" Fill="{StaticResource CheckBrush}" Opacity="0"/> <Rectangle Name="PressVisualElement" Fill="{StaticResource PressBrush}" Opacity="0"/> <Rectangle Name="MouseOverVisualElement" Fill="{StaticResource MouseOverBrush}" Opacity="0"/> <ContentPresenter Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Margin="{TemplateBinding Padding}" Cursor="{TemplateBinding Cursor}"/> </Grid> </Border> <Rectangle Name="DisableVisualElement" Fill="{StaticResource DisableBrush}" IsHitTestVisible="False" Visibility="Collapsed"/> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="CommonStates"> <VisualState x:Name="Normal"/> <VisualState x:Name="Pressed"> <Storyboard> <DoubleAnimation Storyboard.TargetName="PressVisualElement" Storyboard.TargetProperty="Opacity" To="1" Duration="00:00:00.05"/> </Storyboard> </VisualState> <VisualState x:Name="MouseOver"> <Storyboard> <DoubleAnimation Storyboard.TargetName="MouseOverVisualElement" Storyboard.TargetProperty="Opacity" To="1" Duration="00:00:00.05"/> </Storyboard> </VisualState> <VisualState x:Name="Disabled"> <Storyboard> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="DisableVisualElement" Storyboard.TargetProperty="Visibility"> <DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/> </ObjectAnimationUsingKeyFrames> </Storyboard> </VisualState> </VisualStateGroup> <VisualStateGroup x:Name="CheckStates"> <VisualState x:Name="Unchecked"/> <VisualState x:Name="Checked"> <Storyboard> <DoubleAnimation Storyboard.TargetName="CheckVisualElement" Storyboard.TargetProperty="Opacity" To="1" Duration="00:00:00.2"/> </Storyboard> </VisualState> </VisualStateGroup> <VisualStateGroup x:Name="FocusStates"> <VisualState x:Name="Unfocused"/> <VisualState x:Name="Focused"> <Storyboard> <DoubleAnimation Storyboard.TargetName="FocusVisualElement" Storyboard.TargetProperty="Opacity" To="1" Duration="00:00:00.2"/> </Storyboard> </VisualState> </VisualStateGroup> <VisualStateGroup x:Name="ValidationStates"> <VisualState x:Name="Valid"/> <VisualState x:Name="InvalidUnfocused"/> <VisualState x:Name="InvalidFocused"/> </VisualStateGroup> </VisualStateManager.VisualStateGroups> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style TargetType="TextBlock"> <Setter Property="Foreground" Value="{StaticResource ForegroundBrush}"/> <Setter Property="FontFamily" Value="FZDaHei-B02S, HYGothic-Extra, Lucida Sans"/> <Setter Property="FontSize" Value="14"/> <Setter Property="IsHitTestVisible" Value="False"/> </Style> <Style TargetType="TextBox"> <Setter Property="Background" Value="Transparent"/> <Setter Property="BorderBrush" Value="{StaticResource BorderBrush}"/> <Setter Property="BorderThickness" Value="1"/> <Setter Property="SelectionBackground" Value="{StaticResource SelectBrush}"/> <Setter Property="Foreground" Value="{StaticResource ForegroundBrush}"/> <Setter Property="FontFamily" Value="FZDaHei-B02S, HYGothic-Extra, Lucida Sans"/> <Setter Property="FontSize" Value="14"/> <Setter Property="HorizontalContentAlignment" Value="Stretch"/> <Setter Property="VerticalContentAlignment" Value="Top"/> <Setter Property="Padding" Value="0"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="TextBox"> <Grid> <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> <Grid> <Rectangle Name="ReadOnlyVisualElement" Fill="{StaticResource ReadOnlyBrush}" Visibility="Collapsed"/> <Rectangle Name="FocusVisualElement" Fill="{StaticResource FocusBrush}" Opacity="0"/> <Rectangle Name="MouseOverVisualElement" Fill="{StaticResource MouseOverBrush}" Opacity="0"/> <ScrollViewer x:Name="ContentElement" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Margin="{TemplateBinding Padding}" IsTabStop="False"/> </Grid> </Border> <Rectangle Name="DisableVisualElement" Fill="{StaticResource DisableBrush}" IsHitTestVisible="False" Visibility="Collapsed"/> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="CommonStates"> <VisualState x:Name="Normal"/> <VisualState x:Name="ReadOnly"> <Storyboard> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ReadOnlyVisualElement" Storyboard.TargetProperty="Visibility"> <DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/> </ObjectAnimationUsingKeyFrames> </Storyboard> </VisualState> <VisualState x:Name="MouseOver"> <Storyboard> <DoubleAnimation Storyboard.TargetName="MouseOverVisualElement" Storyboard.TargetProperty="Opacity" To="1" Duration="00:00:00.05"/> </Storyboard> </VisualState> <VisualState x:Name="Disabled"> <Storyboard> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="DisableVisualElement" Storyboard.TargetProperty="Visibility"> <DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/> </ObjectAnimationUsingKeyFrames> </Storyboard> </VisualState> </VisualStateGroup> <VisualStateGroup x:Name="FocusStates"> <VisualState x:Name="Unfocused"/> <VisualState x:Name="Focused"> <Storyboard> <DoubleAnimation Storyboard.TargetName="FocusVisualElement" Storyboard.TargetProperty="Opacity" To="1" Duration="00:00:00.2"/> </Storyboard> </VisualState> </VisualStateGroup> <VisualStateGroup x:Name="ValidationStates"> <VisualState x:Name="Valid"/> <VisualState x:Name="InvalidUnfocused"/> <VisualState x:Name="InvalidFocused"/> </VisualStateGroup> </VisualStateManager.VisualStateGroups> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style TargetType="Button"> <Setter Property="Background" Value="Transparent"/> <Setter Property="BorderBrush" Value="{StaticResource BorderBrush}"/> <Setter Property="BorderThickness" Value="1"/> <Setter Property="Foreground" Value="{StaticResource ForegroundBrush}"/> <Setter Property="FontFamily" Value="FZDaHei-B02S, HYGothic-Extra, Lucida Sans"/> <Setter Property="FontSize" Value="14"/> <Setter Property="Padding" Value="0"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="Button"> <Grid> <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> <Grid> <Rectangle Name="FocusVisualElement" Fill="{StaticResource FocusBrush}" Opacity="0"/> <Rectangle Name="PressVisualElement" Fill="{StaticResource PressBrush}" Opacity="0"/> <Rectangle Name="MouseOverVisualElement" Fill="{StaticResource MouseOverBrush}" Opacity="0"/> <ContentPresenter Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Margin="{TemplateBinding Padding}" Cursor="{TemplateBinding Cursor}"/> </Grid> </Border> <Rectangle Name="DisableVisualElement" Fill="{StaticResource DisableBrush}" IsHitTestVisible="False" Visibility="Collapsed"/> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="CommonStates"> <VisualState x:Name="Normal"/> <VisualState x:Name="Pressed"> <Storyboard> <DoubleAnimation Storyboard.TargetName="PressVisualElement" Storyboard.TargetProperty="Opacity" To="1" Duration="00:00:00.05"/> </Storyboard> </VisualState> <VisualState x:Name="MouseOver"> <Storyboard> <DoubleAnimation Storyboard.TargetName="MouseOverVisualElement" Storyboard.TargetProperty="Opacity" To="1" Duration="00:00:00.05"/> </Storyboard> </VisualState> <VisualState x:Name="Disabled"> <Storyboard> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="DisableVisualElement" Storyboard.TargetProperty="Visibility"> <DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/> </ObjectAnimationUsingKeyFrames> </Storyboard> </VisualState> </VisualStateGroup> <VisualStateGroup x:Name="FocusStates"> <VisualState x:Name="Unfocused"/> <VisualState x:Name="Focused"> <Storyboard> <DoubleAnimation Storyboard.TargetName="FocusVisualElement" Storyboard.TargetProperty="Opacity" To="1" Duration="00:00:00.2"/> </Storyboard> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style TargetType="ScrollViewer"> <Setter Property="Background" Value="Transparent"/> <Setter Property="BorderBrush" Value="{StaticResource BorderBrush}"/> <Setter Property="BorderThickness" Value="0"/> <Setter Property="HorizontalContentAlignment" Value="Left"/> <Setter Property="VerticalContentAlignment" Value="Top"/> <Setter Property="HorizontalScrollBarVisibility" Value="Auto"/> <Setter Property="VerticalScrollBarVisibility" Value="Auto"/> <Setter Property="Padding" Value="0"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="ScrollViewer"> <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="*"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <ScrollContentPresenter x:Name="ScrollContentPresenter"/> <ScrollBar x:Name="HorizontalScrollBar" Orientation="Horizontal" Value="{TemplateBinding HorizontalOffset}" ViewportSize="{TemplateBinding ViewportWidth}" Maximum="{TemplateBinding ScrollableWidth}" Minimum="0" Height="17" IsTabStop="False" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" Grid.Column="0" Grid.Row="1"/> <ScrollBar x:Name="VerticalScrollBar" Orientation="Vertical" Value="{TemplateBinding VerticalOffset}" ViewportSize="{TemplateBinding ViewportHeight}" Maximum="{TemplateBinding ScrollableHeight}" Minimum="0" Width="17" IsTabStop="False" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" Grid.Column="1" Grid.Row="0"/> </Grid> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style TargetType="ScrollBar"> <Setter Property="Background" Value="{StaticResource BackgroundBrush}"/> <Setter Property="BorderBrush" Value="{StaticResource BorderBrush}"/> <Setter Property="BorderThickness" Value="0"/> <Setter Property="Foreground" Value="{StaticResource ForegroundBrush}"/> <Setter Property="FontFamily" Value="FZDaHei-B02S, HYGothic-Extra, Lucida Sans"/> <Setter Property="FontSize" Value="14"/> <Setter Property="MinWidth" Value="17"/> <Setter Property="MinHeight" Value="17"/> <Setter Property="Padding" Value="0"/> <Setter Property="IsTabStop" Value="False"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="ScrollBar"> <Grid> <Grid x:Name="HorizontalRoot"> <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Margin="{TemplateBinding Padding}"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <Rectangle Name="MouseOverVisualElementHorizontal" Fill="{StaticResource MouseOverBrush}" Opacity="0" Grid.ColumnSpan="5"/> <RepeatButton x:Name="HorizontalSmallDecrease" Interval="50" IsTabStop="False" Width="17" Grid.Column="0"> <Path Data="F1 M 0,3 L 4,6 L 4,0 Z" Fill="{TemplateBinding Foreground}" Stretch="Uniform" Height="7" Width="5"/> </RepeatButton> <RepeatButton x:Name="HorizontalLargeDecrease" BorderThickness="0" Interval="50" IsTabStop="False" Width="0" Grid.Column="1"/> <Thumb x:Name="HorizontalThumb" Width="17" Grid.Column="2"/> <RepeatButton x:Name="HorizontalLargeIncrease" BorderThickness="0" Interval="50" IsTabStop="False" Grid.Column="3"/> <RepeatButton x:Name="HorizontalSmallIncrease" Interval="50" IsTabStop="False" Width="17" Grid.Column="4"> <Path Data="F1 M 0,0 L 0,6 L 4,3 Z" Fill="{TemplateBinding Foreground}" Stretch="Uniform" Height="7" Width="5"/> </RepeatButton> </Grid> </Border> <Rectangle Name="DisableVisualElementHorizontal" Fill="{StaticResource DisableBrush}" IsHitTestVisible="False" Visibility="Collapsed"/> </Grid> <Grid x:Name="VerticalRoot" Visibility="Collapsed"> <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Margin="{TemplateBinding Padding}"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <Rectangle Name="MouseOverVisualElementVertical" Fill="{StaticResource MouseOverBrush}" Opacity="0" Grid.RowSpan="5"/> <RepeatButton x:Name="VerticalSmallDecrease" Interval="50" IsTabStop="False" Height="17" Grid.Row="0"> <Path Data="F1 M 3,0 L 6,4 L 0,4 Z" Fill="{TemplateBinding Foreground}" Stretch="Uniform" Height="5" Width="7"/> </RepeatButton> <RepeatButton x:Name="VerticalLargeDecrease" BorderThickness="0" Interval="50" IsTabStop="False" Height="0" Grid.Row="1"/> <Thumb x:Name="VerticalThumb" Height="17" Grid.Row="2"/> <RepeatButton x:Name="VerticalLargeIncrease" BorderThickness="0" Interval="50" IsTabStop="False" Grid.Row="3"/> <RepeatButton x:Name="VerticalSmallIncrease" Interval="50" IsTabStop="False" Height="17" Grid.Row="4"> <Path Data="F1 M 0,0 L 3,4 L 6,0 Z" Fill="{TemplateBinding Foreground}" Stretch="Uniform" Height="5" Width="7"/> </RepeatButton> </Grid> </Border> <Rectangle Name="DisableVisualElementVertical" Fill="{StaticResource DisableBrush}" IsHitTestVisible="False" Visibility="Collapsed"/> </Grid> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="CommonStates"> <VisualState x:Name="Normal"/> <VisualState x:Name="MouseOver"> <Storyboard> <DoubleAnimation Storyboard.TargetName="MouseOverVisualElementHorizontal" Storyboard.TargetProperty="Opacity" To="1" Duration="00:00:00.05"/> <DoubleAnimation Storyboard.TargetName="MouseOverVisualElementVertical" Storyboard.TargetProperty="Opacity" To="1" Duration="00:00:00.05"/> </Storyboard> </VisualState> <VisualState x:Name="Disabled"> <Storyboard> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="DisableVisualElementHorizontal" Storyboard.TargetProperty="Visibility"> <DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/> </ObjectAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="DisableVisualElementVertical" Storyboard.TargetProperty="Visibility"> <DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/> </ObjectAnimationUsingKeyFrames> </Storyboard> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> </Application.Resources> </Application>
<UserControl x:Class="SilverlightApplication1.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:u="clr-namespace:SilverlightApplication1.ampedZUserControl" xmlns:s="clr-namespace:System;assembly=mscorlib"> <Grid Background="DeepSkyBlue"> <TextBlock Text="PopupButton_ComboButton" Foreground="Gray" FontSize="48" HorizontalAlignment="Center" VerticalAlignment="Center"/> <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center" Height="48"> <u:PopupButton Content="PopupButton" BorderThickness="1" Width="96"> <StackPanel Width="640"> <TextBlock Text="Child"/> <TextBox Text=""/> <Rectangle Fill="Blue" Height="48"/> <Button Content="Button"/> </StackPanel> </u:PopupButton> <u:ComboButton SelectedIndex="0" BorderThickness="1" Width="96"> <TextBlock Text="ComboButton"/> <s:String>Item1</s:String> <TextBlock Text="Item2"/> <Rectangle Fill="Red" Height="24"/> <Border> <TextBlock Text="Item4"/> </Border> </u:ComboButton> </StackPanel> </Grid> </UserControl>
源代码下载:http://files.cnblogs.com/ampedZ/PopupButton_ComboButton.zip