<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
本文主要介紹了WPF中常用的滑鼠事件、鍵盤事件以及注意事項,同時使用一個案例講解了拓展事件。除此之外,本文還講述如何用行為(Behavior)來封裝事件。
Windows中的事件通過訊息機制來完成,也就是Windows系統來捕獲使用者輸入(如滑鼠點選、鍵盤輸入),然後Windows傳送一個訊息給應用程式,應用程式進行具體的處理。在Winform中,表單中每個控制元件都是有獨立的控制程式碼,也就是每個控制元件都可以收到Windows系統傳來的訊息,但是在WPF中,表單中的控制元件是沒有控制程式碼的,所以只能是表單進行訊息捕獲,WPF框架經過處理再傳遞給相應的控制元件。這是WPF和Winform在事件處理上的不同之處。
常用的滑鼠事件包括:
MouseEnter、MouseLeave、MouseDown、MouseUp、MouseMove、MouseLeftButtonDown、MouseLeftButtonUp、MouseRightButtonDown、MouseRightButtonUp、MouseDoubleClick
值得注意的是諸如Button一類的控制元件,具有Click事件,它其實是仍然是呼叫了MouseLeftButtonDown等底層事件,然後進行截斷,也就是說Button控制元件只能呼叫Click事件而不能呼叫MouseLeftButtonDown事件,因為在Click事件中,呼叫了MouseLeftButtonDown事件,而且應用了e.Handled = true;
阻止事件向下傳下去。如果要在Click事件之前進行事件處理,則可以使用PreviewMouseLeftButtonDown
事件。
用的最多的鍵盤輸入事件有:
KeyDown、KeyUp、TextInput
如果要對某個鍵進行處理則可以
private void TextBox_KeyDown(object sender, KeyEventArgs e) { if(e.Key == Key.Enter) { //e.Handled = true;//表示已經處理完成 //具體邏輯 } }
注意TextBox是不能捕獲到TextInput
事件的,只能捕獲到KeyDown、TextChanged
等事件,但也可以捕獲到PreviewTextInput
事件,事件捕獲順序是KeyDown-PreviewTextInput-TextChanged
。
案例:做一個搜尋欄,輸入文字後回車搜尋
實現方式1:可以在TextBox上增加KeyDown事件,捕獲Key.Enter鍵。
實現方式2:增加一個Button按鈕,設定<Button Content="搜尋" IsDefault="True"/>
拖拽事件包括:Drop、DragLeave、DragOver、DragEnter事件
案例,將某個控制元件拖拽到另一個區域
介面XAML
<Grid> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition/> </Grid.ColumnDefinitions> <StackPanel x:Name="panel" Background="#F7F9FA"> <Border Background="Orange" Height="30" Width="30" MouseLeftButtonDown="Border_MouseLeftButtonDown"/> </StackPanel> <!--必須設定Background,否則預設為null,null是沒有背景和Transparent不同--> <!--AllowDrop="True"必須設定--> <Canvas x:Name="canvas" Grid.Column="1" Drop="Canvas_Drop" AllowDrop="True" Background="Transparent"> </Canvas> </Grid>
實現程式碼
private void Canvas_Drop(object sender, DragEventArgs e) { var data = e.Data.GetData(typeof(Border)); //canvas.Children.Add(data);//直接這樣不可以,因為同一個範例不允許在於兩個容器中 //先在之前的容器中移除,再新增 panel.Children.Remove(data as UIElement); canvas.Children.Add(data as UIElement); //獲得滑鼠相對於canvas的位置 var point = e.GetPosition((Canvas)sender); Canvas.SetLeft(data as UIElement, point.X); Canvas.SetTop(data as UIElement, point.Y); } private void Border_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { Border border = sender as Border; DragDrop.DoDragDrop(border, border, DragDropEffects.Copy); }
通過一個案例來講解
案例,實現某個控制元件的隨意拖動
主要是通過MouseLeftButtonDown、MouseLeftButtonUp和MouseMove
三個事件來實現
XAML介面
<Canvas> <Border Background="Orange" Width="100" Height="50" Canvas.Left="100" Canvas.Top="100" MouseLeftButtonDown="Border_MouseLeftButtonDown" MouseLeftButtonUp="Border_MouseLeftButtonUp" MouseMove="Border_MouseMove" /> </Canvas>
實現程式碼
private Canvas _parentCanvas = null; private bool _isDragging = false; private Point _mouseCurrentPoint; private void Border_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { //獲得承載Border的父物件 if (_parentCanvas == null) _parentCanvas = (Canvas)VisualTreeHelper.GetParent(sender as Border); this._isDragging = true; //獲得相對於border的座標 this._mouseCurrentPoint = e.GetPosition(sender as Border); //關鍵,鎖定滑鼠即不讓滑鼠選中其他元素 (sender as Border).CaptureMouse(); } private void Border_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { if (_isDragging) { //關鍵,取消鎖定滑鼠 (sender as Border).ReleaseMouseCapture(); _isDragging = false; } } private void Border_MouseMove(object sender, MouseEventArgs e) { if (_isDragging) { //獲得相對於Canvas的座標 Point point = e.GetPosition(_parentCanvas); (sender as Border).SetValue(Canvas.TopProperty, point.Y - _mouseCurrentPoint.Y); (sender as Border).SetValue(Canvas.LeftProperty, point.X - _mouseCurrentPoint.X); } }
關鍵點:
在進行移動的時候,一定要鎖定滑鼠,也就是不讓滑鼠可以選中其他元素,如果不鎖定會出現以下情況:
情況1:如果滑鼠移動過快,會出現圖形不能跟隨的情況
情況2:如果有多個元素,會出現選中其他元素的情況
下圖演示中,滑鼠箭頭未鬆開
鎖定滑鼠有兩種方式
(sender as Border).CaptureMouse()//鎖定 (sender as Border).ReleaseMouseCapture();//解鎖 System.Windows.Input.Mouse.Capture(sender as Border);//鎖定 System.Windows.Input.Mouse.Capture(null);//解鎖
上文中主要是通過MouseLeftButtonDown、MouseLeftButtonUp和MouseMove
三個事件來實現,在XAML中需要對這三個事件進行繫結。行為則可以將這三個事件封裝在一起。
Microsoft.Xaml.Behaviors.Wpf
,FrameWork版本安裝System.Windows.Interactivity.WPF
Behavior<T>
,類中重寫OnAttached()和OnDetaching()方法。OnAttached()表示當掛載到對應的物件上的時候觸發
OnDetaching()在物件銷燬時觸發
public class DragMoveBehavior : Behavior<Border> { // 當掛載到對應的物件上的時候觸發 protected override void OnAttached() { base.OnAttached(); //方法與上面相同 //this.AssociatedObject表示關聯的物件 this.AssociatedObject.MouseLeftButtonDown += AssociatedObject_MouseLeftButtonDown; this.AssociatedObject.MouseLeftButtonUp += AssociatedObject_MouseLeftButtonUp; this.AssociatedObject.MouseMove += AssociatedObject_MouseMove; } private Canvas _parentCanvas = null; private bool _isDragging = false; private Point _mouseCurrentPoint; private void AssociatedObject_MouseMove(object sender, System.Windows.Input.MouseEventArgs e) { if (_isDragging) { // 相對於Canvas的座標 Point point = e.GetPosition(_parentCanvas); // 設定最新座標 this.AssociatedObject.SetValue(Canvas.TopProperty, point.Y - _mouseCurrentPoint.Y); this.AssociatedObject.SetValue(Canvas.LeftProperty, point.X - _mouseCurrentPoint.X); } } private void AssociatedObject_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e) { if (_isDragging) { // 釋放滑鼠鎖定 //this.AssociatedObject.ReleaseMouseCapture(); System.Windows.Input.Mouse.Capture(null); _isDragging = false; } } private void AssociatedObject_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e) { this._isDragging = true; // Canvas if (_parentCanvas == null) _parentCanvas = (Canvas)VisualTreeHelper.GetParent(sender as Border); // 當前滑鼠座標 this._mouseCurrentPoint = e.GetPosition(sender as Border); // 滑鼠鎖定 //this.AssociatedObject.CaptureMouse(); System.Windows.Input.Mouse.Capture(this.AssociatedObject); } // 物件銷燬 protected override void OnDetaching() { this.AssociatedObject.MouseLeftButtonDown -= AssociatedObject_MouseLeftButtonDown; this.AssociatedObject.MouseLeftButtonUp -= AssociatedObject_MouseLeftButtonUp; this.AssociatedObject.MouseMove -= AssociatedObject_MouseMove; } }
XAML中程式碼
<Canvas> <Border Background="Orange" Width="100" Height="50" Canvas.Left="100" Canvas.Top="100"> <i:Interaction.Behaviors> <local:DragMoveBehavior/> </i:Interaction.Behaviors> </Border> </Canvas>
以上就是WPF中滑鼠/鍵盤/拖拽事件以及用行為封裝事件詳解的詳細內容,更多關於WPF事件的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45