Wednesday, May 27, 2009

Why doesn’t my WPF Trigger work? (... a peek into the Dependency Property evaluation process)

Imagine a simple situation where I have a blue rectangle:

<Grid>
<Rectangle Height="200" Width="300" Fill="Blue"/>
</Grid>



Now when I do a mouse over the rectangle, I want the color to turn to red - simple! The obvious choice in WPF is to add a property trigger. So that’s what I do.


<Grid>
<Grid.Resources>
<Style TargetType="Rectangle" x:Key="rectStyle">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Fill" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
</Grid.Resources>
<Rectangle Height="200" Width="300" Fill="Blue"
Style="{StaticResource rectStyle}"/>
</Grid>



But it doesn’t work! What could be wrong? Perhaps the mouse over event isn’t firing on the rectangle for some reason? I debug the trigger using this cool technique and find that the trigger is firing alright. Then what on earth is the problem?

A closer look reveals the real issue. The culprit was the Fill="Blue" assignment! When evaluating the value of a dependency property, the dependency property system takes into consideration a few factors. The whole dependency property value evaluation process is shown below. Certain factors have priority over others as shown in Step 1 below.

Step 1: Determine Base Value
In the order of diminishing priority:
(a) Local Value
(b) Style triggers
(c) Template Triggers
(d) Style Setters
(e) Theme Style Triggers
(f) Theme Style Setters
(g) Inheritance
(h) Default Value

Step 2: Evaluate
– If Step 1 returns expression (DataBinding or DynamicResource), evaluate

Step 3: Apply Animation

Step 4: Coerce
- If CoerceValueCallback defined

Step 5: Validate
- If ValidateValueCallback defined

In the above example of the rectangle, the trigger (see Step 1b) that I set in the style, had lower priority when compared to the local value (see Step 1a), that is the Fill="Blue" assignment. That was the reason why the trigger value was ignored. So the result/output of Step 1 as far as the Fill property was concerned was the local value “Blue”. In this example, Steps 2-5 do not apply.

So how do I get my trigger to work? If I remove the local value assignment for Fill, and instead set that value within the style, then everything will work as expected because triggers (see Step 1b) have higher priority over style setters (see Step 1d).


<Grid>
<Grid.Resources>
<Style TargetType="Rectangle" x:Key="rectStyle">
<Setter Property="Fill" Value="Blue" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Fill" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
</Grid.Resources>
<Rectangle Height="200" Width="300"
Style="{StaticResource rectStyle}"/>
</Grid>



Now the trigger works as expected!

5 comments:

Sajiv Thomas said...

thanks for sharing this :)

Vinod Tharakan said...

Hi Jim,

Wanted to get back in touch.

We met a couple of years back at the Silverlight launch in Cochin.

Please email me at vtharakan@gmail.com if you get this message.

Tks,

Vinod Tharakan
Cochin, Kerala.

coffe said...

情色台灣情色台灣3p情色哈拉情色商品情色天空情色妹妹情色孕婦情色守門員破解情色客棧情色寫真聯盟情色寮天情色小游戲情色hbo情色留言板情色線上聊天交友走光貼圖走光貼圖et倩色貼圖做愛貼圖偷拍女生裙底貼圖偷拍情色貼圖偷拍貼圖偷拍貼圖區偷拍貼圖貼片偷拍露奶貼圖偷窺貼圖貼圖區性愛girl5320貼圖區免費美女聊天室免費聊天網如何讓金牛男追求如何讓男人有性高潮如何讓男人性高潮如何讓男人高潮如何高潮如何誘惑男人如何認識熟女如何製造激情如何製造性高潮如何電話性愛如何陰道高潮女人不用套做愛如何對男人口交婐體辣妹妹妹視訊影片

EASY said...

情色百分百情色皇朝情色直播情色直播網情色相姦情色硬弟弟成人情色禁忌情色絲襪情色綱情色綱站情色網球員情色網站破解情色網路情色酒店情色金瓶梅免費美女視訊av女優介紹免費美眉視訊免費聊天免費聊天0401免費聊天66k免費聊天firework免費聊天性伴侶免費聊天室免費聊天室申請踢人免費聊天室交友免費聊天區免費聊天情人d760免費聊天視赤裸裸視訊聊天走光視訊姿勢做愛姿勢走光姦淫圖姓愛辣妹姓愛姐妹一夫自拍妻子色情影片妻子的誘惑亂倫小說妹妹泰正點妹妹成人網妹妹情色網妹妹免費視訊妹妹做愛如何令女人高潮如何令女人興奮

健康保寶 said...

Unable to give you a heart. so have a reply to push up your post. ........................................