How to make your required fields NOT have a bold label using Extensions Made Easy… (By Kirk Brownfield)

I’ll be honest, I haven’t spent much time on Extensions Made Easy lately.  I have good excuses though: I’m writing a “getting started with LightSwitch eBook” (link on the way), I founded a “LightSwitch exclusive startup“, I’m writing about LightSwitch for MSDN magazine, I’m working on my next extension called “LightSwitch Power Productivity Studio“, but mainly because I consider EME in its current form to be complete, in the way that it can do all that I intended it to do, all that I felt was missing/not easy enough in the LightSwitch RTM, and maybe even a bit more, like deep linking in a LightSwitch application

Ironically, just when I stopped writing about EME, other people started discovering the power behind the lightweight extension, and have been happily sharing…

Kirk recently mailed me with another question: “how can one make the required fields NOT have a bold label”?  For those of you that haven’t noticed, when you use the LightSwitch default shell & theme, required properties will have a bold label like in the screenshot below:

Adding Data

By the way, my apologies on the crappy graphics in my MSDN screenshots.  I turned ClearType off on my machine, as requested in the MSDN Magazine writer guidelines.  If you take a screenshot with ClearType on, it looks crappy on-screen but much better when printed.  Bad move for the MSDN Magazine web edition, obviously…

Before I could even answer his mail, a second mail came in from Kirk with the response to his own question.  Kirk later happily granted me the privilege of posting me the answer…

Firstly, set up your LightSwitch project so you can create a theme inside your LightSwitch application.  (Everyone hates the “Extension” debugging mess…)  A sample of how to do this can be found here.

Next up, since you want to do some control styling, not just mess with the colors and the fonts a bit, you need to export a new control style to the LightSwitch framework.  I wrote about this earlier, and Keith posted the VB.Net version!

The question of course is what control you need to style, and for this you need to understand a bit about LightSwitch’s Meta-data driven MVVM implementation (MV3).  Unfortunately, the joke is on you here, because there’s little to no documentation about the subject (hold your breath for exactly 7 days and there will be… 🙂) The very short preview: the LightSwitch default theme & shell provide Views that binds to ViewModelMetaData, which in turn binds to your ViewModels and Models.  The XAML (View) part that shows the label, is called an AttachedLabelPresenter.

Kirk actually found the control to style, by looking at the source code of the LightSwitch Metro Theme, reposted here for your convenience…

<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:framework="clr-namespace:Microsoft.LightSwitch.Presentation.Framework;assembly=Microsoft.LightSwitch.Client"
xmlns:internalstyles="clr-namespace:Microsoft.LightSwitch.Presentation.Framework.Styles.Internal;assembly=Microsoft.LightSwitch.Client"
xmlns:internalconverters="clr-namespace:Microsoft.LightSwitch.Presentation.Framework.Converters.Internal;assembly=Microsoft.LightSwitch.Client"
xmlns:converters="clr-namespace:MetroThemeExtension.Presentation.Converters"
xmlns:windows="clr-namespace:System.Windows;assembly=System.Windows">

<internalstyles:RequiredFontStyleFontWeightConverter x:Key="RequiredFontStyleFontWeightConverter"/>
<converters:TextToUpperConverter x:Key="ToUpperCaseConverter"/>

<!-- The attached label presenter is the control that places labels next to controls. It is restyled here to put the label-->
text in upper case. The style is applied using implicit styles, so do not give the style a key -->
<Style TargetType="framework:AttachedLabelPresenter">
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="framework:AttachedLabelPresenter">
<TextBlock x:Name="TextBlock"
Text="{Binding DisplayNameWithPunctuation, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource ToUpperCaseConverter}}"
VerticalAlignment="Top"
HorizontalAlignment="Left"
TextWrapping="Wrap"
FontWeight="{Binding Converter={StaticResource RequiredFontStyleFontWeightConverter}}">
<windows:VisualStateManager.VisualStateGroups>
<windows:VisualStateGroup x:Name="AttachedLabelPositionStates">
<windows:VisualState x:Name="None"/>
<windows:VisualState x:Name="LeftAligned">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextBlock" Storyboard.TargetProperty="Margin" Duration="0">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<windows:Thickness>0,3,5,0</windows:Thickness>
<!--DiscreteObjectKeyFrame.Value>
<!--DiscreteObjectKeyFrame>
<!--ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextBlock" Storyboard.TargetProperty="HorizontalAlignment" Duration="0">
<DiscreteObjectKeyFrame KeyTime="0" Value="Left"/>
<!--ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextBlock" Storyboard.TargetProperty="VerticalAlignment" Duration="0">
<DiscreteObjectKeyFrame KeyTime="0" Value="Top"/>
<!--ObjectAnimationUsingKeyFrames>
</Storyboard>
VisualState>
<windows:VisualState x:Name="RightAligned" >
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextBlock" Storyboard.TargetProperty="Margin" Duration="0">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<windows:Thickness>0,3,5,0</windows:Thickness>
<!--DiscreteObjectKeyFrame.Value>
<!--DiscreteObjectKeyFrame>
<!--ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextBlock" Storyboard.TargetProperty="HorizontalAlignment" Duration="0">
<DiscreteObjectKeyFrame KeyTime="0" Value="Right"/>
<!--ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextBlock" Storyboard.TargetProperty="VerticalAlignment" Duration="0">
<DiscreteObjectKeyFrame KeyTime="0" Value="Top"/>
<!--ObjectAnimationUsingKeyFrames>
</Storyboard>
VisualState>
<windows:VisualState x:Name="Top" >
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextBlock" Storyboard.TargetProperty="Margin" Duration="0">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<windows:Thickness>0,0,0,5</windows:Thickness>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextBlock" Storyboard.TargetProperty="HorizontalAlignment" Duration="0">
<DiscreteObjectKeyFrame KeyTime="0" Value="Left"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextBlock" Storyboard.TargetProperty="VerticalAlignment" Duration="0">
<DiscreteObjectKeyFrame KeyTime="0" Value="Bottom"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</windows:VisualState>
<windows:VisualState x:Name="Bottom">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextBlock" Storyboard.TargetProperty="Margin" Duration="0">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<windows:Thickness>0,5,0,0</windows:Thickness>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextBlock" Storyboard.TargetProperty="HorizontalAlignment" Duration="0">
<DiscreteObjectKeyFrame KeyTime="0" Value="Left"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextBlock" Storyboard.TargetProperty="VerticalAlignment" Duration="0">
<DiscreteObjectKeyFrame KeyTime="0" Value="Top"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</windows:VisualState>
</windows:VisualStateGroup>
</windows:VisualStateManager.VisualStateGroups>

</TextBlock>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

The interesting bits are all near the top.  First thing to notice, is the comment:

<!-- The attached label presenter is the control that places labels next to controls. It is restyled here to put the label
text in upper case. The style is applied using implicit styles, so do not give the style a key -->

Ok, so that confirms what we thought: the AttachedLabelPresenter is the control that places labels next to control.  Good naming (Nomen est Omen)!

Also, the Metro theme puts all Labels in upper case, and for this exercise, we only wanted to get rid of the bold.  Let’s revert that by getting rid of the ToUpperCaseConverter a couple of lines below that comment line:

  Text="{Binding DisplayNameWithPunctuation, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource ToUpperCaseConverter}}"

Nice, following all the links posted in this blog post, and removing that converter, we have a LightSwitch application where the way labels are represented, looks exactly like the standard theme, but is completely under our control.  One thing we can now accomplish, is to get rid of the functionality where required fields have a bold label.  This is accomplished by getting rid of the following line completely (not just the converter!):

 FontWeight="{Binding Converter={StaticResource RequiredFontStyleFontWeightConverter}}">

Awesomesauce, another mission accomplished!

As you might have suspected, I wrote this blog post myself, but titled it “By Kirk Brownfield” since he basically came up with the solution before I could even read his first mail. 🙂  He promised me to send information about some other LightSwitch hacking adventures he’s been undertaking, I’m personally looking forward to reading about it, and sharing it with you!

Keep rocking LS!

Advertisements

5 thoughts on “How to make your required fields NOT have a bold label using Extensions Made Easy… (By Kirk Brownfield)

  1. Pingback: Windows Azure and Cloud Computing Posts for 4/6/2012+ - Windows Azure Blog

  2. Pingback: Windows Azure and Cloud Computing Posts for 4/28/2012+ - Windows Azure Blog

  3. Pingback: Beth Massi的中文博客

  4. Hi Jan,
    first i want to say that your tipps are very helpful for me! Thanks for that! Great Work!

    I have a question about the “RequiredFontStyleFontWeightConverter”…
    Do you know how this converter works? I would love to change the Bold Font into an Italic Font or set the FontColor to Red or something else, but i dont know how the RequiredFiledConverter (in my words^) get the Metadata to decide if it is a required Field or not.

    Thank you for an Answer (if you have one^)

    Thomas

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s