How to Attach to MouseDown Event on WPF ListBox
来源:互联网 发布:caffe bene 编辑:程序博客网 时间:2024/06/05 10:07
I wanted to create drag and drop functionality between two list boxes – user should be able to drag items from one ListBox
to another.
For test, I created MouseDown
event handler for list boxes. Here is XAML
for window with two list boxes side by side:
01
<
Window
x:Class
=
"ListBoxMouseEvents.Window1"
02
xmlns
=
"http://schemas.microsoft.com/winfx/2006/xaml/presentation"
03
xmlns:x
=
"http://schemas.microsoft.com/winfx/2006/xaml"
04
Title
=
"Window1"
Height
=
"316"
Width
=
"655"
>
05
<
Grid
>
06
<
Grid.ColumnDefinitions
>
07
<
ColumnDefinition
/>
08
<
ColumnDefinition
Width
=
"20"
/>
09
<
ColumnDefinition
/>
10
</
Grid.ColumnDefinitions
>
11
<
ListBox
x:Name
=
"listBox1"
Mouse.MouseDown
=
"ListBox_MouseDown"
>
12
<
ListBoxItem
>Lorem ipsum dolor sit amet,</
ListBoxItem
>
13
</
ListBox
>
14
<
ListBox
Grid.Column
=
"2"
x:Name
=
"listBox2"
Mouse.MouseDown
=
"ListBox_MouseDown"
>
15
<
ListBoxItem
>Lorem ipsum dolor sit amet,</
ListBoxItem
>
16
</
ListBox
>
17
</
Grid
>
18
</
Window
>
In codebehind, I added simple handler for the MouseDown
events on both listboxes. Handler should popup messagebox with name of the listbox that triggered the event.
01
public
partial
class
Window1 : Window
02
{
03
public
Window1()
04
{
05
InitializeComponent();
06
}
07
08
private
void
ListBox_MouseDown(Object sender, MouseButtonEventArgs e)
09
{
10
ListBox listBox = (ListBox)sender;
11
MessageBox.Show(
"MouseDown event on "
+ listBox.Name);
12
}
13
}
Press F5 and test. Clicked in the middle of the left listbox – MesasgeBox
pops up with correct name. Same for right listbox. Then I accidentally clicked on that one item in the listbox and nothing happened. Item was selected, but no MessageBox
. Obviously,ListBoxItem
class handled event and it stopped propagating.
How routed events work in WPF
MouseDown
is, like all mouse events in WPF, implemented as RoutedEvent
. Mechanics of routed events is described in MSDN article: Routed Events OverView.
In WPF, events can be routed in three ways: bubbling, tunneling and direct routing. Direct routing is not interesting because event fires only in control where it originated. Bubbling and tunneling routing propagate event through the visual tree.
- Bubbling routes event from control where event was invoked to successive parent elements until it reaches the root.
- Tunneling routes event in opposite direction, starting with element tree root and propagates until it reaches control where it was invoked. These are called “Preview” events.
Bubbling and tunneling events are often implemented in pairs. Tunneling events are always invoked first, before corresponding bubbling event.MouseDown
is routed event that is routed by bubbling and his corresponding tunneling or preview event is PreviewMouseDown
.
Routing MouseDown event in ListBox
ListBox
control contains ItemsPresenter
which contains ListBoxItems
(there are other controls in between like border and scrollviewer, but they could be abstracted here because they by default handle MouseDown
event same way as ItemsPresenter
). When I click inside ListBox
, but not on ListBoxItem
, MouseDown
event is routed like this:
- Event originates in
ItemsPresenter
which is first control to receive event. Default handler does not setHandled
property totrue
and event is propagated to its parents, who also do not changeHandled
property, until it reaches theListBox
. ListBox
findsListBox_MouseDown
handler and it invokes it. Code showsMessageBox
and does not changeHandled
property so event can be propagated further. IfWindow
hadMouseDown
event handler, it would be invoked.
When I click on ListBoxItem
inside ListBox
following happens:
ListBoxItem
is first control that receives event. It’sMouseDown
handler have code that deals with the selected item insideListBox
(sets properties related to selection and changes visual appearance). Finally it setsHandled
property totrue
. This suggests that event does not need further handling.
Work around: how to handle ‘handled’ routed events
Fortunately, there are two ways to work around this situation:
- Use the “Preview” event which happens before the bubbling event. This event can be added in
XAML
. When using this approach, you should be careful not to setHandled
property to true, because it will prevent bubbling events to be invoked. - Add handler by using the
handledEventsToo
signature ofAddHandler(RoutedEvent, Delegate, Boolean)
. Limitation of this workaround is that it can be set only in code, not inXAML
.
More details on this can be found in last section of MSDN article Marking Routed Events as Handled, and Class Handling.
Finally, here is the code that uses both approaches – one ListBox
have preview event attached, while the other has handler added in code.
XAML:
01
<
Window
x:Class
=
"ListBoxMouseEvents.Window1"
02
xmlns
=
"http://schemas.microsoft.com/winfx/2006/xaml/presentation"
03
xmlns:x
=
"http://schemas.microsoft.com/winfx/2006/xaml"
04
Title
=
"Window1"
Height
=
"316"
Width
=
"655"
>
05
<
Grid
>
06
<
Grid.ColumnDefinitions
>
07
<
ColumnDefinition
/>
08
<
ColumnDefinition
Width
=
"20"
/>
09
<
ColumnDefinition
/>
10
</
Grid.ColumnDefinitions
>
11
<
ListBox
x:Name
=
"listBox1"
Mouse.PreviewMouseDown
=
"ListBox_MouseDown"
>
12
<
ListBoxItem
>Lorem ipsum dolor sit amet,</
ListBoxItem
>
13
<
ListBoxItem
>consectetur adipiscing elit. </
ListBoxItem
>
14
<
ListBoxItem
>Duis mollis egestas ornare. </
ListBoxItem
>
15
</
ListBox
>
16
<
ListBox
Grid.Column
=
"2"
x:Name
=
"listBox2"
>
17
<
ListBoxItem
>Lorem ipsum dolor sit amet,</
ListBoxItem
>
18
<
ListBoxItem
>consectetur adipiscing elit.</
ListBoxItem
>
19
<
ListBoxItem
>Duis mollis egestas ornare.</
ListBoxItem
>
20
</
ListBox
>
21
</
Grid
>
22
</
Window
>
CodeBehind:
01
public
partial
class
Window1 : Window
02
{
03
public
Window1()
04
{
05
InitializeComponent();
06
// Add handler. Note third parameter: handledEventsToo = true
07
listBox2.AddHandler(UIElement.MouseDownEvent,
08
new
MouseButtonEventHandler(ListBox_MouseDown),
true
);
09
}
10
11
private
void
ListBox_MouseDown(Object sender, MouseButtonEventArgs e)
12
{
13
ListBox listBox = (ListBox)sender;
14
this
.Title =
"MouseDown event on "
+ listBox.Name;
15
}
16
}
Note that in this version text is displayed in the title of the window instead ofMessageBox
. I changed it because showing message box in PreviewMouseDown
event was interfering with event propagation and item in left list box was not selected after click – looked like click never happened. It probably has something to do with the fact that there were other mouse events happening when I was closing message box. So, be careful with actions in preview event.
For drag/drop handling I will use second approach – adding handler that receives handled events. Drag and drop functionality needs information about selected item. I could get that myself in preview event, but why, when there is code in event handler of ListBoxItem.
Referenced from: http://www.wpfnewbie.com/2010/07/22/how-to-attach-to-mousedown-event-on-listbox/
- How to Attach to MouseDown Event on WPF ListBox
- How to bind listbox to data dynamically
- How to add event listener to div
- How to attach behavior in code behind (Silverlight 3)
- How to attach JDK source code in Eclipse?
- Eclipse – How to attach JDK source code
- How to Find Blocking Session for Mutex Wait Event cursor: pin S wait on X
- How to invoke a JSF managed bean on a HTML DOM event using native JavaScript?
- Attach to an already running managed process on device
- How to use VB6.0's Event.
- MFC how to handle ocx event
- How to add event for usercontorl ?
- How to simulate Mouse Click event
- how to trigger event in program
- How to automatically select all text on focus in WPF TextBox?
- Attach Gripper to Robot
- attach source to Struts2
- how to detemine event file node belongs to which device
- UIDeviceOrientation 和 UIInterfaceOrientation 设备旋转的用法 (实例)
- 用 Addr2line 将函数地址解析为函数名
- Myeclipse中集成SVN
- Android ndk 开发环境搭建
- MANI fold Learning Matlab Demo
- How to Attach to MouseDown Event on WPF ListBox
- dyld: Symbol not found:
- A*算法
- 新浪微博开发三----------------------发微博
- fedora 17下的文件安装
- JAVA的线程同步
- MFC 带参数运行
- EXTJS4.2中neptune主题的使用
- 直接拿来用!最火的Android开源项目