Published on

# Programmatically adding EventSetters in WPF

Authors

I've been doing some WPF work lately. WPF is ridiculously powerful and provides a lot more than WinForms. On the other hand - wow, the learning curve is quite steep. I think I'm improving, though.

So, the scenario. I wanted to be able to let a user click on an item in a ListBox and drag across, selecting multiple items in the process. Basically, I want to emulate the behavior that the Outlook calendar provides. I ended up coding up the following XAML to get the behavior:

<ListBox
x:Name="myListBox"
SelectionMode="Multiple"
ItemsSource="{Binding Path=SomeIEnumerableOnMyDataContext}"
>
<ListBox.Resources>
<Style
TargetType="{x:Type ListBoxItem}"
>
<EventSetter
Event="PreviewMouseLeftButtonDown"
Handler="ListBoxItem_PreviewMouseLeftButtonDown" />
<EventSetter
Event="PreviewMouseUp"
Handler="ListBoxItem_PreviewMouseUp" />
<EventSetter
Event="PreviewMouseMove"
Handler="ListBoxItem_PreviewMouseMove" />
<EventSetter
Event="PreviewMouseRightButtonDown"
Handler="ListBoxItem_PreviewMouseRightButtonDown" />
</Style>
</ListBox>


The problem with this code is that Blend (currently v2 SP1) doesn't like EventSetters.

I wanted to keep the events hooked up so that, while testing, I could keep the behavior but, at the same time, I want to be able to at least try to design in blend. So I took to implementing the above XAML in code.

Sacha Barber has a good article on converting from XAML to code and back that helped a lot but it didn't get me quite there.

Here is how to programmatically create one of the EventSetters in code:

var style = new Style(typeof (ListBoxItem));

new EventSetter(PreviewMouseLeftButtonDownEvent,
new MouseButtonEventHandler(OnPreviewMouseLeftButtonDown)));


It's pretty straightforward, but actually hooking this style into my ListBox was what got me confused next.

Setting the ListBox's style to my style instance didn't work and then I got stuck on how to plug my style into the ListBox's ResourceDictionary (via the Resources property). The XAML doesn't specify a Key anywhere, but the Resources's Add method requires a key. I tried creating my own key and also specifying a null key, but I still didn't get the behavior I wanted.

StackOverflow's goal of being the place for one-off questions like this is starting to work because I stumbled across my answer via Google. I didn't realize that, in the above XAML, when the Style specifies its TargetType, the type is implicitly the Key in the ResourceDictionary.

So the solution is this:

Resources.Add(typeof (ListBoxItem), style);


Easy enough.