The final version can be downloaded here. I finally worked out the easiest way to embed silverlight apps in the blog so here is the finished working demo app:
In this post we will look at the code we need to make it all work. Although writing code is easier in Visual Studio, we will do it all in Blend since we have been working in there anyway. Be prepared; this post doesn't have much in the way of graphical content - it's pretty much all code.
Since we have buried the TextBox control inside a UserControl we need to expose a couple of properties to make this reusable. Although we could do a thorough job and expose quite a few properties of the TextBox control, I just want to expose two properties for now: the Text property and the Style property.
There are plenty of other tutorials on the web about Dependency Properties so if you are not familiar with them then it would pay to do a bit of reading later on; but for now all you need to know is that the we are going to use them to expose properties on our user control.
The Text property
Open up the WatermarkedTextbox.xaml.cs file and you should see the current code behind. The first property to declare looks like this:
This declares a bindable dependency property on our UserControl that another consuming UserControl can use to set the text content of our embeded TextControl. So if you placed the control on another UserControl and set it's Text property, the static method TextChangedHandler will be called for us to respond to the new text value. The TextChangedHandler method looks like this:
The above static method ensures that the change to our UserControl's text property gets passed on to our embedded TextBox control. If the new text is not empty then we go to the WatermarkHidden state, and the ButtonVisible state. We still have to handle the case where the user types into our embeded TextBox; we need to update our UserControl's Text DependencyProperty. We cant bind the TextEntry.Text property in the XAML against the UserControl's Text property because we would have to give our UserControl an "x:Name=..." attribute, and you can't name UserControls if you want to use more than one instance on the same parent UserControl; otherwise you get a nasty error that stops you Silverlight app dead in it's tracks.
So we are going to handle the TextChanged event on our embeded TextEntry TextBox. To do this, select the TextEntry TextBox control and on the Properties page select the "Events" button in the top left corner. You will see all the events that the TextBox control exposes. Double click the "TextChanged" event and Blend will create a method stub in our code-behind called "TextEntry_TextChanged". The code we need to write here looks like this:This method does two important things: it updates our UserControl's Text DependencyProperty and it updates the states that the UserControl needs to be in. So now our Text property updates and is updates in sync with the TextEntry TextBox's Text property. Consuming UserControls can use our UserControl's Text property the same way they would have used the TextBox's Text property (including binding).
The Watermark Property
The watermark is a little easier. It's not an editable control so we only have to update it in one direction. The declaration for the DependencyProperty and UserControl property looks like this:
And the WatermarkChangedHandler is as follows:
The TextBoxStyle Property
The last Dependency Property to add is the Style property. This will allow users of our FilteredTextBox UserControl to supply a style to change the appearance of the text box. If we were going to be really thorough we would also provide properties for the button and the watermark too - and there is nothing stopping you from adding that functionality yourself!
Here is the DependencyProperty declaration for the Style property:
Pretty straight forward by now. And you can probably guess what the TextBoxStyleChanged method will look like too:
The Last Events
There are three more events that we need to write code for. Back on the design surface select the TextEntry control and go to the Events page of the Properties panel again. Create an event handler for both the GotFocus and LostFocus events. The code for these events is going to make sure the Watermark disappears and appears at the right time. It requires us to use a flag to keep track of when our TextBox has the focus. The flag declaration and method handlers look like this:
And the last event to handle is the user clicking on our ClearFilterButton. Use the same technique as above to create an event handler for the Click event on our button. The code looks like this:
And we're finished!
The download for this control also has support for Commanding, which will only mean something to you if you are using the MVVM pattern, in which case the extra code will probably be straight forward for you anyway - so I won't go over it here.
So you now have a working, reusable UserControl that gives you the functionality of a Watermarked TextBox control. Back in Part I of the series I said we could go about building this control two ways: as a UserControl or as a templated custom control. The most flexible way would have been as a templated custom control - and I hope to do a series on this at a later stage - but the easiest way is using a UserControl.
Note : for those of you who have already downloaded the control, I have updated the file on Microsoft Expression Gallery, and the alternate download location. I noticed an incorrect binding I had left on the TextEntry text box, which is now removed.
Feel free to use this control for your own projects - if you like it, please leave a comment below!