今天學習WPF控制類模版,嘗試自寫模版控制自定義Button類視覺效果時遇到一坑,記錄如下。
情景:
嘗試通過將Button.Template屬性設置為自定義的Control Template,以控制該Button的視覺效果。
問題:
使用該Control Template后,模版中為按下按鍵及彈起按鍵所設的EventTrigger無效。
1 <ControlTemplate.Triggers> 2 <EventTrigger RoutedEvent="MouseLeftButtonDown"> 3 ... 4 </EventTrigger> 5 <EventTrigger RoutedEvent="MouseLeftButtonUp"> 6 ... 7 </EventTrigger> 8 ... 9 </ControlTemplate.Triggers>
Trouble Shooting:
1' 為該Button的MouseLeftButtonDown及MouseLeftButtonUp事件添加回調函數,發現該Button的這兩個事件並不開火。
2' 為使用WPF默認模版Button的MouseLeftButtonDown及MouseLeftButtonUp事件添加回調函數,發現事件仍不開火。
3' 在StackOverFlow發現,當基類ButtonBase的ClickModeProperty的值被設置為ClickMode.Press或ClickMode.Release(默認)時,這兩個事件的EventArgs會被該按鈕的Click事件處理機制捕獲並抑制,造成所述的RoutedEvent啞火。只有在將ClickModeProperty設置為ClickMode.Hover時,所述事件才會正常開火。經過調整后,上述代碼果然得以正常運行。
4' 那么有沒有辦法在保留ClickModeProperty默認值(此值下的Click事件的行為通常證實我們需要的)的情況下,在模版中個性化按下按鈕與取消按下時的視覺效果呢?注意到Button類的默認模版實現了這一功能,然而通過反射查看其Xaml文件並沒有得到更多有用的信息。默認模版將Heavy work丟給了相應的Chrome類。
5' 最后才注意到,ButtonBase提供了名為IsPressed的屬性,描述是,「獲取一個值,該值標識ButtonBase當前是否被激活」。修改代碼,將相應動畫添加至綁定到該屬性的Trigger下:
1 <Trigger Property="IsPressed" Value="True"> 2 <Trigger.EnterActions> 3 <BeginStoryboard> 4 <Storyboard> 5 <ColorAnimation Duration="0:0:0.1" 6 Storyboard.TargetName="border" 7 Storyboard.TargetProperty="Background.Color" 8 To="#1177cc" /> 9 </Storyboard> 10 </BeginStoryboard> 11 </Trigger.EnterActions> 12 <Trigger.ExitActions> 13 <BeginStoryboard> 14 <Storyboard> 15 <ColorAnimation Duration="0:0:0.15" 16 Storyboard.TargetName="border" 17 Storyboard.TargetProperty="Background.Color"/> 18 </Storyboard> 19 </BeginStoryboard> 20 </Trigger.ExitActions> 21 </Trigger>
測試發現動畫成功生效。
