Customizing the WPF DatePicker's Watermark

Introduced as part of the WPF Toolkit and added to .NET 4 as a part of the framework, the DatePicker control is a half-decent replacement for Windows Form's DateTimePicker control.

Something that a lot of people (myself included) don't like about the DatePicker, though, is that by default if no date is displayed it shows the text "Select a date" as a watermark, and this text is baked into the control - it's not localized or accessible by any public property. This is particularly frustrating if the date in question is optional and you don't necessarily want to prompt your users to select one.

There are a few posts around the net describing how to customize this text by deriving your own new control from DatePicker and/or by completely replacing the default ControlTemplate, but this is cumbersome, especially if you already have a project with DatePickers throughout.

Here's a much simpler way to customize the watermark text in a DatePicker.

First, in your app's OnStartup method, you'll want to register a global event handler to the control's Loaded event:

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);
        EventManager.RegisterClassHandler(typeof(DatePicker),
            DatePicker.LoadedEvent, 
            new RoutedEventHandler(DatePicker_Loaded));
    }
}

That means that any DatePicker in our application will call the DatePicker_Loaded method once it's loaded. That method needs to find the watermark text in the control, so we'll need this helper method defined somewhere too:

public static T GetChildOfType<T>(DependencyObject depObj) where T : DependencyObject
{
    if (depObj == null) return null;

    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
    {
        var child = VisualTreeHelper.GetChild(depObj, i);

        var result = (child as T) ?? GetChildOfType<T>(child);
        if (result != null) return result;
    }
    return null;
}

Now that we have that in place, our event handler looks like this:

void DatePicker_Loaded(object sender, RoutedEventArgs e)
{
    var dp = sender as DatePicker;
    if (dp == null) return;

    var tb = GetChildOfType<DatePickerTextBox>(dp);
    if (tb == null) return;

    var wm = tb.Template.FindName("PART_Watermark", tb) as ContentControl;
    if (wm == null) return;

    wm.Content = "Your watermark here!";
}

Now all DatePickers will show "Your watermark here!" rather than the default "Select a date" text when no date is selected. If you'd rather not see any watermark at all, simply assign null to wm.Content instead.

wpf datepicker
Posted by: Matt Hamilton
Last revised: 25 May, 2013 03:41 AM History

Trackbacks

Comments

04 Feb, 2011 07:37 AM

Nice, Matt. It is a frustration that the control doesn't expose a 'Watermark' property - but this is a nice workround

Juan
Juan
09 Mar, 2011 02:23 PM

Thanks! That's a nice workaround. Still, I could not make it work. I even tried extending DatePicker and editing the template XAML, but could not find the "PART_Watermark" ContentControl. Any ideas?

08 Apr, 2011 05:32 PM

Matt - thanks for posting this. From all the work-arounds I've seen, this is IMHO the best and straightest forward one.

Cheers, Olaf

Geoffrey Adam
Geoffrey Adam
26 Apr, 2011 09:26 AM

Thanks Matt, this really Helped me out for a school project!

Narayana
Narayana
30 Jun, 2011 01:53 PM

Great work. Thank you very much Matt.

Leonardo
Leonardo
05 Aug, 2011 06:20 PM

Didn't work. I have a WPF window that contain a DatePicker. I placed this code on App.xml.cs. But still, my DatePicker gets "Select a date" content. What am I doing wrong?

06 Aug, 2011 12:22 AM

Leonardo,

Have you stepped through the code in debug mode? Can you see which line it's failing on. For example, is it not finding the PART_Watermark ContentControl?

Leonardo
Leonardo
08 Aug, 2011 03:38 PM

Sorry Matt. There was an inconsistence among my Namespaces. It worked perfectly! Thanks for the article!

JZ
JZ
09 Aug, 2011 02:14 AM

Is that have anyway to find this watermaker content control in XAML? I am looking a way to bond it with a string which later can be localized in the resource file.

Thanks.

09 Aug, 2011 02:25 AM

Not that I'm aware of, JZ. That's the big complaint about the DatePicker control (well, one of) - that it doesn't allow for much customization in XAML.

brodny
brodny
26 Aug, 2011 08:50 AM

Thanks, Matt. Really nice workaround, works great. Too bad that we have to use workarounds and .NET 4 developers didn't expose property to modify default watermark. I hope it will change in the next release (or in service pack).

01 Sep, 2011 08:14 PM

you could get around the text by assigning the SelectedDate with a date. code example: myDataPicker.SelectedDate = DateTime.Now.

01 Sep, 2011 10:40 PM

young,

That doesn't really get around the problem. The watermark is shown whenever there is no text in the DatePicker, so as soon as the user clears out the text, the watermark will show again.

Sebastian
Sebastian
10 Oct, 2011 07:52 PM

Hi, when the application starts and the datepicker is visibility = collapse its don't have effect because when i do visible the datepicker through one button's event appears the default watermark.. Matt, how to fix this?.., Sorry my English :/...

10 Oct, 2011 09:25 PM

Sebastian,

That's odd. I don't think the initial visibility of the DatePicker should affect this at all - it all happens before even the windows containing the DatePicker are instantiated. Perhaps there's another problem causing this. Are you using DatePicker directly, or have you derived another control from it?

Sebastian
Sebastian
11 Oct, 2011 03:39 AM

Hi Matt.. thanks for replying,

Nou.., it's inside the windows directly, and if would put the DatePicker visible inside a Panel (Stackpanel, Grid, Wrappanel, etc..) and the panel is collapsed, after clic on button which put the panel visible appears the default watermark too because he extends visibility from him parent :'(..

Here is one image very clearly from the code actually

http://www.subeimagenes.com/img/datepicker-105906.png

What could be?...

11 Oct, 2011 05:08 AM

Wow - you're totally right, Sebastian.

It seems that the "Loaded" event isn't firing if the control is initially collapsed.

All I can suggest at this point is to have your DatePicker visible by default, and collapse it in the "Loaded" event handler of your Window. That way the watermark will get changed but the user won't see it until you want them to.

Sebastian
Sebastian
11 Oct, 2011 04:02 PM

Wow that does the trick, was not what i wanted but it works!!

Excellent code, excellent page, excellent guy... Thanks Man!

Chris
Chris
04 Nov, 2011 08:07 AM

Thank you! That looks to me just the way to do it.

Naveed
Naveed
22 Nov, 2011 07:54 AM

Hi Matt,

Thanx for the awesome article. One thing, how can i assign different watermarks to different DatePicker contol. I might want to display "Select DOB" in one and "Select Expiry" in the other.

22 Nov, 2011 08:53 AM

Hi Naveed,

To assign a custom watermark to an individual DatePicker control is nice and easy - simply handle the Loaded event on that control and use the code in the DatePicker_Loaded method above, supplying whatever text you like.

If you wanted to get tricky you could hijack the Tag property of the DatePicker and assign that as the watermark in the code above. That way you could set the tag to "Select DOB" on one DatePicker but leave it as null on all the others, and have the DatePicker_Loaded method say something like:

wm.Content = dp.Tag ?? "Your watermark here";

Even more in the spirit of WPF, but a little more work, would be to create a Watermark attached property, but I won't try to address that in a comment here. I think the Tag approach is the easiest for your needs.

Alvaro Lopez
Alvaro Lopez
02 Mar, 2012 12:15 PM

Excellent tip !!! Thank you Mark !!

Bhuvan Desai
Bhuvan Desai
02 Mar, 2012 02:05 PM

This is one of the best answer so far, I have read online. Just useful information. Very well presented. You made it very simple and understandable. I've found some other good articles on DatePicker control in WPF which also explained very well. Here I'm sharing the link of that helpful post.....

http://www.codeproject.com/Articles/88757/WPF-Calendar-and-Datepicker-Final

and

Date Picker control

These links also helped me to complete my task.

Tony
Tony
09 May, 2012 12:49 PM

Nice one Matt - didn't think that would work at all...

Spot on...

andrea
andrea
29 May, 2012 10:18 AM

Great job but I'm trying using it in my vb project but I've some problem to converting. Anyone can help me?

Regards Andrea

29 May, 2012 11:38 PM

Post some code, Andrea. Either here, or better still on Stack Overflow.

Camilo Chavarriaga
Camilo Chavarriaga
07 Aug, 2012 01:35 AM

Thank you very much. I created a DateTimePicker user control in the following way: DatePicker("Not Set" - for null), TextBox(Hours), TextBlock(:), TextBox(Mins), TextBlock(:), TextBox(Secs), ComboBox(AM, PM), and TimeZone. And the Select a date was completely unaceptable for this control.

noir
noir
13 Aug, 2012 01:30 AM

Thank you very much Matt!!!!!

Garima Saini
Garima Saini
24 Sep, 2012 10:23 AM

Thanks a ton Matt!!!! :)

Alex
Alex
09 Oct, 2012 03:18 PM

Thanks a lot Matt!

Your Comments

Used for your gravatar. Not required. Will not be public.
Posting code? Indent it by four spaces to make it look nice. Learn more about Markdown.

Preview