Silverlight and the Content Presenter in an iPhone-like button.

The Content Presenter was one of the more confusing things in Silverlight when I was first learning it because you can’t style it the way you would normally think to.

The place you run into the Content Presenter most often at first is when creating custom buttons. You design this great looking button in Blend, turn it into a button control and all of a sudden your text formatting is killed as your button’s text block is turned into a Content Presenter. Further, there is no way to get the formatting back.

The simple thing you have to keep in mind is that unlike HTML, Silverlight lets you put anything on a button as the content, not just text. So, in your button, you might have an image and text that changes depending upon the button context and those all may be inside a grid inside your button container.

In this example, I’ve created a simple, glossy iPhone-like button in Expression Blend that is set up to hold both an image and text.

First, I created a grid at about the size that my buttons will be, in this case, I made it 150 x 120 and set the Horizontal Alignment to Center and the Vertical Alignment to Top.

Next, I drew a Rectangle 90 x 90 square inside the grid and gave it round corners by setting the RadiusX and Y at 7 each. I set the fill to a black to dark gray gradient and copied the fill for the stroke only I reversed the direction to give it a little dimension. I set the Horizontal Alignment to Center and the Vertical Alignment to Top so the square will always stay aligned to the top of my grid (future button) and in the center of it.ex1

Next, I copied the Rectangle and pasted it right on top of the other Rectangle. I named this new copy “Glow”. I changed both the fill and stroke colors to white and added a blur Effect with a Radius of 13.ex2

Next, I selected both of the Rectangles and grouped them into a Canvas because I always want them to be a fixed size. By default, both the horizontal and vertical alignment will be set to stretch which is not what we want, so I changed the to Horizontal Alignment to Center and Vertical Alignment to Top. This is closer to what we want, but Blend has added in Margins for us and set the Width and Height to Auto which totally change the position of the canvas. Simply set the Height and Width both to 90 (the size of the squares we drew earlier) and set all the margins to 0. Now no matter what size the parent grid is, the squares will stay anchored to the top and centered in it.

It is time to add a nice little glossy shape to the top of the button. I used the pen tool for this and drew a shape inside the Canvas with 6 points and shown in my example below. (To give the rounded corners, you have to hold the Alt key and click on the point to pull it out and make the curve.) I filled the shape white at 40% opacity and made the final size of it 87 wide, 41 high and gave it a Left and Top both of 1.5 to allow a little of the black line around it to show.ex3

The last thing we’ll do is add a TextBlock to our Grid. Make sure the TextBlock is not inside the Canvas. There’s no need to change the default text of “TextBlock” because we’re only doing this in order to get the text settings set as styles inside the button control we’re about to create. (To my knowledge in Blend 3 there is no way to apply settings to an element and then automatically convert those to a style so it is important to do it here before converting your Grid to a Button control.)ex5a

I want the text to be 12 pt, colored White, horizontally aligned center and vertically aligned top.

Now we’re ready to turn our Grid into a button control by right-clicking on the Grid and choosing Make Into Control. Choose Button as the control type and give it a Name (Key). I named mine iPhoneButton.

You’ll notice that Blend has automatically your textblock into a ContentPresenter for you with the word “Button” on it. The content presenter is what will hold a grid that contains our icon and text when we’re finished. It looks like all the formatting we applied to the text is gone, but it isn’t. That formatting has been added to the control template and you’ll see it again when you go back to your MainPage.xaml. ex6

We will undoubtedly want to go in and set the different States for this button by setting the opacity of the glow to 0%  in the normal state and setting it to 100% on MouseOver, etc., but you can play with that on your own. For now, we’re done creating the basic button and ready to put a custom image and text on it inside the Content Presenter. Click the [Button] button to go back to your MainPage.xaml.ex7

Now add a Grid inside your button and give it two rows. (You’ll notice as soon as you add the grid inside the button, the text on your button disappears. This is because you’ve now told Blend that you’re going to use this new grid and its contents instead of just text.) I want the top row to be a fixed height of 90 so the image I add to the front of the button will always appear there. The second row should be set to Auto with MinHeight of 30. The width of the grid should have a MinWidth of 90 so it can never be smaller than the button image.ex8

We’re finally ready to add the text and image! Let’s start by adding another  TextBlock. This one will actually hold our button’s text. Select the Grid, then double-click the TextBlock icon to add a TextBlock to the Grid. My button is going to be a sound recorder, so my text will be “Sound Recorder.” You’ll need to set several properties of the TextBlock:

  • Margin – make sure it is Left:0, Right:0, Top:2, Bottom:0
  • Horizontal Alignment – Center
  • TextAlignment – Center
  • Row – 1
  • TextWrapping – Wrap

 

Lastly, we’re going to add an image icon to our Grid. I have a PNG image of a microphone that I’m using. I first double-click the image icon to insert an image at the default size. Then I navigate to it by setting the Source under Common Properties. My image is sized perfectly at 90x90 so I also set Stretch to None. And finally I updated the margins of the image to all zeros.ex9

At this point, our button is done, but there are several settings on the TextBlock that would be much better if they were in a style instead of inline on the TextBlock. I’ll do that now.

To begin, let’s get inside the button control we created. Right-click the Button in the Objects and Timeline panel. Then select Edit Template > Edit Current.

Open up the code view and scroll down to the style closing tag and create a new style tag right after it and call it iPhoneButtonText.ex10

Jump back to your MainPage.xaml by clicking the [Button] button at the top left of your design view and then select the TextBlock in the Objects and Timeline panel. Then go to Object menu > Edit Style > Apply Resource > choose iPhoneButtonText.

Now go to Object menu > Edit Style > Edit Current and apply all the same settings we applied above with the exception of the Row setting:

  • Margin – make sure it is Left:0, Right:0, Top:2, Bottom:0
  • Horizontal Alignment – Center
  • TextAlignment – Center
  • TextWrapping – Wrap

Go back to your MainPage.xaml by click the [TextBlock] button in the top left corner of your design view. Now in the XAML code, navigate to your TextBlock and select and delete all the settings you applied earlier so your code looks like the example.

Woala! You now have your button. To create another one just like it with a different image and text, simply copy the button from your Objects and Timeline panel and paste it and update the image and text. You will probably also want to put both buttons inside a StackPanel so they aren’t right on top of each other.ex13

I hope this helps clarify how the Content Presenter works along with giving you an idea how to create a button that looks like one on an iPhone.

No Comments

 

Leave a Comment