路由事件
路由事件使用以下三种路由策略之一:
-
浮升(冒泡): 调用事件源上的事件处理程序。 路由事件随后会路由到后续的父级元素,直到到达元素树的根。 大多数路由事件都使用浮升路由策略。 浮升路由事件通常用于报告来自不同控件或其他 UI 元素的输入或状态变化。
-
直接: 只有源元素本身才有机会调用处理程序以进行响应。 这类似于窗体用于事件的Windows路由"。 但是,与标准 CLR 事件不同,直接路由事件支持类处理 (类处理在即将发布的) 节中进行了说明,并且 和 可以使用 EventSetter EventTrigger 。
-
隧道: 最初将调用元素树的根处的事件处理程序。 随后,路由事件将朝着路由事件的源节点元素(即引发路由事件的元素)方向,沿路由线路传播到后续的子元素。 合成控件的过程中通常会使用或处理隧道路由事件,通过这种方式,可以有意地禁止复合部件中的事件,或者将其替换为特定于整个控件的事件。 在 WPF 中提供的输入事件通常是以隧道/浮升对实现的。 隧道事件有时又称作预览事件,这是由该对所使用的命名约定决定的。
一般冒泡和隧道是成对出现的。隧道比较好认,会有Preview作为前缀。
例子:
TunnelLabelClick
BubbledLabelClick
键盘输入:
焦点: Focusable = true/false 空间元素默认为true,非控件默认false
控制焦点的顺序,TabIndex
<Window x:Class="Demo.WPFLearning.Keyboard" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:Demo.WPFLearning" mc:Ignorable="d" Title="Keyboard" Height="450" Width="400"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <DockPanel Margin="5"> <TextBlock Margin="3"> Type Here</TextBlock> <TextBox Name="Textboxx" PreviewKeyDown="Textboxx_KeyEvent" KeyDown="Textboxx_KeyEvent" PreviewTextInput="Textboxx_TextInput" PreviewKeyUp="Textboxx_KeyEvent" KeyUp="Textboxx_KeyEvent" TextChanged="Textboxx_TextChanged"></TextBox> </DockPanel> <ListBox Margin="5" Name="listMessage" Grid.Row="1"/> <Button Grid.Row="2" HorizontalAlignment="Right" Margin="5" Padding="3" Name="clear" Click="Clear_Click">Clear List</Button> </Grid> </Window>
public partial class Keyboard : Window
{
public Keyboard()
{
InitializeComponent();
}
public void Textboxx_KeyEvent(object sender,KeyEventArgs e)
{
string msg = "Event:" + e.RoutedEvent + " Key:" + e.Key;
this.listMessage.Items.Add(msg);
}
public void Textboxx_TextInput(object sender, TextCompositionEventArgs e)
{
string msg = "Event:" + e.RoutedEvent + " Key:" + e.Text;
this.listMessage.Items.Add(msg);
}
private void Textboxx_TextChanged(object sender, TextChangedEventArgs e)
{
string msg = "Event:" + e.RoutedEvent ;
this.listMessage.Items.Add(msg);
}
private void Clear_Click(object sender, RoutedEventArgs e)
{
this.listMessage.Items.Clear();
}
}
鼠标输入:
移动事件 MousePosition:
MouseEventArgs对象 :包含标识鼠标状态的一些信息
直接事件:MouseEnter 、MouseLeave
隧道路由事件: PreviewMouseMove、MouseMove
<Grid Margin="5"> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <Rectangle x:Name="rect" Fill="AliceBlue" MouseMove="Rect_MouseMove"/> <Button Grid.Row="1" Name="cmdCapture"> Capture the Mouse</Button> <TextBlock x:Name="Info" Grid.Row="2"/> </Grid>
private void Rect_MouseMove(object sender, MouseEventArgs e) { Point pt = e.GetPosition(this); this.Info.Text = ("Mouse is at ( "+pt.X +" , "+pt.Y+" ) in window" ); }
单击事件:
Mouse.Capture()进行捕获,第一个参数为鼠标,第二个参数为类型,可选
当一个鼠标事件被一个元素捕获后,其他元素就无法收到鼠标事件了,因此需要通知鼠标键释放事件(鼠标离开原来元素)
路由事件:
PreviewMouseLeftButtonDown、MouseRightButtonDown、LeftButtonDown、RightButtonDown
PreviewMouseLeftButtonUp、MouseRightButtonUp、LeftButtonUp、RightButtonUp
鼠标的拖放 MouseDragAndDrop
- 单击或者选择一些一些元素后,一些信息被搁置。
- 用户将鼠标移动到其他元素上,元素可以接受拖动的内容,鼠标指针变为拖放图标
- 释放鼠标键时 ,目标元素接收信息并对信息进行处理
一些控件,如TextBox自带拖放的逻辑,对Lable写一些代码。
DragDrop.DoDragDrop(源, 属性内容, DragDropEffects.Copy(方式));
接收内容的元素 ,属性 AllowDrop 要修改为 true
<Grid> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition/> </Grid.RowDefinitions> <TextBox Padding="10" VerticalAlignment="Center" HorizontalAlignment="Center" Text="Drag from this TextBox"/> <TextBox Padding="10" VerticalAlignment="Center" HorizontalAlignment="Center" Grid.Column="1"/> <Label x:Name="LabFrom" Padding="20" VerticalAlignment="Center" HorizontalAlignment="Center" Grid.Row="1" Background="#FFC4F1A3" MouseDown="LabFrom_MouseDown">or this Label</Label> <Label x:Name="LabTo" Padding="20" VerticalAlignment="Center" HorizontalAlignment="Center" Grid.Column="1" Grid.Row="1" Background="#FFC4F1A3" AllowDrop="True" Drop="LabTo_Drop">To this Label</Label> </Grid>
private void LabFrom_MouseDown(object sender, MouseButtonEventArgs e) { Label label = (Label)sender; DragDrop.DoDragDrop(label,Content,DragDropEffects.Copy); } private void LabTo_Drop(object sender, DragEventArgs e) { Label label = (Label)sender; label.Content = e.Data.GetData(DataFormats.Text); }