Quando si azzera la scatola sul nuovo controllo 4.0 DatePicker WPF mostra "Selezionare una data"Come localizzare il WPF 4.0 di controllo DatePicker
Esiste un modo per localizzare il testo?
Quando si azzera la scatola sul nuovo controllo 4.0 DatePicker WPF mostra "Selezionare una data"Come localizzare il WPF 4.0 di controllo DatePicker
Esiste un modo per localizzare il testo?
Sfortunatamente, l'impostazione del testo della filigrana è un po 'complicata.
Come si può fare si può vedere in questo articolo: Changing the watermark text in a DatePicker control
Ecco come farlo senza dover ricavare un nuovo controllo da DatePicker:
Mi piace questa soluzione –
Ho preso l'idea di Matt e lo ha esteso un po '; Ho implementato un comportamento associato che consente di definire la filigrana per ciascun controllo DatePicker tramite XAML. Ecco il codice:
namespace DatePickerWatermark
{
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
public static class DatePickerWatermarkBehaviour
{
public static readonly DependencyProperty WatermarkProperty =
DependencyProperty.RegisterAttached(
"Watermark",
typeof(string),
typeof(DatePickerWatermarkBehaviour),
new UIPropertyMetadata(null, OnWatermarkChanged));
public static string GetWatermark(Control control)
{
return (string)control.GetValue(WatermarkProperty);
}
public static void SetWatermark(Control control, string value)
{
control.SetValue(WatermarkProperty, value);
}
private static void OnWatermarkChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
var datePicker = dependencyObject as DatePicker;
if (datePicker == null)
return;
if ((e.NewValue != null) && (e.OldValue == null))
datePicker.Loaded += DatePickerLoaded;
else if ((e.NewValue == null) && (e.OldValue != null))
datePicker.Loaded -= DatePickerLoaded;
}
private static void DatePickerLoaded(object sender, RoutedEventArgs e)
{
var datePicker = sender as DatePicker;
if (datePicker == null)
return;
var datePickerTextBox = GetFirstChildOfType<DatePickerTextBox>(datePicker);
if (datePickerTextBox == null)
return;
var partWatermark = datePickerTextBox.Template.FindName("PART_Watermark", datePickerTextBox) as ContentControl;
if (partWatermark == null)
return;
partWatermark.Content = GetWatermark(datePicker);
}
private static T GetFirstChildOfType<T>(DependencyObject dependencyObject) where T : DependencyObject
{
if (dependencyObject == null)
return null;
for (var i = 0; i < VisualTreeHelper.GetChildrenCount(dependencyObject); i++)
{
var child = VisualTreeHelper.GetChild(dependencyObject, i);
var result = (child as T) ?? GetFirstChildOfType<T>(child);
if (result != null)
return result;
}
return null;
}
}
}
Ecco qualche esempio XAML:
<Window x:Class="DatePickerWatermark.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:b="clr-namespace:DatePickerWatermark" Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.Resources>
<Style TargetType="DatePicker">
<Setter Property="Margin" Value="10,5"/>
</Style>
<Style x:Key="EnglishDatePicker" TargetType="DatePicker" BasedOn="{StaticResource {x:Type DatePicker}}">
<Setter Property="b:DatePickerWatermarkBehaviour.Watermark" Value="Please select a date:"/>
</Style>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<DatePicker Grid.Row="0" b:DatePickerWatermarkBehaviour.Watermark=""/>
<DatePicker Grid.Row="1" b:DatePickerWatermarkBehaviour.Watermark="Wählen Sie ein Datum"/>
<DatePicker Grid.Row="2" b:DatePickerWatermarkBehaviour.Watermark="Sélectionner une date"/>
<DatePicker Grid.Row="3" Style="{StaticResource EnglishDatePicker}"/>
<DatePicker Grid.Row="4" Style="{StaticResource EnglishDatePicker}"/>
</Grid>
</Window>
Wayne, questa grande opera, ma non funziona quando DatePicker è parte di DataGridColumnHeader e, a volte, quando DatePicker è sul controllo che viene prima nascosto e quindi visibile. La soluzione di Matt Hamilton funziona solo su Load, e quando si modifica selectedDate c'è di nuovo fastidioso Selezionare una filigrana della data. La soluzione più semplice è solo per sostituire l'evento OnRender in una classe personalizzata. Se si imposta la proprietà filigrana e non un contenuto filigrana che è necessario ignorare anche l'evento onload. La classe completa è qui:
public class myDateTimePicker : DatePicker
{
public string Watermark { get; set; }
protected override void OnSelectedDateChanged(SelectionChangedEventArgs e)
{
base.OnSelectedDateChanged(e);
//SetWatermark();
}
protected override void OnRender(System.Windows.Media.DrawingContext drawingContext)
{
base.OnRender(drawingContext);
SetWatermark();
}
private void SetWatermark()
{
FieldInfo fiTextBox = typeof(DatePicker).GetField("_textBox", BindingFlags.Instance | BindingFlags.NonPublic);
if (fiTextBox != null)
{
DatePickerTextBox dateTextBox = (DatePickerTextBox)fiTextBox.GetValue(this);
if (dateTextBox != null)
{
if (string.IsNullOrWhiteSpace(this.Watermark))
{
this.Watermark = "Custom watermark";
}
// if you set property this way then you need to override OnSelectedDateChanged event
//PropertyInfo piWatermark = typeof(DatePickerTextBox).GetProperty("Watermark", BindingFlags.Instance | BindingFlags.NonPublic);
//if (piWatermark != null)
//{
// piWatermark.SetValue(dateTextBox, this.Watermark, null);
//}
var partWatermark = dateTextBox.Template.FindName("PART_Watermark", dateTextBox) as ContentControl;
if (partWatermark != null)
{
partWatermark.Foreground = new SolidColorBrush(Colors.Gray);
partWatermark.Content = this.Watermark;
}
}
}
}
}
Che funziona solo in Silverlight. – svick
Qualche soluzione dal lato WPF? – papaiatis