路由事件

原文: 路由事件

简介:每个.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。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值