Entries Tagged 'Tip of the Day' ↓

Tips of the Day: Setting properties in custom controls in 1.0

Got a nice international email today that said in part...

...things get more interesting it is a common scenario to write custom controls....I need to specify the parameters in code behind. Can I create custom xaml tags which are connected to the code-behind? ... I mean something like...

   <myButton width="100" height="20" Text="Hello World" />

Is this possibly for 2.0?

Assuming I understand this, it is no problem and you don't have to wait for 2.0. Fire up Visual Studio, create a new 1.0 application, clean out the XAML and the code behind and add this crude custom button:

CustomButtonXAML

In this XAML file we create a custom button that is composed of a canvas enclosing a rectangle (the shape of the button) and a TextBlock (to hold the text of the button).  Our initial settings make for a somewhat simple button,

FirstButton

Our goal is to set some of the properties of this button from within the Javascript. This we can do.

The first step is to get a reference to the Button and to its component parts, from within the JavaScript. We'll do that by using the FindName method of the content subpart of the Silverlight control that is passed as a parameter into the handleLoad event handler, fired when the Silverlight control is first loaded. 

In order to remember the names, I'll split the visual studio editor into two panes (a handy option) so that I can see the code and the code-behind at the same time. (There's a lot to go over in the next figure, we'll take it one piece at a time)

Step1Code

You can see the one to one relationship between the names of the Button and its parts in the XAML and the string passed to FindName in the JavaScript (highlighted in yellow).

(Remember that the first parameter passed to handleLoad, plugIn, is a reference to the Silverlight control itself. This reference can also be obtained by calling GetHost() on any Silverlight object.)

Once we have a reference to all three objects, we set up an event handler for the button. In yesterday's Tip of the Day I hooked up an event handler in the XAML file, and that could have been done here, but I prefer to have the event handlers "wired up" in  the code behind because that is where they are implemented, and that allows me to encapsulate the handler and its relationship to the object in one place (if I change the handler's name, for instance, I only have to update one file).

Note that this code behind is using the pseudo-object oriented form of Javascript. If this is new to you, you'll want a pretty modern book on JavaScript such as

JavaScript The Definitive Guide
by David Flanagan

Read more about this title...

The key thing to remember is that if you name a variable with "this" it is available to all the "member methods" but if you name it with var it is local to the method in which you name it. The job of "Silverlight.createDelegate" (a method provided by Visual Studio) is to ensure that the method name handleMouseUp is resolved properly, as indicated by the arrow.

The net effect is that when the user clicks on the button, the handleMouseUp event will be called. (Caution, there is no "fill" for the rectangle, and so clicking in the rectangle will have no effect, unless you click on the text!) As noted yesterday, the default fill is "null" and will not respond to events.

I've put a test alert message into the event handler to make sure it is working; when you click on the text in the button; the alert box comes up; and that assures us of two things: FindName is in fact returning a reference to the button (or else wiring up the event handler would not have been possible) and the event handler is working.

EventHandlerWorking

Since we now have references to the button and its parts, we have only to make them member variables (so that we can access them from the event handler, which is a member method, and then we can set whatever properties we want; even properties not yet declared in the XAML.

The first thing to do is to change the var's in handleLoad to this (making btn, btnRect and btnText member variables)

Using this

Return to the event handler, remove the alert box, and start setting properties!

SetPropertiesInCode

In the event handler we set properties on the objects within the button (setting the color weight and text of the text block, and the width and height of the rectangle, and then we reposition the button itself.

The result is that when we click on the button, it is redrawn as if these properties had been injected into the object.

AfterClicking

Technorati

Silverlight Tip of the Day Gadget Version 2

Kelly White has updated the Silverlight Tip of the Day Vista Gadget  and added the ability to set the update frequency; so that you are sure to get the Tip of the Day just after it is posted (1 pm GMT -5).

 

image

Did You Know… How to create XAML objects in Javascript?

I have had a very strong positive reaction to focusing on the Javascript in code behind for Silverlight 1.0, and so will devote not only today's Tip of the Day to a bit more on the topic, but will make sure that I do so on a frequent basis for a while.

Before I start: a small house keeping measure: the convention of starting every Tip of the Day with "Did You Know" is getting old. Thus, starting with the very next one it will be replaced with Tip Of The Day:

A reader (let's call this one Joe) writes,

What I've had trouble understanding is a small bit of code....

 Now, I have to say that the best way to get this kind of question answered is to post it to our forums; that way a lot more people see it a lot more quickly; but since you did write to me, I'll feel free to use it as grist for the Tip of the Day mill...

sender.fill = createLinearGradientBrush(sender.getHost(), sender);

function createLinearGradientBrush(plugin)
{
    var xamlFragment = '<RadialGradientBrush>';
    xamlFragment += '<GradientStop Color="LimeGreen" Offset="0.0" />';
    xamlFragment += '<GradientStop Color="Green" Offset="1.0" />';
    xamlFragment += '</RadialGradientBrush>';

    return plugin.content.createFromXaml(xamlFragment, false);
}

I understand 'what' it is doing and i understand 'why' it is doing it, but I don't know 'how'... I found the code to do it on a forum return plugin.content.createFromXaml(xamlFragment, false)

It isn't surprising you're baffled by this code as it is pretty advanced and it starts in the middle.

sender.fill = createLinearGradientBrush(sender.getHost(), sender);

What can we see or guess?

1. the purpose of this line is to fill sender with a LinearGradientBrush.

2.  the LinearGradientBrush will be created by the function createLinearGradientBrush.

3. The function createLinearGradientBrush takes two parameters: the getHost() method of the sender and the sender itself

4. The function crateLinearGradientBrush returns a Brush (and it better be a LinearGradientBrush or someone should be hurt) that be assigned to the sender's fill property.

What is sender?  It's not a big leap to assume sender is a shape.

How did we get here? We assume "here" is the middle of some function, and sender was a parameter to that function.

To do this right, I think we want to create a simple application that might get us to just this point.  So I'll fire up Visual Studio, strip out the starter application and put the following into Scene.xaml:

image

This creates two shapes, both of which respond to the MouseLeftButtonUp by calling an event handler method named onMouseUp, which we will expect to find in the code-behind file.

Note that you must provide a fill or if you click inside the shapes the event handlers will not fire! If you want the boxes to appear unfilled, you can use Fill="Transparent" as I've done here, but if you leave the fill out, it will default to null and clicking inside the shape will have no effect.

Here's the event handler:

image

  Presumably the event handler has work to do or there is more than one event handler. In any case, the programmer has decided to factor out the work of dynamically creating the Linear Gradient Brush. We now know what sender is; it is whatever shape we clicked on (in this case) but of course you can imagine other programs in which sender will be a shape retrieved by other means (picked from a menu in a drawing program?)

We saw CreateLinearGradientBrush in the original code above, but it is needlessly complex and we can simplify both the call to it and its own logic. Let's send just the sender, and encapsulate within createLinearGradientBrush the work of getting the SilverligthHost. First, we change the call,

image

Notice that we no longer ask the calling method to know that we need to retrieve the Silverlight control by calling GetHost; we just pass along the sender (the shape). Next, we create the brush by creating the XAML as a string and then asking the Silverlight control to create the brush we need from that string,

image

The top half of the method creates a string that replicates exactly how you would create the brush in XAML. To make it clear, I've put in the spacing I'd use in a XMAL file. Though this is not required, I believe it is good coding practice and far easier to maintain.

The bottom three lines (above the comment) act as follows;

var SilverligthHost = sender.GetHost()

GetHost() can be called by any Silverlight object as explained in this article and in the Silverlight 1.0 Help Files (an often overlooked and quite useful resource

image

Now, I admit it takes a while to translate some of that back into English, but what it tells you is that you can call GetHost on any Silverlight object (e.g., sender) and get back the plug-in (that is, the Silverlight control). Handy.

The second line is the key to this entire exercise

var brush = silverlightHost.content.createFromXAML(xamlFragment, false);

To understand this, you need to know that there is a method, createFromXAML that takes a string of XAML and returns a XAML object. That is explained in some detail in this video.

In addition it is helpful to know that the Silverlight control has sub-objects, one of which is named content, as explained in

this article.

You also want to know that createFromXAML takes two arguments, the second of which is used to create a unique namespace for the objects it creates, as explained both in the video and in the Silverlight documentation

image

I've commented out the line that is actually the way most programmers (or at least most of us who grew up in the C/Unix world where terseness is prized despite the fact that it makes for harder to maintain or understand code, and we should all be slapped silly)

return sender.GetHost().content.createFromXaml(xamlFragment, false);

I include it here not because I think it is the right way to do it, but because you'll see it and will want to know how to read it; the answer is "inside out" --

"Return from this method the result of calling GetHost on the sender object and then accessing the content sub-object on the returned Silverlight control so that you can call createFromXAML and pass in the text fragment that represents the object you are creating plus the boolean value false signifying that you do not want to protect namespaces." 

Easy.

So; when you bring up the application, the objects look like they are unfilled (their fill is transparent, but if you click on them, the event handler is called, which in turn calls createLinearGradientBrush passing in a reference to whichever object was clicked on. That object accesses the Silverlight control and asks it to instantiate a brush, which it uses to fill itself with color,

image

Hope that helps.

-j

image

Did You Know That… The Code Behind is Just… Code?

A very insightful reader sent me email that I'm going to respond to here. To protect his identity let's call him Bob. I'm going to excerpt Bob's  email and rephrase a bit so that this becomes a more general discussion.

I find that a lot of Webcasts and books about Silverlight spend most of their time explaining XAML or using Expression tools in  great depth, yet whenever its time to examine the code,  the presenter tends to speed up and glide over the actual JavaScript.

...I noticed in your last Webcast you made the comment that you would be spending most of the hour talking code, ...however, once again lots of time was spent on XAML shapes and gradiant fills, but when it came to the actual code behind side, that was rapidly glossed over....I get the feeling that a lot of people are really enthusiastic about Silverlight, however they are perhaps lacking the "JavaScript 101 for Silverlight" that is needed to follow along with most of the webcasts.

Bob went on to observe that switching rapidly between Visual Studio and IE in Live Meeting is not a great tactic (one I will solve next time by setting up my desktop properly, and then sharing the entire desktop to avoid all the switching).

I think Bob's key point is exactly right, and while I can't answer for anyone else, I can tell you why this happens in my presentations; though now that it has been pointed out to me, I have the opportunity to make a conscious decision to change.

First, in a course named "Getting started with..." or "from scratch" there seems to be an imperative to spend a good bit of time showing where the resources are. That can be very time consuming. It might be better to point folks to our web site and to my How Do I Get Started? web post and let it go at that.

The second reason is more pressing, and it is that Silverlight 1.0 has  always been about XAML and code-behind, but the code behind has always been, if I'm going to be totally honest, "well, it's JavaScript right now, but it should be C# and it will be C#, so let's just show how the logic works without dwelling on the implementation which is, after all, not object oriented or the way we'll do things in the long run."

Now, there are a couple real problems with that attitude. 

First, Silverlight 2 won't be released (RTM) for quite a while. We'll be in Beta with a Go-Live license very soon, but it won't be replacing 1.0 until it is released. We've not announced a release date. Which means 1.0 isn't going away next week. So glossing over coding in 1.0 is a mistake.

Second, you can still code in JavaScript if you want to in 2.0 and some folks will most certainly want to (Calling all AJAX programmers).

Most important, if you are going to teach Silverlight From Scratch, then you can't gloss over the implementation of the code behind (read, in most cases, the event handlers) because you run the risk (read certainty) of leaving your users hopelessly confused and frustrated.  It all becomes a hand-wave, and even worse, the critical distinction between the XAML file and its code-behind becomes even more confusing. So I must stop this madness.

SceneXAMLAlone

Hooking Up the Event Handlers

In the figure, Scene.xaml declares a Canvas and declares that the Canvas (which will hold a diamond) will respond to three known events: MouseLeftButtonDown, MouseLeftButtonUp, and MouseMove. The three functions that will serve as event handlers are named: OnMouseDown, OnMouseUp and OnMouseMove respectively.  

These Event handlers do not exist in the XAML file. They exist in the code-behind file: Scene.xaml.js

SceneXAMLSideBySide

Note that the programmer could have named the functions Moe Larry and Curly; as long as the names match in the XAML declaration and the code-behind file, all is good.

This is where I wave my hands at the JavaScript and move on. So, why? 

JavaScript isn't that hard, though I will tell you that you'll run into two basic approaches when you review example code here and elsewhere. One, as shown here is the older style of independent functions and global variables. Perfectly respectable. The other, more object-oriented-ish creates kinda-sorta-member methods with kinda-sorta-member variables. That looks more like this:

OOJava

In this example (which is what Visual Studio 2008 creates as a sample for you when you make a new Silverlight app) the prototype acts as a "class" and each function acts as a "method."  Any variable prepended with "this" is a member, declared with var is local.  In this style it is more common to wire up even handlers using addEventListener in the code rather than in the XAML.  More about this approach here.

It's Just Code

Returning to our story, already in progress, we had three event handlers: onMouseDown, onMouseMove and onMouseUp.

Each of these is just JavaScript, the kind you can find incredibly well described here in David Flanagan's book, BLOCKED SCRIPT The Definitive Guide:

JavaScript The Definitive Guide
by David Flanagan

Read more about this title...

The code behind begins by declaring three variables that will be used by the event handlers.  The job of OnMouseDown is to store the location of the mouse by calling GetPosition on the mouseEventArgs argument passed in with the syntax shown. We then set trackingMouseMove to true (to signal to OnMouseMove that we are tracking a moving object) and we tell the sender (the object that caused the event) to "capture" the mouse, so that if we move off that object we'll still get mouse move events until the user lets the mouse button up.

OnMouseDown

As the user moves the mouse we check to see if we are tracking. If so, we continually recompute the new position of the mouse and then recompute the new position of the object, setting its Canvas.Left and Canvas.Top properties and then resetting the new values for the global  beginX and beginY

OnMouseMove

Finally, when the user lets the left mouse button up, we stop tracking and we tell the object to "uncapture" the mouse.

OnMouseUp

Not so bad.  Other than the manipulation of currentX vs BeginX in MouseMove the logic is fairly intuitive, and the syntax should feel pretty familiar to anyone who has worked in the C/Java family of languages.

All of this is walked through in great detail in this video and its example code.

Accessing XMAL defined objects in Code

Since I'm up late, and on a roll, let me mention one more bit about the relationship between XAML and the code behind; and that is how you access an object declared in XAML from your Javascript. The key to making this work is

  1. Name the object in XAML
  2. Use FindName to assign the object to a variable in the code behind

The XAML file:

NamingObjects

Referring to these objects in code can be done in a number of ways, but it typically involves calling FindName, passing in the name used in the XAML as a string, and returning the reference to an object in the code:

UsingFindName

JavaScript

Note that plugIn is the Silverlight Control which is passed in as the first parameter to hanldeLoad.  If you are not in handleLoad you can always get a reference to the Silverlight control by calling GetHost() as explained here.

Of course there's more to say, but this is a start on addressing the well made point that understanding the Javascript is an essential point in understanding how the Silverlight application works its magic.

Much thanks to "Bob"

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Did You Know.. There is now a Silverlight TOD Gadget?

Thanks to the work of Kelly White you can now have the Silverlight Tip of the Day appear in your Vista Sidebar as a Gadget

.

Kelly has graciously made the script available here. Just unzip the file and place it in your gadgets folder, all explained in detail in this article.

Once the gadget is in your dock;you can view the current tip or click on View All Tips or click the Silverlight logo to go to the Silverlight site. Finally, if you click on the story, the "fly-out" shows you more in place, and offers to take you to the full article:

You can pull the gadget out of the dock, allowing it to float free. Settings allow for a larger or smaller size when undocked.  

 

My sincere thanks to Kelly and to whoever wrote the Visual Studio gadget

Did You Know That… You can find the best Silverlight blog entries of the day on Twitter?

Adam Kinney has worked with Dave Campbell to feed Silverlight Cream to Twitter.

SilverlightNewsTwitter

 

You can subscribe here. In addition, Adam has created a script for placing this news into his (or your!) web log and formatting it.

SLNews

You can download the script here, along and read full details on how to use it on your own site as well. Once in place, its all automagic.

More on this to come!

 

Technorati Profile

Tip of the day is moving its release schedule

 

1pm

The Tip of The Day is moving its release schedule to be more predictable....

Starting today, the Tip of the Day will be published at 1PM Eastern (GMT -5) seven days a week (except when it isn't).

I will work hard that the majority of the Tips of the Day per week contain code and are substantive mini-lessons, while other Tips are about using the tools well, best practices and lessons learned.

In addition to the Tip of the Day, I will continue to post ad-hoc entries as information arises, events happen, or the mood strikes.

If you have suggestions for Tips of the Day (especially if your suggestions come with small example code) please send them my way; if I use your Tip of the Day I'll be happy to credit you (complete with a link to your blog or web site).

Thanks.

 

-jesse

 

Technorati Profile

Tip Of The Day… Did You Know How To Format Your XAML?

A reader wrote and asked: "A quick question: how did you set your VS to format the XAML in the way that it does?"

Here's how to do it:

In Visual Studio click on Tools -> Options

Tools-Options

When the Options window opens, make sure Show All Settings is clicked, and then click on the triangle next to Text Editor to expand that section

OptionsWindow

Scroll down to XAML and expand it. Click on each sub-category (General, Tabs, and expand Formatting) to set the options for formatting XAML the way you want. When you are done click OK.

XAML Options

Once all of your options are set the way you want them, you may want to back up your options by selecting Tools -> Import and Export Settings (a topic for another Tip of the Day)

Technorati Profile