一、事件路由

1. 直接路由事件

  起源于一个元素,并且不能传递给其他元素

MouserEnter 和MouserLeave 就是直接事件路由

2. 冒泡路由事件

  在包含层次中向上传递,首先由引发的元素触发,然后被父元素引发,直到到达WPF的元素树的顶部位置

例如:MouserUp

以下控件都绑定了,MouseUp事件。根据输出的顺序表现冒泡路由的效果

<Window x:Class="Haos.WPF.Case.Event.BubbleRouteWindow"
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:Haos.WPF.Case.Event"
mc:Ignorable="d"
Title="BubbleRouteWindow" Height="300" Width="300">
<!--冒泡路由-->
<Grid Margin="3" MouseUp="SomethingClick">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<Label Margin="5" Background="AliceBlue" BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Center" Grid.Row="0" MouseUp="SomethingClick">
<StackPanel MouseUp="SomethingClick">
<TextBlock Margin="3" TextAlignment="Center" MouseUp="SomethingClick">Image and Picture Lable</TextBlock>
<Image Source="/Images/logo_ye.png" Width="20" Stretch="Fill" MouseUp="SomethingClick"></Image>
<TextBlock Margin="3" TextAlignment="Center" MouseUp="SomethingClick">Courtesy of the StackPanel</TextBlock>
</StackPanel>
</Label>
<ListBox Margin="5" Name="lstMessage" Grid.Row="1"></ListBox>
<CheckBox Margin="5" Grid.Row="2" Name="Check_Box">Handle first event</CheckBox>
<Button Grid.Row="3" Margin="5" Padding="2" Click="Btn_Click">Clear List</Button>
</Grid>
</Window>
namespace Haos.WPF.Case.Event
{
/// <summary>
/// BubbleRouteWindow.xaml 的交互逻辑
/// </summary>
public partial class BubbleRouteWindow : Window
{
public BubbleRouteWindow()
{
InitializeComponent();
} public int EventCounter = ; /// <summary>
/// MouseUp 的处理程序
/// </summary>
/// <param name="sender">触发者</param>
/// <param name="e">事件参数</param>
private void SomethingClick(object sender, MouseButtonEventArgs e)
{
EventCounter++;
string message = $"#{EventCounter}:\r\nSender:{sender.ToString()}\r\nSource:{e.Source}\r\nOriginal Source:{e.OriginalSource}";
lstMessage.Items.Add(message);
e.Handled = (bool)Check_Box.IsChecked;
} private void Btn_Click(object sender, RoutedEventArgs e)
{
EventCounter = ;
lstMessage.Items.Clear();
}
}
}

3. 隧道路由事件

  在包含层次中向下传递,首先由WPF的元素树的顶部触发,然后向子元素引发,直到到达最后一个子元素

隧道路由的事件名称以Preview开头,例如PreviewKeyDown键盘按下事件

<Window x:Class="Haos.WPF.Case.Event.ChunnelRouteWindow"
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:Haos.WPF.Case.Event"
mc:Ignorable="d"
Title="ChunnelRouteWindow" Height="300" Width="300" PreviewKeyDown="SomethingKeyUp">
<!--隧道路由事件-->
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" PreviewKeyDown="SomethingKeyUp">
<TextBlock Margin="3" HorizontalAlignment="Center" PreviewKeyDown="SomethingKeyUp">Image and text Lable</TextBlock>
<Image Source="/Images/logo_ye.png" Width="20" Stretch="Fill" PreviewKeyDown="SomethingKeyUp"></Image>
<DockPanel PreviewKeyDown="SomethingKeyUp">
<TextBlock PreviewKeyDown="SomethingKeyUp">Type here:</TextBlock>
<TextBox PreviewKeyDown="SomethingKeyUp"></TextBox>
</DockPanel>
</StackPanel>
<ListBox Margin="5" Name="lstMessage" Grid.Row="1"></ListBox>
<CheckBox Margin="5" Grid.Row="2" Name="Check_Box">Handle first event</CheckBox>
<Button Grid.Row="3" Margin="5" Padding="2" Click="Btn_Click">Clear List</Button>
</Grid>
</Window>

二、事件类型

1. 生命周期事件

  1.1 Window.Initialized:在所有子元素都被设置完成时触发

    这个元素已经被构建出来,并且它的属性值都被设置好了,所以通常都是子元素先于父元素触发这个事件.当一个元素的 Initialized 事件被触发, 通常它的子树都已经初始化完成, 但是父元素还未初始化. 这个事件通常是在子树的 Xaml 被加载进来后触发的. 这个事件与 IsInitialized 属性相互绑定

  1.2 Window.Activated和Window.Deactivated:在窗口成为前台窗口时发生(激活)/在窗口成为后台窗口时发生

       户在运行系统上的多个窗口中切换时,Activated和Deactivated在窗口的生命周期里会发生多次

  1.3 Window.Loaded:在元素布局,呈现和准备交互时发生

    为了让一些事情能在所有内容都显示给用户之前马上执行,可以用Loaded事件

  1.4 Window.ContentRendered:在窗口的内容被渲染后发生

    ContentRendered事件只对窗口第一次完全呈现出来进行触发。为了让一些事情能在所有内容都显示给用户之后马上执行,可以用ContentRendered事件

  1.5 Window.Closed:当窗口即将关闭时发生  

  1.6 Window.Closing:Closed之后立即发生 Close 被调用,并且可以处理以取消关闭窗口。

2.鼠标事件

2.1 捕获鼠标坐标

捕获鼠标相对,元素的位置

2.2 捕获鼠标

当元素捕获鼠标以后,其他元素就无法触发其他元素上的,鼠标按钮类事件。直到 Mouse.Capture(null);方法接受到一个null参数。

2.3 鼠标拖放输入

用户单击或选择元素上一块区域,拖放动作开始,将鼠标移动到其他的元素上并且该元素可以接受拖放信息。

文本框自带拖放功能。

首先设置鼠标按下事件时,绑定拖放的源。在放目标元素开启,允许放属性AllowDrop。同时绑定Drop事件处理放的操作

<Window x:Class="Haos.WPF.Case.Event.MouseEventWindow"
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:Haos.WPF.Case.Event"
mc:Ignorable="d"
Title="MouseEventWindow" Height="300" Width="300">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<!--获取鼠标位置-->
<Rectangle Name="rect" Fill="AliceBlue" MouseMove="Rect_Move"></Rectangle>
<!--捕获鼠标-->
<Button Grid.Row="1" Name="Btn_Capture" Click="Capture_Click">Capture the Mouse</Button>
<TextBlock Grid.Row="2" Name="Txt_Block">Mouse posstion at (0,0) in window coordinates</TextBlock>
<DockPanel Grid.Row="3">
<!--设置拖动的源-->
<Label Background="DarkKhaki" Name="Txt_Scouce" MouseDown="Scouce_Down">this is label mouse</Label>
<!--被放的对象,开启允许拖放接受数据 AllowDrop="True"-->
<Label Background="Aqua" AllowDrop="True" Name="Lbl_Drop" Drop="Lbl_Drops"></Label>
</DockPanel>
</Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes; namespace Haos.WPF.Case.Event
{
/// <summary>
/// MouseEventWindow.xaml 的交互逻辑
/// </summary>
public partial class MouseEventWindow : Window
{
public MouseEventWindow()
{
InitializeComponent();
}
/// <summary>
/// 鼠标在矩形移动
/// </summary>
/// <param name="sender"></param>
/// <param name="e">MouseEventArgs 不具备鼠标按钮,鼠标滚轮的事件提供的参数</param>
private void Rect_Move(object sender, MouseEventArgs e)
{
//获取鼠标坐标
Point point = e.GetPosition(this);
Txt_Block.Text = $"Mouse posstion at ({point.X},{point.Y}) in window coordinates";
if (point.X == )
{
//让被捕获的鼠标释放
Mouse.Capture(null);
}
} private void Capture_Click(object sender, RoutedEventArgs e)
{
Mouse.Capture(rect);
Btn_Capture.Content = "鼠标被捕获…";
} /// <summary>
/// 鼠标按下设置,拖放的源
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Scouce_Down(object sender, MouseButtonEventArgs e)
{
Label lbl = sender as Label; ;
//启动拖动
DragDrop.DoDragDrop(lbl, lbl.Content, DragDropEffects.Copy);
}
/// <summary>
/// 拖放,放的事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Lbl_Drops(object sender, DragEventArgs e)
{
Label lbl = sender as Label;
lbl.Content = e.Data.GetData(DataFormats.Text);
}
}
}

3.键盘事件

  按照执行顺序排列如下

  3.1 PreviewKeyDown:隧道键盘按下

  3.2 KeyDown:冒泡键盘按下

  3.3 PreviewTextInput:文本正在输入事件

  3.4 TextChanged:本文框值发生改变

  3.5 PreviewKeyUp:隧道键盘弹起

  3.6 KeyUp:冒泡键盘弹起

<Window x:Class="Haos.WPF.Case.Event.KeyboardEventWindow"
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:Haos.WPF.Case.Event"
mc:Ignorable="d"
Title="KeyboardEventWindow" Height="300" Width="300">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<DockPanel Margin="5" Grid.Row="0">
<TextBlock Margin="3">Type here:</TextBlock>
<TextBox Focusable="True" PreviewKeyDown="KeyEvent" KeyDown="KeyEvent" PreviewKeyUp="KeyEvent" KeyUp="KeyEvent" PreviewTextInput="TextBox_PreviewTextInput" TextChanged="TextBox_TextChanged"></TextBox>
</DockPanel>
<ListBox Margin="5" Grid.Row="1" Name="lstMessage"></ListBox>
<Button Grid.Row="2" Name="Btn_Clear" Padding="3" Margin="3" Click="Btn_Clear_Click">Clear ListBox</Button>
</Grid>
</Window>
namespace Haos.WPF.Case.Event
{
/// <summary>
/// KeyboardEventWindow.xaml 的交互逻辑
/// </summary>
public partial class KeyboardEventWindow : Window
{
public KeyboardEventWindow()
{
InitializeComponent();
} private void TextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
string message = $"Event:{e.RoutedEvent} Key:{e.Text}";
lstMessage.Items.Add(message);
} private void KeyEvent(object sender, KeyEventArgs e)
{
string message = $"Event:{e.RoutedEvent} Key:{e.Key}";
lstMessage.Items.Add(message);
} private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
string message = $"Event:{e.RoutedEvent}";
lstMessage.Items.Add(message);
} private void Btn_Clear_Click(object sender, RoutedEventArgs e)
{
lstMessage.Items.Clear();
}
}
}

  3.7 焦点相关:

    Focusable设置控件是否能够获得焦点,和TabIndex属性设置按下Tab键获得焦点的顺序。在WPF中是使用树形结构布局的,所以当按下Tab键时,焦点会移动到当前元素的一个子元素。如果没有子元素,会移动到同级下一个元素的第一个子元素

4.手写笔事件

5.多点触控事件

WPF 入门笔记之事件的更多相关文章

  1. WPF 学习笔记 路由事件

    1. 可传递的消息: WPF的UI是由布局组建和控件构成的树形结构,当这棵树上的某个节点激发出某个事件时,程序员可以选择以传统的直接事件模式让响应者来响应之,也可以让这个事件在UI组件树沿着一定的方向 ...

  2. WPF 入门笔记之基础

    一.创建WPF程序 1. App.xaml 相当于窗体的配置文件 2. xmlns:xml名称空间的缩写 xmlns="http://schemas.microsoft.com/winfx/ ...

  3. WPF 入门笔记之控件内容控件

    一.控件类 在WPF中和用户交互的元素,或者说.能够接受焦点,并且接收键盘鼠标输入的元素所有的控件都继承于Control类. 1. 常用属性: 1.1 Foreground:前景画刷/前景色(文本颜色 ...

  4. WPF 入门笔记之布局

    一.布局原则: 1. 不应显示的设定元素的尺寸,反而元素可以改变它的尺寸,并适应它们的内容 2. 不应使用平布的坐标,指定元素的位置. 3. 布局容器和它的子元素是共享可以使用的空间 4. 可以嵌套的 ...

  5. 《深入浅出WPF》笔记——事件篇

    如果对事件一点都不了解或者是模棱两可的话,建议先去看张子阳的委托与事件的文章(比较长,或许看完了,也忘记看这一篇了,没事,我会原谅你的)http://www.cnblogs.com/JimmyZhan ...

  6. WPF入门:数据绑定

    上一篇我们将XAML大概做了个了解 ,这篇将继续学习WPF数据绑定的相关内容 数据源与控件的Binding Binding作为数据传送UI的通道,通过INotityPropertyChanged接口的 ...

  7. React.js入门笔记

    # React.js入门笔记 核心提示 这是本人学习react.js的第一篇入门笔记,估计也会是该系列涵盖内容最多的笔记,主要内容来自英文官方文档的快速上手部分和阮一峰博客教程.当然,还有我自己尝试的 ...

  8. WPF入门教程系列三——Application介绍(续)

    接上文WPF入门教程系列二——Application介绍,我们继续来学习Application 三.WPF应用程序的关闭 WPF应用程序的关闭只有在应用程序的 Shutdown 方法被调用时,应用程序 ...

  9. WPF入门教程系列(二) 深入剖析WPF Binding的使用方法

    WPF入门教程系列(二) 深入剖析WPF Binding的使用方法 同一个对象(特指System.Windows.DependencyObject的子类)的同一种属性(特指DependencyProp ...

随机推荐

  1. C#基础:ref和out的区别 [转]

    ref和out的区别在C# 中,既可以通过值也可以通过引用传递参数.通过引用传递参数允许函数成员更改参数的值,并保持该更改.若要通过引用传递参数, 可使用ref或out关键字.ref和out这两个关键 ...

  2. Win8 Metro(C#)数字图像处理--2.52图像K均值聚类

    原文:Win8 Metro(C#)数字图像处理--2.52图像K均值聚类  [函数名称]   图像KMeans聚类      KMeansCluster(WriteableBitmap src,i ...

  3. C# Insert批量插入

    最近项目需要做一个批量导入的功能,每次导入最少的记录数都达到1万,之前写了一个通过循环Insert的方法,结果我自己都看不下了.太慢了,所以用了SqlBulkCopy,很快,100万条数据,1分钟都不 ...

  4. 财富500强的前10个公司里有8个公司在使用Qt(Qt自己认为的优点是:直觉主义、跨平台、节省时间),以及一些商业案例

    8 of Top 10 Fortune 500 use Qt Qt is the software development framework of choice by engineers in ov ...

  5. 至于Nim和Crystal这类语言最大的用途,就是活在脑残粉的理想里(发人警醒)

    lisp,haskell 有很多人在用,而且是编程经验在 10 年以上,包括 Rust 的作者.Nim 的作者.因此,你不知道有人用,那是因为你的开发阅历太低. 人工智能这个领域从来没有脱离 lisp ...

  6. SQLite实现内存键值存储

    SQLite数据文件往Linux内存文件系统/dev/shm/data.sqlite3一放,就是内存级读写性能的SQL系统.用SQLite实现内存键值存储:CREATE TABLE IF NOT EX ...

  7. EF Power Tool 代码生成器 反向生成

    大致来说,这个工具有这样几个功能: 1) 按照现有数据库结构,生成Code First POCO class.DbContext class和相应的mapping class. 2) 以designe ...

  8. HTML连载11-HTML中被废弃的标签&字符实体

    ​一.为什么会有被废弃的标签 答:HTML中以前存在一部分不是用来添加语义的标签,而与我们HTML标签是用来添加语义的,这与我们的定义不相符. 例如: 1.标签<br>:换行 2.标签&l ...

  9. Java算法-求最大和的子数组序列

    问题:有一个连续数组,长度是确定的,它包含多个子数组,子数组中的内容必须是原数组内容中的一个连续片段,长度不唯一,子数组中每个元素相加的结果称为子数组的和,现要求找出和最大的一个子数组. 具体算法如下 ...

  10. java中list和Arrylist的区别

    List:是一个有序的集合,可以包含重复的元素.提供了按索引访问的方式.它继承 Collection. List有两个重要的实现类:ArrayList 和 LinkedList ArrayList:我 ...