路由事件

简介: 原文:路由事件简介:每个.NET开发人员都熟悉"事件"的思想,当有意义的事情发生时,由对象(WPF元素)发送的用于通知代码的消息。WPF通过路由(event routing)的概念增强了.Net事件模型,事件路由允许源自某个元素的事件由另一个元素引发。
原文: 路由事件

简介:每个.NET开发人员都熟悉"事件"的思想,当有意义的事情发生时,由对象(WPF元素)发送的用于通知代码的消息。WPF通过路由(event routing)的概念增强了.Net事件模型,事件路由允许源自某个元素的事件由另一个元素引发。

1、定义、注册和封装路由事件。

步骤:

1.1)、由只读的、静态的方式声明。

1.2)、在静态的构造函数中通过EventManager.RegisterRoutedEvent()方法注册。

1.3)、通过.Net事件定义进行封装。

例子:

public class ButtonBase:ContentControl
{
    //声明只读的、静态的、RoutedEvent类型的字段。
    public static readonly RoutedEvent ClickEvent;

    /// <summary>
    /// 在静态的构造函数中注册路由事件。
    /// </summary>
    static ButtonBase()
    {
        //路由事件是使用EventManager.RegisterRoutedEvent()方法注册的。
        //参数:Click:事件的名称。
        //参数:RoutingStrategy.Bubble:路由的类型(冒泡路由、隧道路由)。
        //参数:typeof(RoutedEventHandler):定义事件处理程序语法的委托。
        //参数:typeof(ButtonBase):拥有事件的类。
        ClickEvent = EventManager.RegisterRoutedEvent("Click", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(ButtonBase));
    }

    //通过普通的.Net事件进行封装,从而使所有的.Net语言都能访问他,事件封装器可使用AddHandle()和RemoveHandle()方法添加删除已注册的程序。
    public event RoutedEventHandler Click
    {
        add
        {
            //为指定的路由事件添加路由事件处理程序,并将该处理程序添加到当前元素的处理程序集合中。
            base.AddHandler(ClickEvent, value);
        }
        remove
        {
            //从此元素移除指定的路由事件处理程序。
            base.RemoveHandler(ClickEvent, value);
        }
    }
}

 2、共享路由事件。

与依赖项属性一样,可在类之间共享路由事件的定义,例如,UIElement(该类是所有普通WPF元素的起点),MouseUp事件是由System.WIndows.Input.Mouse类定义的,UIElement类和ContentElement类只通过Routed-Event.AddOwner()方法重用MouseUp事件。

UIElemtn.MouseUpEvent = Mouse.MouseUpEvent.AddOwner(typeof(UIElement));

3、处理路由事件。

 3.1)、Xaml的方式添加处理程序。

Xaml代码: 

<Grid>
    <Image Name="img1" Source="Images/1.jpg" MouseEnter="Image_MouseEnter"></Image>
</Grid>

Image_MouseEnter处理函数: 

private void Image_MouseEnter(object sender, MouseEventArgs e)
{
    MessageBox.Show("MouseEnter事件");
}

3.2)、通过+=使用代码链接。

创建了一个针对该事件具有正确签名的委托对象(该类中是MouseEventHandler委托的实例),并将该委托指向Img_MouseEnter()方法。然后将该委托添加到img1.MouseEnter事件的已注册的事件的处理程序列表中 

private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
    //第一种写法。
    img1.MouseEnter += new MouseEventHandler(Img_MouseEnter);
    //第二种写法。
    img1.MouseEnter += Img_MouseEnter;
}

private void Img_MouseEnter(object sender, MouseEventArgs e)
{
    MessageBox.Show("进入了MouseEnter事件");
}

 3.3)、通过AddHandler()方法添加事件处理程序。

private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{   
    //Image.MouseEnterEvent:处理路由事件的标志符。
    //new MouseEventHandler(Img_MouseEnter):处理程序实现的引用。
    img1.AddHandler(Image.MouseEnterEvent, new MouseEventHandler(Img_MouseEnter));
}
private void Img_MouseEnter(object sender, MouseEventArgs e)
{
    MessageBox.Show("进入了MouseEnter事件");
}

4、断开事件处理程序。

4.1)、通过-=断开事件处理程序。 

//第一种写法。
img1.MouseEnter -= new MouseEventHandler(Img_MouseEnter);
//第二种写法。
img1.MouseEnter -= Img_MouseEnter;

4.2)、通过RemoveHandler()方法断开事件处理程序。

img1.RemoveHandler(Image.MouseEnterEvent, new MouseEventHandler(Img_MouseEnter));

5、事件路由。

WPF中,事件路由以3种方式出现:直接路由事件(Direct event)、冒泡路由事件(bubbing event)、隧道路由事件(tunneling)。

在WPF中,如果事件不需要传递任何额外细节,可使用RoutedEventArgs类,该类包含了一些有关如何传递事件的一些细节,如果事件确实需要传递一些额外的信息,那么需要使用更特殊的继承自RoutedEventArgs的对象,其中每个WPF事件参数类都继承自RoutedEventArgs类。

RoutedEventArgs类常用属性

Source

指示引发事件的对象。

OriginalSource

指示最初是什么对象引发了事件。

RoutedEvent

通过事件处理程序为触发的事件提供RoutedEvent对象,如果同一个事件处理程序处理不同的事件,这一信息是非常有用的。

Handled

该属性允许终止事件的冒泡或隧道过程,如果将该属性设置为true,就终止了传递。

 

 

 

 

 

 

 

 

5.1)、直接路由。

源于同一个元素,不传递给其他。如元素的MouseEnter事件。  

5.2)、冒泡路由。

从下到上传递。一般情况下,冒泡路由以Mouse开头,如MouseDown、MouseUp。

Xaml代码:

<Window x:Class="冒泡路由.MainWindow"
        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:冒泡路由"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525" MouseDown="SomethingClick">
  <Grid MouseDown="SomethingClick">   <Grid.RowDefinitions>   <RowDefinition></RowDefinition>   <RowDefinition></RowDefinition>   </Grid.RowDefinitions>   <Label MouseDown="SomethingClick">   <StackPanel MouseDown="SomethingClick">   <TextBlock MouseDown="SomethingClick">Hello,World!!!</TextBlock>   <Label MouseDown="SomethingClick">World,Hello</Label>   <Image MouseDown="SomethingClick" Source="Images/1.jpg"></Image>   </StackPanel>   </Label>   <ListBox Name="listBox" Grid.Row="1"></ListBox>   </Grid> </Window>

 后台代码: 

protected int eventCount = 0;
private void SomethingClick(object sender, MouseButtonEventArgs e)
{
    eventCount++;
    string message = "#" + eventCount.ToString() + ":\r\n" +
    " Sender: " + sender.ToString() + "\r\n" +
    " Source: " + e.Source + "\r\n" +
    " Original Source" + e.OriginalSource;
    //将内容加入到listBox中。
    listBox.Items.Add(message);
    //如果将Handled属性设置为true,则终止传递。
    //e.Handled = true;
}

效果:

 

当点击了图片,会从下到上地发生冒泡路由,直到冒泡到最外层的父级元素。 

5.3)、隧道路由。

从上到下传递。 隧道路由比较容易识别,冒泡以Preview开头,如PreviewMouseDown、PreviewMouseUp。WPF通常成对地定义冒泡路由事件和隧道路由事件,这意味着如果发现冒泡的MouseUp事件,还可以找到PreviewUp隧道事件,隧道路由事件总是在冒泡路由事件之前被触发。如果隧道路由事件标记为已处理过,就不会发生冒泡路由事件,这是因为两个事件共享RoutedEventArgs类。

Xaml代码:

<Window x:Class="隧道路由事件.MainWindow"
        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:隧道路由事件"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525" PreviewMouseDown="SuiDaoThings">
        <Grid PreviewMouseDown="SuiDaoThings">
            <Grid.RowDefinitions>
                <RowDefinition Height="100"></RowDefinition>
                <RowDefinition></RowDefinition>
            </Grid.RowDefinitions>

            <StackPanel Grid.Row="0" PreviewMouseDown="SuiDaoThings">
                <Image Source="Images/1.jpg" PreviewMouseDown="SuiDaoThings"></Image>
            </StackPanel>    
        
            <ListBox Name="listBox1" Grid.Row="1"></ListBox>        
        </Grid>
</Window>

后台代码:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    int count = 0;
    private void SuiDaoThings(object sender, MouseButtonEventArgs e)
    {
        count++;
        string message = "#" + count + ":\r\n" +
        " Sender: " + sender + "\r\n" +
        " Source " + e.Source + "\r\n" +
        " Original" + e.OriginalSource;
        listBox1.Items.Add(message);
    }
}

效果:

5.4)、处理挂起的事件。

有一种方法可接收被标记为处理过的事件,不过不是直接通过XAML关联事件处理程序,而是必须使用AddHandle()方法,AddHandle()方法提供了一个重载版本,该版本可以接收一个Boolean值作为他的第三个参数,如果将该参数设置了True,即使设置了Handle标志,也将接收事件。

Xaml代码,不直接指定事件处理函数:

<Window x:Class="冒泡路由.MainWindow"
        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:冒泡路由"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525" Name="window1">        
        <Grid Name="grid1">
            <Grid.RowDefinitions>
                <RowDefinition Height="150"></RowDefinition>
                <RowDefinition></RowDefinition>
            </Grid.RowDefinitions>
            
            <Label Name="label1">
                <StackPanel Name="stackPanel1">
                    <Image Name="img1" Source="Images/1.jpg"></Image>
                </StackPanel>
            </Label>        
            <ListBox Name="listBox" Grid.Row="1"></ListBox>        
        </Grid>
</Window>

 后台代码:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        //通过AddHandle()方法添加事件处理程序。
        img1.AddHandler(UIElement.MouseDownEvent,new  MouseButtonEventHandler(SomethingClick),true);
        stackPanel1.AddHandler(UIElement.MouseDownEvent, new MouseButtonEventHandler(SomethingClick), true);
        label1.AddHandler(UIElement.MouseDownEvent, new MouseButtonEventHandler(SomethingClick), true);
        grid1.AddHandler(UIElement.MouseDownEvent, new MouseButtonEventHandler(SomethingClick), true);
        window1.AddHandler(UIElement.MouseDownEvent, new MouseButtonEventHandler(SomethingClick), true);
    }

    protected int eventCount = 0;
    private void SomethingClick(object sender, MouseButtonEventArgs e)
    {
        eventCount++;
        string message = "#" + eventCount.ToString() + ":\r\n" +
        " Sender: " + sender.ToString() + "\r\n" +
        " Source: " + e.Source + "\r\n" +
        " Original Source" + e.OriginalSource;
        listBox.Items.Add(message);
        //如果使用AddHandle()方法添加事件处理程序,那么设置Handled属性不会阻止路由,仍会继续向上冒泡路由传递。
        e.Handled = true;
    }
}

 效果图,如果使用AddHandle()方法的重载设置为true的那个,设置e.Handled属性为True,会继续传递。

5.5)、附加事件。

Button元素有Click事件,而StackPanel元素则没有Click事件,如果要为StackPanel元素添加Click事件,则报错。这个时候附加事件的优势就体现出来了。

在Xmal中添加附加事件: 

<Grid>
    <!--由于StackPanel元素没有Click事件,所以XAMl解析器会将其解析成错误。-->
    <StackPanel Margin="5" Click="DoSomeThing">
        <Button Name="Cmd1">Cmd1</Button>
        <Button Name="Cmd2">Cmd2</Button>
        <Button Name="Cmd3">Cmd3</Button>
    </StackPanel>

    <!--添加附加事件。-->
    <StackPanel Margin="5" Button.Click="DoSomeThing">
        <Button Name="Cmd11">Cmd11</Button>
        <Button Name="Cmd22">Cmd22</Button>
        <Button Name="Cmd33">Cmd33</Button>
    </StackPanel>
</Grid>

 通过AddHandle()方法添加附加事件:

Xaml代码: 

<StackPanel Margin="5" Name="stackPanel1">
    <Button Name="Cmd1">Button1</Button>
    <Button Name="Cmd2">Button2</Button>
    <Button Name="Cmd3">Button3</Button>
</StackPanel>

 后台代码:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        //通过AddHandler方法添加附加事件。
        stackPanel1.AddHandler(Button.ClickEvent, new RoutedEventHandler(DoSomeThing));
    }
    private void DoSomeThing(object sender, RoutedEventArgs e)
    {
            
    }
}

 6、WPF事件。

一般情况下,WPF最重要的事件包括这5类,分别是:生命周期事件、鼠标事件、键盘事件、手写笔事件和多点触控事件。

6.1)、生命周期事件。

生命周期事件是在元素被初始化,加载或卸载时发生这些事情。都是在FrameworkElement类中定义的。 

所有元素的生命周期

Initialized

当元素被初始化,并已根据Xaml标记设置了元素的属性之后发生,这时元素已经初始化,但窗口的其他部分可能尚未初始化,但是,此时还没应用样式和数据绑定,这时,IsInitialized属性为true

Loaded

当整个窗口已经初始化并应用了样式和数据绑定时,该事件发生,就是在元素呈现之前的最后一站,这时IsLoaded属性为true

UnLoaded

当元素被释放时,该事件发生。原因是包含元素的窗口被关闭或者特定的元素被从窗口中删除。

 

Window类的常用生命周期事件

名称

说明

ContentRendered

在窗口首次呈现后立即发生,ContentRendered事件表明窗口已经完全可见,并且已经准备好接收输入

Activated

当用户切换到该窗口时发生(从其他窗口切换到当前窗口),当窗口第一次加载也会引发该事件

Deactivated

当用户从该窗口切换到其他窗口时发生。

Closing

当关闭窗口时发生,不管是用户关闭窗口,还是通过代码WIndow.Close()

Closed

当窗口已经关闭后发生,但是让然可以访问元素对象,当然是在UnLoaded事件尚未发生之前

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

如果只对执行控件的第一次初始化感兴趣,完成这项任务的最好时机是触发Loaded事件。

6.2)、输入事件。

 输入事件是当用户使用某些种类的外设硬件进行交互时发生的事件,如鼠标、键盘、手写笔或者多触控屏。输入事件可通过继承自InputEventArgs的自定义事件参数类型传递额外的信息。

6.2.1)、键盘输入。

当用户按下键盘上的一个键时,就会发生一系列事件。键盘处理永远不是那么的简单,一些控件可能会挂起这些事件中的某些事件,最明显的是TextBox控件,他挂起了TextInut事件,TextBox控键还挂起了KeyDown事件,通常可以使用隧道路由事件。

所有元素的按下键盘的顺序

名称

路由类型

说明

PreviewKeyDown

隧道

当按下一个键时发生

KeyDown

路由

当按下一个键时发生

PreviewTextInput

隧道

当输入完成且元素正在接收文本输入时发生,对不会产生文本输入的按键(Ctrl键、shift键、方向键等),不会引发该事件

TextInput

路由

当输入完成且元素正在接收文本输入时发生,对不会产生文本输入的按键,不会引发该事件

PreviewKeyUp

隧道

当释放一个键时发生

KeyUp

路由

 

当释放一个键时发生

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Xaml中定义:

<Window x:Class="鼠标输入事件.MainWindow"
        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:鼠标输入事件"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="50"></RowDefinition>
            <RowDefinition></RowDefinition>            
        </Grid.RowDefinitions>
        
        <Grid.ColumnDefinitions>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
        </Grid.ColumnDefinitions>
        
        <Label Content="请输入要输入的内容:" FontSize="20" HorizontalAlignment="Right" VerticalAlignment="Center"/>
        <TextBox Grid.Column="1" Margin="5" PreviewKeyDown="TextBox_PreviewKeyDown" KeyDown="TextBox_KeyDown" PreviewTextInput="TextBox_PreviewTextInput" TextInput="TextBox_TextInput" PreviewKeyUp="TextBox_PreviewKeyUp" KeyUp="TextBox_KeyUp" TextChanged="TextBox_TextChanged"></TextBox>
        <ListBox Name="listBox1" Grid.Row="1" Grid.ColumnSpan="2" Margin="20"></ListBox>        
    </Grid>
</Window>

 后台代码:

//PreviewKeDown事件处理程序。
private void TextBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
    string message = string.Format("Event--->{0},Key--->{1}", e.RoutedEvent, e.Key);
    listBox1.Items.Add(message);
}
//KeyDown事件处理程序。
private void TextBox_KeyDown(object sender, KeyEventArgs e)
{
    string message = string.Format("Event--->{0},Key--->{1}", e.RoutedEvent, e.Key);
    listBox1.Items.Add(message);
}
//PreviewTextInput事件处理程序。
private void TextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
    string message = string.Format("Event--->{0},Key--->{1}", e.RoutedEvent, e.Text);
    listBox1.Items.Add(message);
}
//TextInput事件处理程序,不会执行此事件处理程序,因为TextBox元素挂起了TextInput事件。
private void TextBox_TextInput(object sender, TextCompositionEventArgs e)
{
    string message = string.Format("Event--->{0},Key--->{1}", e.RoutedEvent, e.Text);
    listBox1.Items.Add(message);
}
//PreviewKeyUp事件处理程序。
private void TextBox_PreviewKeyUp(object sender, KeyEventArgs e)
{
    string message = string.Format("Event--->{0},Key--->{1}", e.RoutedEvent, e.Key);
    listBox1.Items.Add(message);
}
//KeyUp事件处理程序。
private void TextBox_KeyUp(object sender, KeyEventArgs e)
{
    string message = string.Format("Event--->{0},Key--->{1}", e.RoutedEvent, e.Key);
    listBox1.Items.Add(message);
}
//TextChanged事件处理程序。
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
    string message = string.Format("Event--->{0}", e.RoutedEvent);
    listBox1.Items.Add(message);
}

 效果图,在文本框中输入了一个K键:

 

6.2.2)、 焦点。

在Windows的世界中,用户每次只能使用一个控件,当前接收用户按键的控件是具有焦点的控件。为了让控件能接受焦点,必须将Focusable设置为true,这是所有控件的默认值,如果为TextBox元素的Focusable元素设置为false,就不会获取焦点了,可以通过TabIndex属性设置按下tab键后的顺序。

6.2.3)、获取键盘状态。

当发生按键事件时,经常需要知道更多的信息,不仅需要知道按下的是哪个键,其他键是否按下了也同样重要,特别是Shift键、Ctrl键、Alt键。

KeyBoardDevice属性提供了KeyBoardDevice类的一个实例,它的属性包含了当前是哪个元素具有焦点以及按下了哪些修饰键,可用代码显示。

Xmal代码: 

<TextBox PreviewKeyDown="TextBox_PreviewKeyDown"></TextBox>

后台代码:

private void TextBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
    if ((e.KeyboardDevice.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
    {
        MessageBox.Show("你点击了Control键");
    }

    //还可以使用KeyBoard类,该类和KeyboardDevice类非常类似,只是Keyboard类由静态成员构成。
    if (Keyboard.IsKeyDown(Key.LeftCtrl))
    {
        MessageBox.Show("按下了Ctrl键盘");
    }
}

 6.2.4)、鼠标输入。

 鼠标事件执行几个关联的任务,当鼠标移到某个元素上时,可通过最基本的鼠标事件进行响应,这些都是MouseEnter和MouseLeave(直接事件)。

所有元素的鼠标单击事件(按顺序排序)

名称

路由类型

说明

PreviewMouseLeftButtonDown

PreviewMouseRightButtonDown

隧道

按下鼠标左键时发生

MouseLeftButtonDown

MouseRightButtonDown

隧道

按下鼠标左键时发生

PreviewMouseLeftButtonUp

PreviewMouseRightButtonUp

隧道

按下鼠标右键时发生

MouseLeftButtonUp

MouseRightButtonUp

隧道

按下鼠标右键时发生

PreviewMouseWheel

隧道

鼠标滚轮动作

MouseWheel

冒泡

鼠标滚轮动作

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

6.2.5)、捕获鼠标。

当鼠标被一个元素捕获时,就不能与其他元素进行交互了(不能单击窗口中的其他元素),鼠标捕获通常用于短时间的操作。

Xaml代码: 

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition></RowDefinition>
        <RowDefinition></RowDefinition>
    </Grid.RowDefinitions>

    <Canvas Background="AliceBlue"></Canvas>
    <Button Name="btn1" Grid.Row="1" Margin="20" Click="Button_Click">Hello,World!!!</Button>        
</Grid>

后台代码:

private void Button_Click(object sender, RoutedEventArgs e)
{
    Mouse.Capture(btn1);
}

当点击button按钮后,整个窗口的其他元素和按钮就不能点击了,只有把光标移开该窗口,然后点击一下,这个窗口的元素才可以点击。

6.2.6)、鼠标拖放。

拖放操作的方法和事件都集中在System.Windows.DragDrop类中。

拖放操作有以下3个步骤:

1)、用户单击元素,并保持鼠标按键为按下状态,这时,某些信息被搁置起来,并且拖放操作开始。

2)、用户将鼠标移动到其他元素上,如果该元素可接受正在拖动的内容的类型,鼠标指针会变成拖放图标,否则鼠标指针会变成内部有一条线的圆形。

3)、当用户释放鼠标键时,元素接收信息并决定如何处理接收到的信息,在没有释放鼠标键时,可按下Esc键取消该操作。

Xaml代码: 

<Window x:Class="鼠标拖放.MainWindow"
        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:鼠标拖放"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
        <Grid ShowGridLines="True">
            <Grid.RowDefinitions>
                <RowDefinition></RowDefinition>
                <RowDefinition></RowDefinition>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition></ColumnDefinition>
                <ColumnDefinition></ColumnDefinition>
            </Grid.ColumnDefinitions>

            <!--为源元素设置MouseDown事件-->
            <Label Name="lbl1" MouseDown="lbl1_MouseDown" Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Center">Hello,World!!!</Label>
            <TextBox Name="textBox1" Grid.Column="1" Height="35" Margin="10"></TextBox>
            <!--为目标属性设置AllowDrop属性,然后再Drop事件中写内容-->
            <Label Name="lbl2" Grid.Row="1" Drop="lbl2_Drop" AllowDrop="True" HorizontalAlignment="Center" VerticalAlignment="Center">今天天气好晴朗!!!</Label>       
        </Grid>
</Window>

后台代码:

/// <summary>
/// 源元素的MouseDown事件。
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void lbl1_MouseDown(object sender, MouseButtonEventArgs e)
{
    //转换成Label对象。
    Label lbl = (Label)sender;

    //DragDrop类用于拖动操作。
    //DoDragDrop()方法用于启动拖放操作。 源对象,源对象的属性,拖放的效果(复制,移动...)
    //DoDragDrop()方法重载参数:源对象,源对象的属性,拖放的效果(复制,移动...)
    DragDrop.DoDragDrop(lbl, lbl.Content, DragDropEffects.Scroll);
}

/// <summary>
/// 目标元素的Drop事件。
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void lbl2_Drop(object sender, DragEventArgs e)
{
    //获取指定数据对象,格式由字符串指定。
    ((Label)sender).Content = e.Data.GetData(DataFormats.Text);
}

6.2.7)、多点触控输入(适用于带触摸屏的电脑)。

所有元素的原始触控事件

名称

路由类型

说明

PreviewTouchDown

隧道

用户触摸元素时发生

TouchDown

冒泡

用户触摸元素时发生

PreviewTouchMove

隧道

用户移动到触摸屏上的手指时发生

TouchMove

冒泡

用户移动到触摸屏上的手指时发生

PreviewTouchUp

隧道

用户移开手指,结束触摸时发生

TouchUp

冒泡

用户移开手指,结束触摸时发生

TouchEnter

触点从元素外进入元素内时发生

TouchLeave

触点离开元素时发生

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

End。

目录
相关文章
|
26天前
|
缓存 JavaScript 前端开发
vue-router学习二:动态路由(路由传递数据的一种方式),路由懒加载,嵌套路由,路由传递参数方式,导航守卫,keep-alive标签
这篇文章主要介绍了Vue Router的高级用法,包括动态路由、路由懒加载、嵌套路由、路由参数传递、导航守卫以及keep-alive的使用。
24 0
vue-router学习二:动态路由(路由传递数据的一种方式),路由懒加载,嵌套路由,路由传递参数方式,导航守卫,keep-alive标签
|
3月前
|
网络协议 网络虚拟化
如何对接收和发布的路由进行过滤?
如何对接收和发布的路由进行过滤?
|
4月前
|
JavaScript 前端开发 API
Vue Router【详解】含路由配置、路由定义、路由跳转、路由传参、自动注册路由、路由守卫、页面滚动、监听路由、$route、$router、路由过渡动画等
Vue Router【详解】含路由配置、路由定义、路由跳转、路由传参、自动注册路由、路由守卫、页面滚动、监听路由、$route、$router、路由过渡动画等
825 0
路由策略与路由控制
路由策略与路由控制
页面第二次进入或者多次进入,事件总线触发事件多次,eventBus触发多次
页面第二次进入或者多次进入,事件总线触发事件多次,eventBus触发多次
uiu
|
JavaScript 调度
【Svelte】-(5)DOM事件 / 事件修饰符 / 组件事件 / 事件转发 (组件之间的事件沟通)
【Svelte】-(5)DOM事件 / 事件修饰符 / 组件事件 / 事件转发 (组件之间的事件沟通)
uiu
209 0
【Svelte】-(5)DOM事件 / 事件修饰符 / 组件事件 / 事件转发 (组件之间的事件沟通)
|
JavaScript 开发者
路由-为路由切换启动动画|学习笔记
快速学习路由-为路由切换启动动画
路由-为路由切换启动动画|学习笔记
|
移动开发 前端开发 API
【前端】【H5 API】addEventListener监听网络状态的变动
【前端】【H5 API】addEventListener监听网络状态的变动
437 0
|
JSON 小程序 JavaScript
小程序事件、组件、生命周期、路由及数据请求
小程序事件、组件、生命周期、路由及数据请求
269 0
小程序事件、组件、生命周期、路由及数据请求
|
监控 JavaScript
路由中的钩子
路由中的钩子
135 0