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:
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,
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)
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 |
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.
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)
Return to the event handler, remove the alert box, and start setting properties!
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.