Dependency Properties – Background for Custom Controls

In  a previous post I began talking about Custom Controls, and I will continue that discussion over the next few days and weeks even as I start producing videos on the topic.

It turns out that the more you look at Custom Controls, the deeper you get into the Silverlight UI architecture, and there is much to see.

As an example of this phenomenon, in writing about Custom Controls, you quickly realize that sooner or later you must describe and explain the Dependency Properties System in Silverlight. This brings great joy to my heart, because it is one of the more interesting and one of the less discussed aspects of Silverlight programming

So this evening I'm going to leap ahead (a bit out of order) and introduce this system, though by no means cover it in depth in one blog post. 

(Written late Tuesday, posted early Wednesday)

Understanding Our Roots

Traditional C# classes consist of

  • Methods
  • Events
  • Member Variables
  • Properties

You can easily view these in the Object Browser in Visual Studio (all but the member variables, which are almost always marked private and not shown).

ObjectBrowserUIButtonNoCircles

[Note, image cut down to save space]

C++  did not have properties (nor running water, nor electricity). Back in those dark days, if we wanted to provide access to the value of a member variable, we created methods to do so.

Thus, you ended up with funny looking code like this:

overallApproval = jesse.GetApprovalAverage() + tim.GetApprovalAverage();

Rather than the more natural,

overallApproval = jesse.Approval + tim.Approval;

Properties were brilliant. They looked to the class author just like methods, but they looked to the class consumer just like variables.

This was crucial. The class author was free to continue to obtain the actual value from backing variables or anywhere else:

   1: private double approval = .4;
   2: public double Approval
   3: {
   4:    get
   5:    {
   6:       if ( currentViewer.ID == "ScottGu" )
   7:          return .9;
   8:       else
   9:          return approval;
  10:    }
  11: }

In practical experience, most properties are backed by member variables, though that is by no means universal – some are backed by values in persistent storage, and some are computed dynamically. But some very large percentage are backed by member variables, which is why Auto-implemented properties were invented (and they are also brilliant). Prior to C# 3.0 my code was peppered with annoying properties that looked like this:

   1: private int myMember;
   2: public int MyProperty
   3: {
   4:    get { return myMember; }
   5:    set { myMember = value; }
   6: }
   7:  

Auto-implemented properties let me write

public int MyProperty { get; set; }

which C# 3.0 interpreted as an exact equivalent – the IL code produced is identical. 

Yes, there are a few restrictions, the only significant one is that I can't do anything in the getter or setter except get and set the value. If I need to do anything else, it's back to the full getter and setter – leaving me no worse off than before. 

So What's Wrong With Properties?

As terrific as properties are, they just don't cut it in a declarative, animated, data-bound world. Think about the property that describes the position of an object that is being animated; that value is changing very rapidly, in real time, possibly in response to conditions that cannot be anticipated at compile time. Properties just were not invented for that.

A Hidden World Underneath Your Feet

It turns out that WPF and Silverlight have extended properties in a way that you might never have suspected, and really never need be aware of until and unless you decide to create your own controls.

In fact, it is entirely possible to write completely robust Silverlight applications for quite a long while without knowing that underneath the surface lies an entirely new and very powerful system, humming gently and doing its work.

When you do learn of it, however, the revelation is not unlike the moment when you learned that beneath the streets of your city was a gargantuan system of pipes and wires that made up the city’s power and water grid. A bit unsettling at first, and then totally fascinating (at least it was to me, but I'm a nerd). 

In brief:  the Dependency Properties system allows Silverlight to determine the value of a property not from a value at compile time, but rather dynamically from a number of different inputs: specifically from

  • Resources

allowing you to write code that looks like this

   1: <UserControl.Resource>
   2:   <SoldColorBrush x:Key="ABrushFromAResource" Color=Red" />
   3: </UserControl.Resource>

and then later in your Xaml file use that code like this

   1: <Button "{StaticResource ABrushFromAResource theBrush}" width="100"
   2: height="100" />

  • DataBinding

By using Dependency Properties the value of the property can be set based on late binding to a data source.

  • Animation

Animation makes the highest demands on a property; requiring that its value change quickly over short periods of time. It is animation that makes crystal clear that the Dependency property system had  to be build, that the extant Reflection system could never be sufficiently performant

Dependency Property Precedence

One issue that quickly arises is this: if a property might be affected by multiple sources (the template says I should be red, but the data binding says I should be blue, but the animation just turned me to violet" – who wins?

To solve this problem, a non-negotiable (and quite logical) order of precedence was established. Like all such things, there is some complexity to handle border cases, but the essence of it is straight forward, and just what most of us would do given enough time (say 5 years) to think it through:

  • Animation always wins
  • IN the absence of animation, local values (values on the object itself) take precedence
  • If neither of the above apply, use the templated value
  • If none of the above apply use the style
  • Failing all of that, use the default value

But Wait, There's More…

There is always more to say, but this general overview of the Dependency Property system will serve as a solid foundation for our next exploration of custom controls. We'll return to the Dependency Properties system in more depth as we go.

 

Thanks!

 

-jesse

Posted in z Silverlight Archives | Comments Off on Dependency Properties – Background for Custom Controls

Ok, so tell me….

 

 

iStock_SurveyXSmall

At the suggestion of a reader, I've created a survey to find out what topics are most important to you.

It won't be 100% scientific, and of course I can't guarantee instant responsiveness, but I really am interested in what you'd like to see more of, learn about, hear about and have us focus on. So if you have a moment, please do take the (very short) survey.

Thanks!

-jesse

Posted in z Silverlight Archives | Comments Off on Ok, so tell me….

On Meeting the Needs of Every User

I received a public flame recently that I've become complacent in this job and am not doing the hard work of meeting the needs of those who want to go beyond the basics.  While it is tempting to talk about 16 hour days, missed weekends with my family, 50 videos, 300 blog posts and yadda yadda,  no one rightly cares about all that. What is cared about is "How much is Microsoft committed to helping me meeting my needs to get my  work done?"

Fair enough.  You don't take this job without understanding that there will come a time in the life-cycle when you're going to have to simultaneously meet the needs of people who are just getting started, folks who are intermediate in their understanding and those who need advanced material.

My personal assessment is that we're getting better at meeting the needs of the first two groups, but we don't yet have a lot of material for the last group, though as we've said, we're working on that.  The fact that we don't isn't really all that surprising – the product is relatively new, so are we, and everything is a moving target. But so what? If it were easy no one would need us.

the dancerThus, I don't have much to offer you yet, except an open acknowledgement that you've been heard, that what you say has merit, and that we're working on it.

There is an old story: a man meets a woman in a bar. They start to dance. He says "I'm only here for the weekend." She says "I'm dancing as fast as I can."

Stay tuned.

 

-jesse

Posted in z Silverlight Archives | Comments Off on On Meeting the Needs of Every User

Throwing Together An Application

Creating a Quick and Dirty App in Silverlight

 There comes a point, usually within 3-6 months after I commit to a new technology, when it becomes my platform of choice for throwing together quick applications… when I just find it easier to think in terms of the new technology than one of the old.

I also find that it usually comes in two stages: first, it is easier to use the new technology for small illustrative programs, then it is easier for creating quick and dirty utilities, apps, whatever it is I need to get done.

Today I had my first such opportunity when my daughter needed a stop watch for her Mac. Rather than looking for one (I'm sure there are hundreds) it just seemed easier to throw it together using Silverlight. 

Total development time, including thinking, napkin design, layout in Blend, coding, debugging, and testing on Windows and Mac… 20 minutes. Not too bad.

Rachel timer on mac

One of the things I enjoyed about this project was that it reminded me how very cross-platform Silverlight really is. This was, of course, written and tested on Vista, and yet, when I ran it on the Mac, it looked just like a Mac program should look. I had to go back and run it on Vista to remind myself that it started out life looking like a Vista program!

Rachel timer on vista

That was kind of neat.

Start In Expression

Creating the program itself was painfully simple. I started out in Blend, and created a grid, then filled in the heading with a Textblock, added a row with three buttons, then four more text blocks. 

TimerProgramInBlend

 

Once you get over the idea that Blend "really isn't for our kind" – it is a gas. I make a point of using Comic Sans MS as I'm told it is a clear signal to any designer that I don't have a clue what I'm doing design-wise; it's the design equivalent of wearing a button that says "what is an object, anyway?"

…Proceed To Visual Studio

With the UI in place, and all the little UI objects named, I flipped over to Visual Studio to write the code to support the timer.

I won't walk you through every detail (unless you need the sleep) but briefly… I gave each button its own event handler (I'd probably consolidate this to a single handler if the program were any larger).  Taking them easy to harder…

The Pause button calls Pause( true) which disables the Pause button (so you can't press it twice), and sets a paused flag.

The Stop button disables both the pause and the stop button and sets the started flag to false and turns off the timer (timer is explained in just a moment). The net effect is to stop everything but leave the current elapsed time showing.

The start button has all the fun. It enables the Pause button and sets the startTime member variable to now (we keep track of two times, the time since the start button was first pressed, and the time since it was most recently pressed). It then calls a helper method named Start.

The helper method checks to see if this is the first time the start button has been pressed. If so it records the time (we use this for the total elapsed time) and enables the stop button and we reset the elapsed time and start up the timer.

The timer uses a System.Windows.ThreadingDispatcherTimer as explained here.

The start code (combined and cut down) looks like this:

   1: void startButton_Click( object sender, RoutedEventArgs e )
   2: {
   3:    // un-pause
   4:    Pause( false );  
   5:    // start a new elapsed time
   6:    startTime = DateTime.Now;  
   7:    Start();
   8: }
   9:  
  10: private void Start()
  11: {
  12:    // if first time started
  13:    if ( started == false )
  14:    {
  15:       started = true;
  16:       stopButton.IsEnabled = true;
  17:       firstStartTime = startTime;
  18:       ResetElapsed();
  19:       StartTimer();
  20:    }
  21: }
  22:  
  23: public void StartTimer()
  24: {
  25:     // set up timer with event handler
  26:     timer = new System.Windows.Threading.DispatcherTimer();
  27:     timer.Interval = new TimeSpan(0, 0, 0, 0, 100); 
  28:     timer.Tick += new EventHandler(TickTock);
  29:     timer.Start();
  30: }
  31:  
  32:  
  33: // event handler for timer (10 times/second)
  34: public void TickTock( object o, EventArgs sender )
  35: {
  36:    if ( !started )
  37:       return;
  38:  
  39:    totalElapsed = DateTime.Now - firstStartTime;
  40:    TimeSpan elapsed = notPausedElapsed;
  41:  
  42:    if ( !paused )
  43:    {
  44:       TimeSpan temp = DateTime.Now - startTime;
  45:       elapsed += temp;
  46:    }
  47:  
  48:    // display paused and total time
  49:    time.Text = elapsed.Hours.ToString() + ":" + elapsed.Minutes.ToString() + ":" + elapsed.Seconds.ToString();
  50:    totalTime.Text = totalElapsed.Hours.ToString() + ":" + totalElapsed.Minutes.ToString() + ":" + totalElapsed.Seconds.ToString();
  51: }

As you can see, no rocket-science; and very familiar; we've all done it a zillion times. But it works, and it works on the client, cross-browser and cross-platform. You can stream it or you can just drop the .xap and html file right on the machine so you don't have to be on line to use it. Sweet.

Here's the source code for this post: RachelTimer1.zip

 

Posted in z Silverlight Archives | Tagged | Comments Off on Throwing Together An Application

Most Frequently Asked Question: When Will Silverlight Ship?

Dock at Camden ME

My way of acknowledging that you need to know, and we want to tell you as soon as we can. 

As an aside, about four months ago I started to buy photos to make my presentations “pop” (see Presentation Zen). 

As a side benefit, I’ve rediscovered just a hint of my old interest in photography – wow have things changed. In any case, unlike all the others I’ve been using; this one is mine. 🙂

Posted in z Silverlight Archives | Comments Off on Most Frequently Asked Question: When Will Silverlight Ship?

The difference between understanding a concept…

Follow up posted at bottom of article

 

 

… and implementing it, can be the difference between your book being on time, and being, er, ah, well… late.

I’ve written chapters on custom controls at least a dozen times, and I’ve explained how to write custom controls at least a hundred times. You’d think I could do it in my sleep. In this first of a series of blog entries about Silverlight custom controls I’ll try to convey why creating custom controls is not difficult, but explaining it, or at least explaining it well, is.

There were custom controls in ASP.NET, in Windows Forms, in many other GUI platforms, and they’ve always been just  about the same idea. You typically had three options:

DropDownButton

Option One

The first way to create a custom control is to aggregate two or more existing controls into a new type; to make something new (or something monstrous). My favorite example is to combine a button with a DropDown to make a button whose action can change.

 

 

 

 

 

 

 

 

 

 

 

 

 

Option Two

The second approach is to derive from an existing control but to add a little new CountedButtonfunctionality. My standard  example is Clickable button, a button that knows how many times it has been clicked.

The code shown below is taken from Programming ASP.NET  but the concepts are the same across many GUI frameworks.

 

 

   1: using System;
   2: using System.ComponentModel;
   3: using System.Web.UI;
   4:  
   5: namespace CustomControls
   6: {
   7:     [DefaultProperty("Text")]
   8:     [ToolboxData("<{0}:CountedButton2 runat=server></{0}:CountedButton2>")]
   9:     public class CountedButton : System.Web.UI.WebControls.Button
  10:     {
  11:       private string displayString;
  12:  
  13:       public CountedButton(  )
  14:       {
  15:          displayString = "clicks";
  16:          InitValues(  );
  17:       }
  18:  
  19:       private void InitValues(  )
  20:       {
  21:          if (ViewState["Count"] == null)
  22:             ViewState["Count"] = 0;
  23:          this.Text = "Click me";
  24:       }
  25:    
  26:       public int Count 
  27:       {
  28:          get { return (int) ViewState["Count"]; }
  29:          set { ViewState["Count"] = value; }
  30:       }
  31:  
  32:       protected override void OnClick(EventArgs e)
  33:       {
  34:          ViewState["Count"] =  ((int)ViewState["Count"]) + 1;
  35:          this.Text = ViewState["Count"] + " " + displayString;
  36:          base.OnClick(e);
  37:       }
  38:     }
  39: }
  40:  

 

 

Option Three

And the third, typically most labor-intensive approach is to derive from a root Control object and (typically) draw the entire control and write all its logic yourself. An example that I’ve used a number of times is a custom clock face where the date travels around the circumference in Ferris Wheel like fashion and where you must draw the numbers, and the hour and minute hands and the position for the seconds indicator essentially “by hand”

CustomClock

This kind of control requires extensive coding in some environments, as shown in this cut down code listing (full and annotated listing in Programming WinForms.)

   1: public class ClockFaceCtrl : System.Windows.Forms.Control
   2: {
   3:     public ClockFaceCtrl()
   4:     {    }
   5:  
   6:     public void OnTimer(Object source, ElapsedEventArgs e)
   7:     {
   8:         Graphics g = this.CreateGraphics();
   9:         SetScale(g);
  10:         DrawFace(g);
  11:         DrawTime(g,false);
  12:         DrawDate(g);
  13:         g.Dispose();
  14:     }
  15:  
  16:     protected override void OnPaint ( PaintEventArgs e )
  17:     {     }
  18:  
  19:     private void SetScale(Graphics g)
  20:     {
  21:         g.TranslateTransform(Width / 2, Height / 2);
  22:         float inches = Math.Min(Width / g.DpiX, Height / g.DpiX);
  23:         g.ScaleTransform(inches * g.DpiX / 2000, inches * g.DpiY / 2000);
  24:     }
  25:  
  26:     private static float GetSin(float degAngle)
  27:     { return (float) Math.Sin(Math.PI * degAngle / 180f);     }
  28:  
  29:     private static float GetCos(float degAngle)
  30:     { return (float) Math.Cos(Math.PI * degAngle / 180f);     }
  31:  
  32:     private void DrawFace(Graphics g)
  33:     {
  34:         for (int i = 1; i <= numHours; i++)
  35:         {
  36:             SizeF stringSize = g.MeasureString(i.ToString(),font);
  37:             x = GetCos(i*deg + 90) * FaceRadius;
  38:             y = GetSin(i*deg + 90) * FaceRadius;
  39:             if ( currentTime.Second  == i * 5)
  40:                 g.DrawString(i.ToString(), font, greenBrush, -x, -y,format);
  41:             else
  42:                 g.DrawString(i.ToString(), font, brush, -x, -y,format);
  43:         }
  44:     }
  45:  
  46:     private void DrawTime(Graphics g, bool forceDraw)
  47:     {
  48:         rotation = GetSecondRotation();
  49:         state = g.Save();
  50:         g.RotateTransform(rotation);
  51:         g.FillEllipse(blankBrush,-25,-secondLength,50,50);
  52:         g.Restore(state);
  53:     }
  54:  
  55:     private float GetHourRotation()
  56:     { }
  57:     private float GetMinuteRotation()
  58:     { return( 360f * currentTime.Minute / 60f );  }
  59:  
  60:     private float GetSecondRotation()
  61:     { return(360f * currentTime.Second / 60f);  }
  62:  
  63:     private class LtrDraw
  64:     {    }
  65:  
  66:     private class StringDraw
  67:     { 
  68:         public StringDraw(string s, ClockFaceCtrl theControl)
  69:         {           }
  70:  
  71:         public void DrawString(Graphics g, Brush brush)
  72:         {
  73:             foreach (LtrDraw theLtr in theString)
  74:             {
  75:                 theLtr.DrawString(g,brush,theControl);
  76:             }
  77:             ClockFaceCtrl.offset += 1;
  78:         }
  79:     }
  80:  
  81:     private void DrawDate(Graphics g)
  82:     {
  83:         Brush brush = new SolidBrush(ForeColor);
  84:         sdToday.DrawString(g,brush);
  85:     }
  86: }

 

 

 

 

 

 

 

 

 

Why Is This GUI Framework Different From All Other Gui Frameworks?

Writing a templatable custom control in Silverlight is exactly the same, only totally different. That is, the architectural build/ buy/ make-do decisions are the same, and the derivation decisions are the same, but the new wrinkle is the separation of logic from visuals though a contract enforced by the Parts and States model and leveraged by the Visual State Machine.

It is to that, I will turn when I wake up, but I suddenly realized that it is 2:20 am, and I should be sleeping. Very much.

 

Follow-up
More here:  Digging Into Custom Controls

Posted in z Silverlight Archives | Tagged | Comments Off on The difference between understanding a concept…

I’m Back!


In the words of the immortal
Roseanne Roseannadana “It’s always something….”

stock_hypo_blueJust when i was finally back from vacations and other distractions and ready to handle my very intense deadlines… I was struck down by… well you really don’t want to know except that it was food-borne, it landed me in a lovely hospital outside Redmond (where i came for what seemed at the time to be an important 3 day meeting of which I attended 10 minutes) and someone owes me two entire days that I don’t remember at all.

As these things do, the experience gave me time to reflect on what is important in life. You know, kids, Silverlight, family, blogging, videos, wifi, private rooms in hospitals, good health care, the Daily Show….

And it gave me time to plan and prioritize to meet the needs of folks who have responded to the tutorials, blog entries, videos and more.  I’ve written more than enough already about “here’s what’s coming…”  so I won’t again. Instead I’ll spend the next couple months kicking those plans into gear. 

By the end of October I’ll try to get a sense of how things are going, and adjust the balance and in January it will be time to assess. That said, look for the first step: regular blogging, to start right now: I was listening to Scott Hanselman sing the praises of those who have something useful in their blogs daily; that is a high standard, but worth shooting for.

Up next: the difference between understanding a concept and implementing it.  Creating Templatable Custom Controls using the States and Parts Model, Part 1.

Posted in z Silverlight Archives | Comments Off on I’m Back!

When Will Silverlight Ship?

I have received a number of emails asking when Silverlight will ship; and I’ve promised to look into it for a number of folks who very much need to know.  Here is what I found out…

Mature man with blue shirt, closed mouthWhile the incredible success of the use of Silverlight in facilitating the viewing of the Olympics and the Democratic convention speak to the solidity of Silverlight 2 and to the very high standards we’ve set, we’re not quite ready to make any announcements. (sorry).

Please be assured that we totally understand how much you need to know the date, but as has been true all along, when we announce a date we want it to be a date you can count on, and we are working hard on getting you that date as soon as we possibly can.


Where Has Liberty Gone?

While I have you, let me apologize for the recent slow down in information coming from Liberty Central.  I was on vacation for much of August (and, as many of you know, dealing with family “stuff”) and I’ll be “out of office” for much of September: I’m in Redmond this week, and will be in England and Ireland from the 14th to the 25th (Remix, Bristol, Dublin and Ulster).

Once I return, I hope to ramp up a significant set of more advanced videos, supplemented by tutorials, web-casts, and blog posts, and then venture into a couple new approaches. The goal will be to meet the needs of those of you who want to go beyond the fundamentals, while still ensuring that the “on ramps” to Silverlight are kept in good condition as programmers arrive. I have a long list of advanced topics from your suggestions and from talking with folks here, and Tim and I are looking at a lot of cool ways to get that information out.

In the meantime, please be sure to catch my next webcast on September 10: Creating Skinnable Custom Controls.

Posted in z Silverlight Archives | Comments Off on When Will Silverlight Ship?

Pixellated – Podcast Radio Interview and Silverlight

 

Pixel8.jpeg

I had a great time discussing Silverlight with Craig Shoemaker on his PodCast Pixel8.

 

Craig is a terrific interviewer; well informed, passionate, smart, Microsoft MVP, ASP Insider, developer, podcaster, blogger, co-author of Beginning ASP.NET with AJAX,  and very good at letting me blather on and then jumping in to get me back on track.

I highly recommend subscribing both to Pixel8 and to Craig’s independent PolymorphicPodcast

 

I had a lot of fun in this interview in which we focused in on what’s hot in the Silverlight Developer community; what do folks want to know, how are we going to meet those needs.

Posted in z Silverlight Archives | Comments Off on Pixellated – Podcast Radio Interview and Silverlight

Sparkling Client – Monthly Podcast Guest

I’m very proud and excited to announce that I’ve been invited to be a monthly guest on the Sparkling Client Silverlight Podcast. Details to follow very soon, but our initial shows include a discussion of Templates on September 23rd and of Databinding on October 28.

SparklingPodcast

You can find out more about the show, its hosts and their previous podcasts on the Sparkling Client Home Page. 

Posted in z Silverlight Archives | Comments Off on Sparkling Client – Monthly Podcast Guest

Web Cast-off

Due to a family emergency I had to postpone today’s Webcast, and I apologize for the inconvenience. I did want to assure you that we have already rescheduled, that we will record the Webcast,  and that I will be recording a series of How Do I videos on custom controls as well.

Thank you for your patience.

Posted in z Silverlight Archives | Comments Off on Web Cast-off

Silverlight Tutorials Now In Japanese

I’m very pleased to announce that the Silverlight Tutorials are now available in Japanese with more on the way soon.  (All tutorials in VB and C# soon as well)

TutorialInJapanese

 

-Jesse

Posted in z Silverlight Archives | Comments Off on Silverlight Tutorials Now In Japanese