Archives for: April 2008
28/04/08
WPF styles and default behavior
After my recent presentation at the VBUG conference, somebody sent me this question: "I have code to style a button and several triggers to change the button's background color. For some reason, the trigger for the IsPressed property doesn't seem to work. Why?" Here's the style code that was being used (this actually includes some changes I made to the original, but never mind that):
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="Red"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Green"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Width" Value="200" />
<Setter Property="Background" Value="Lime" />
</Trigger>
</Style.Triggers>
</Style>
With a few buttons on a form and this style code installed in App.xaml, you can easily see that he's right - the IsMouseOver property change triggers a change of the background color to green, but IsPressed seems to do its job only partly, since it misses setting the Background property to Lime. In the original example, the change to the background color in that trigger was actually the only thing that was supposed to happen, so it looked like nothing was happening at all. With my changes, it seems obvious that the trigger is observed correctly, but the Background property change doesn't seem to be executed.
The reason for this behavior is simple: there are standard templates in place that format the buttons in the way we're normally used to seeing a button formatted. On Vista that means setting the background color to a certain gradient, displaying a rounded rectangle, and having certain animations in place that are executed when the button is focused, the mouse moves over it or it is clicked. This standard behavior is also implemented as control templates using triggers, and so interests collide - the triggers in the sample code actually do set the background color to Green or Lime, only the standard trigger quickly starts doing something else. As a result, the IsMouseOver trigger sets the color to Green only for a short while before the standard animation sets in, and in the IsPressed case the color is actually never seen.
To solve this problem I used Blend to get hold of the standard control template for a button. I opened my test solution in Blend, selected one of my buttons and used the context menu entry Edit Control Parts (Template) | Edit a Copy... to have a block of code for the base template inserted into my XAML file. Note that this block is inserted into the Window class XAML file by default. In many cases this is actually the sensible solution, but in the sample application I had my styles defined in App.xaml, so I had to move the block across to that file. If you do this, be aware that there's also an XML namespace Microsoft_Windows_Themes inserted by Blend, which you have to move together with the code in order to make things work.
Now, if you have a close look at this code that has been created by Blend, you will see that there are three "events" called RenderDefaulted, RenderMouseOver and RenderPressed configured to call various elements of the ButtonBase class, which are pulled in using the TemplateBinding syntax extension. In addition, there are some triggers that are also involved with changing the button's appearance in response to various events.
For this example, I chose to remove all those elements to break things down to an extremely basic button that doesn't react visually anymore (apart from my own triggers) to mouse moves or clicks. In reality this might not always be the right thing to do - this article is just meant as a starting point for readers to figure out what they need to do in their own use cases. Anyway, after my modifications, this is what I was left with:
<ControlTemplate x:Key="buttonTemplate" TargetType="{x:Type ButtonBase}">
<Microsoft_Windows_Themes:ButtonChrome x:Name="Chrome"
SnapsToDevicePixels="True"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}">
<ContentPresenter
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding Padding}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
RecognizesAccessKey="True"/>
</Microsoft_Windows_Themes:ButtonChrome>
</ControlTemplate>
Blend had automatically inserted a Template attribute for this control template into XAML, to make the particular button, which I had called the context menu on, work with this template. So I just had to run the application and there it was - two buttons still working in the same way as ever, and a third one without any of the animations and perfect green and lime colors depending on mouse state. Great!

You can download the source code for my test application here: WPFControlTemplating.zip (9016 bytes)
27/04/08
Impressions from the VBUG conference
VBUG did their Spring 2008 Conference last week. In the beginning, Andy was tired
, Chris was enthusiastic
and Tim was ...
... also there. Dave was hungry
and then he couldn't get in
. When he finally made it, he was the only one in Rich's session
and had to be revived
. Not quite Dave's event - he was scared of his computer
and ended up starting his own presentation early
.
Mark
, Gary
and Rich sang
, and everybody danced

In the end it was all as it should be.

Great event, guys!
DX takes all the awards plus Product of the Year
Developer Express have won each of the 8 (eight!!) categories we entered for this year's asp.netPRO Magazine Reader's Choice Awards. Wow!
The categories we entered were Best Add-in, Best Charting and Graphics Tool, Best Component Set, Best Grid, Best Navigation Suite, Best Online Editor, Best Printing/Reporting Tool and Best Scheduling/Calendar Tool. Our overall package DXperience was also named Product of the Year.
Look here for more info, the official thank-you to everybody and a few words from Julian.
25/04/08
Locked myself out of Vista? Help! - Solved
It appears I've managed to do a pretty stupid thing - personally I rather feel like Windows let me do a stupid thing, but that's probably a matter of perspective ;-)
Anyway, I was trying out some things with UAC, looking at the way different elevation prompts are displayed depending on whether or not the current user is an Administrators member or not, and so on. Previously I was working in what appears to be the default configuration, which my user account being a member of the local Administrators group and the Administrator account disabled and without password.
I activated the Administrator account and gave it a password. Then I removed my own account from the Administrators group and added Power Users instead. I played around with this setup and then decided to go back where I came from - only I made a mistake, I disabled the Administrator account first, before assigning the Administrators group back to my own account.
As a result, I can't currently find a way to get Administrator privileges on my system! I can't log in as Administrator because the account is disabled. For the same reason I can't use the "runas" command to run any admin tools. And elevation offers only my own account (pretty weird that - why does it offer to elevate into my own account if I'm not an Administrators member at all?), which allows me, after entering my password, to bring up Computer Management - but I still can't make changes to any account settings, obviously.
What do I do? I can see that I wasn't thinking enough before making those changes, but I'm still having a hard time believing that I managed to lock myself out completely, i.e. the only solution is a restore from backup. Any ideas, please?
Update: I found a solution on this very helpful page: http://www.jimmah.com/vista/Administration/locked_out_of_admin.aspx I feel quite lucky that the no. 1 option actually worked for me and I didn't have to use any of the other two - but at least there seems to be hope even if the situation is worse than mine turned out to be. In case you need that article and the above link should have stopped working, I have a local copy of it that I might be prepared to pass on in that event. Thanks to everybody who helped!
Not using the Secure Desktop?
Using Local Security Policy settings (specifically the one called "User Account Control: Switch to the secure desktop when prompting for elevation"
, I can modify Vista's behaviour when showing elevation prompts, so that the elevation dialog is simply shown as a normal window on the current desktop. I like this behaviour much better, but I'm wondering if there's any security related reason why the so-called secure desktop is actually more secure. If you know, please tell me!


