DatePicker default watermark

Nov 10, 2008 at 9:21 PM
A previous post stated that there is no way to override the default watermark for the date picker.  Is this correct?  Is there really no way to apply a template to clear out the silly "Show Calendar" text?
Coordinator
Nov 11, 2008 at 12:51 AM
Edited Nov 11, 2008 at 6:14 PM
Well... you could modify the template, technically. The real source of that String is hardcoded in ExceptionStringTable.txt in the Resources folder in the source. This file contains the Default/US-EN String Table for the Toolkit. In this file you could change DatePicker_WatermarkText  and  DatePickerTextBox_DefaultWatermarkText to change this. The second attribute controls a different String that appears under different circumstances (ie: when you have a Date, then remove it).

If you would rather alter the Template, you could copy the entire Style for DatePickerTextBox from Generic.xaml in the DatePicker's Themes folder and reuse it as your own personal style. You will have to change the the Content Property of the ContentControl element with the x:Name PART_Watermark. This will not though change the text that changing DatePickerTextBox_DefaultWatermarkText (mentioned above) will change.

 This should help you out.

-Eric Fabricant, MSFT

 P.S.  This thread may be of some use to readers concerned with localization: http://www.codeplex.com/wpf/Thread/View.aspx?ThreadId=39596

Feb 11, 2009 at 5:51 PM
arackaf,

Easy way to fix for your self:
1.  Get source code.
2.  Add the following dependency property to the DatePicker.cs file:  (I added in #Data region)
            public static DependencyProperty WatermarkProperty = DependencyProperty.Register( "Watermark", typeof( string ), typeof( DatePicker ), new PropertyMetadata( "Show Calendar" ) );
            public string Watermark
            {
                get { return ( string ) GetValue( WatermarkProperty ); }
                set { SetValue( WatermarkProperty, value ); }
            }

3.  Replace existing SetWatermarkText() with the following:
            private void SetWaterMarkText()
            {
                if (this._textBox != null)
                {
                    this.SetTextInternal(string.Empty);
                    this._defaultText = string.Empty;
                    this._textBox.Watermark = Watermark;
                }
            }

4.  Recompile WPFToolkit, and you're in business.
Feb 18, 2009 at 10:38 PM
Edited Feb 18, 2009 at 10:39 PM
Hello!

How do you properly recompile and install the new dlls?

I have tried bmatalus idea. I have managed to make it work to a certain extent, but not entirely. I managed to correct the source code. Produce the new dlls. I also managed to somehow substitute the old ones, but the problem remaind in the visual studio. I couldn't drag and drop the controls on my wpf window or user control anymore. I was able to manually add controls by typing XAML code. But I couldn't drag and drop them from the toolbar flyout.

So how do you properly recompile and install the new dlls.

Thank you very much!!

Best regards,
Jurij
Mar 2, 2009 at 8:07 AM
Request from me:
Could this solution (making Watermark property accessible) be integrated in the datepicker control plz?
My obvious next question is of course: any ideas when next release will be available?

But I have to say that for the moment I still have a problem with the solution from bmatalus.
When the language is changed at run-time, the watermark doesn't get updated correctly...
Anyone any thoughts on that?

Thx!
Nico
Mar 3, 2009 at 3:26 PM
sodjaj,

I think the problem that you are running into is that the *.msi that installs the toolkit puts these DLLs into the GAC (Global Assembly Cache)... which is great if you are planning on using them out of the box.  I think it is a really bad idea for open source or beta projects where the functionality is likely to need minor modifications and fixes... especially if the release cycle is long (like this one).

I think you have two options:
1. Remove/uninstall the toolkit instance in GAC, and move the re-compiled *.dll(s) into the Visual Studio path(s) so that it finds them at runtime.
    - C:\<Visual Studio 9.0 Path>\Common7\IDE

2. Install the re-compiled *.dll(s) into the GAC.

Brian
Mar 3, 2009 at 4:03 PM
doolitle,

My application(s) do not need to be localized, so my little solution to the problem didn't include looking up the text as a resource.  But, it should be pretty simple to change the assignment of the watermark to include the lookup:

this._textbox.Watermark = MyResourceStrings.Lookup( Watermark);

Brian
Jun 18, 2009 at 3:01 PM

You can easily derive from DatePicker and override method OnRender. In this example I set characteer "-" instead of text "Show calendar"

protected override void OnRender(System.Windows.Media.DrawingContext drawingContext)
{
    base.OnRender(drawingContext);
    FieldInfo fiTextBox = typeof(DatePicker).GetField("_textBox", BindingFlags.Instance | BindingFlags.NonPublic);
    if (fiTextBox != null)
    {
        DatePickerTextBox dateTextBox = (DatePickerTextBox)fiTextBox.GetValue(this);
        PropertyInfo piWatermark = typeof(DatePickerTextBox).GetProperty("Watermark", BindingFlags.Instance | BindingFlags.NonPublic);
        if (piWatermark != null)
        {
            piWatermark.SetValue(dateTextBox, "-", null);
        }
    }
}

 

 

Aug 20, 2009 at 1:19 PM

Is there an interface that I can inherit instead of deriving from DatePicker? My classes are already deriving other interfaces.

Thanks

- arch

Feb 23, 2010 at 10:13 PM

Bit late, but...

Arch it can be used as well in Loaded event, but requires bit of modification (thanks spud for great point of ref)

Lets assume that in your wpf window wpftoolkit:datepick object is being placed and x:Name="datePick1".

Now, add Loaded event to this object, and use code below:

private void datePicker1_Loaded(object sender, RoutedEventArgs e)
{
  FieldInfo fiTextBox = datePicker1.GetType()
    .GetField("_textBox", BindingFlags.Instance | BindingFlags.NonPublic);

  if (fiTextBox != null)
  {
    DatePickerTextBox dateTextBox =
      (DatePickerTextBox)fiTextBox.GetValue(datePicker1);

    if (dateTextBox != null)
    {
      PropertyInfo piWatermark = dateTextBox.GetType()
        .GetProperty("Watermark", BindingFlags.Instance | BindingFlags.NonPublic);

      if (piWatermark != null)
      {
        piWatermark.SetValue(dateTextBox, "-", null);
      }
    }
  }
}

Regards, 

Mar 18, 2010 at 9:34 AM
Edited Mar 18, 2010 at 9:37 AM

If you use DataTemplate in DataGrid(or other control): 

	     <toolkit:DataGridTemplateColumn x:Name="DateColumn" Header="{x:Static globalStr:GlobalStrings.Date}" Width="auto">
                    <toolkit:DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <toolkit:DatePicker x:Name="datePickerDateColumn" SelectedDate="{Binding Date}" Loaded="datePickerDateColumn_Loaded" />
                        </DataTemplate>
                    </toolkit:DataGridTemplateColumn.CellTemplate>
                </toolkit:DataGridTemplateColumn>

You have to use sender:

private void datePickerDateColumn_Loaded(object sender, RoutedEventArgs e)
        {
            DatePicker picker = sender as DatePicker;

            FieldInfo fiTextBox = picker.GetType().GetField("_textBox", BindingFlags.Instance | BindingFlags.NonPublic);

            if (fiTextBox != null)
            {
                DatePickerTextBox dateTextBox =
                  (DatePickerTextBox)fiTextBox.GetValue(picker);

                if (dateTextBox != null)
                {
                    PropertyInfo piWatermark = dateTextBox.GetType()
                      .GetProperty("Watermark", BindingFlags.Instance | BindingFlags.NonPublic);

                    if (piWatermark != null)
                    {
                        piWatermark.SetValue(dateTextBox, "", null);
                    }
                }
            }

        }
Jan 5, 2012 at 10:06 PM

Here is a working VB example:

    Private Sub dtpEndDate_SelectedDateChanged(sender As System.Object, e As System.Windows.Controls.SelectionChangedEventArgs) Handles dtpEndDate.SelectedDateChanged
        EraseDatePickerWaterMark(sender)
    End Sub

    Private Sub dtpEndDate_Loaded(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles dtpEndDate.Loaded
        EraseDatePickerWaterMark(sender)
    End Sub

    Private Sub EraseDatePickerWaterMark(sender As System.Object)
        Dim picker As DatePicker = CType(sender, DatePicker)
        Dim fieldInfo As Reflection.FieldInfo = _
            picker.GetType().GetField("_textBox", _
                Reflection.BindingFlags.Instance Or Reflection.BindingFlags.NonPublic)
        If Not fieldInfo Is Nothing Then
            Dim datePickerTextBox As Primitives.DatePickerTextBox = fieldInfo.GetValue(picker)
            If Not datePickerTextBox Is Nothing Then
                Dim propertyInfo As Reflection.PropertyInfo = _
                    datePickerTextBox.GetType().GetProperty("Watermark", _
                        Reflection.BindingFlags.Instance Or Reflection.BindingFlags.NonPublic)
                If Not propertyInfo Is Nothing Then
                    propertyInfo.SetValue(datePickerTextBox, String.Empty, Nothing)
                End If
            End If
        End If
    End Sub