使用以下代码,虽然Text属性绑定到DateTime源属性,但我注意到WPF似乎自动将文本转换为DateTime,而不需要编写ValueConverter。有人可以说明如何做到这一点
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:WpfApplication1="clr-namespace:WpfApplication1"
Title="MainWindow" Height="350" Width="525"
>
<StackPanel>
<DatePicker Height="25" Name="datePicker1" Width="213" Text="{Binding Path=DueDate,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>
</Window>
public class P
{
private DateTime? dueDate = DateTime.Now;
public DateTime? DueDate
{
get { return dueDate; }
set
{
dueDate = value;
}
}
}
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
P p = new P();
this.DataContext = p;
}
}
答案 0 :(得分:5)
它正在使用基类库中的DateTimeTypeConverter
(编辑:嗯,它可能使用了TypeConverter,但它似乎来自@DeviantSeev's answer他们没有)
您所谈论的'默认'转换器实际上是TypeConverters
(MSDN),它们自v2.0以来一直是.NET Framework的一部分,它们在整个Base中使用类库。 WPF中TypeConverters的另一个示例是ThicknessTypeConverter
,Padding
和Margin
属性的BorderThickness
。它将逗号分隔的字符串转换为Thickness
对象。
如果您想plenty,可以articles understand them further。
使用TypeConverter
有两个部分 - 类的实现,然后用TypeConverterAttribute
标记属性/类型。
例如,我最近有一个自定义控件需要char[]
,我想从Xaml
设置<AutoCompleteTextBox MultiInputDelimiters=",;. " />
,如下所示:
[TypeConverter(typeof(CharArrayTypeConverter))]
public char[] MultiInputDelimiters
{
get { return (char[])GetValue(MultiInputDelimitersProperty); }
set { SetValue(MultiInputDelimitersProperty, value); }
}
<强>用法强>
public class CharArrayTypeConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return (Type.GetTypeCode(sourceType) == TypeCode.String);
}
public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
{
if (value is string)
return ((string)value).ToCharArray();
return value;
}
}
<强>实施强>
TypeConverter
何时使用TypeDescriptors
?
如果您正在编写自定义控件,则只能使用TypeDescriptorAttribute
,因为您需要能够使用TypeConverter
标记属性。此外,我只会使用char[]
,如果转换相当简单 - 如上例中我有一个字符串并想要IValueConverter
- 或者我想要多种可能的格式转换自。
当您希望通过数据驱动或传递参数来更灵活地转换值时,可以编写bool
。例如,WPF中一个非常常见的操作是将Visibility
转换为Visible
;这种转换有三种可能的输出(Hidden
,Collapsed
,true
),只有两个输入(false
,TypeConverter
)很难确定这是BoolToVisibilityConverter
。
在我的应用程序中,要实现这两个输入到三个输出问题,我编写了一个TrueValue
FalseValue
和ResourceDictionary
属性,然后我在全局实例三次[ValueConversion(typeof(bool), typeof(Visibility))]
public class BooleanToVisibilityConverter : IValueConverter
{
public Visibility FalseCondition { get; set; }
public Visibility TrueCondition { get; set; }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return ((bool)value) ? TrueCondition : FalseCondition;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if ((bool)value)
return TrueCondition;
return FalseCondition;
}
}
<converters:BooleanToVisibilityConverter x:Key="BoolToVisibilityConverter" FalseCondition="Collapsed" TrueCondition="Visible"/>
<converters:BooleanToVisibilityConverter x:Key="BoolToVisibilityCollapsedConverter" FalseCondition="Visible" TrueCondition="Collapsed"/>
<converters:BooleanToVisibilityConverter x:Key="BoolToVisibilityHiddenConverter" FalseCondition="Visible" TrueCondition="Hidden"/>
<converters:BooleanToVisibilityConverter x:Key="BoolToVisibilityHiddenWhenFalseConverter" FalseCondition="Hidden" TrueCondition="Visible"/>
。 我明天早上会发布代码示例,我现在不在我面前。。
{{1}}
答案 1 :(得分:1)
DatePicker是一个自定义控件,最初是WPF Toolkit的一部分,之后作为.NET 4中的标准控件添加。
我刚刚访问控件的源代码存储库,找到了负责将文本转换为日期的确切源代码:
#region Text
/// <summary>
/// Gets or sets the text that is displayed by the DatePicker.
/// </summary>
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
/// <summary>
/// Identifies the Text dependency property.
/// </summary>
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register(
"Text",
typeof(string),
typeof(DatePicker),
new FrameworkPropertyMetadata(string.Empty, OnTextChanged, OnCoerceText));
/// <summary>
/// TextProperty property changed handler.
/// </summary>
/// <param name="d">DatePicker that changed its Text.</param>
/// <param name="e">DependencyPropertyChangedEventArgs.</param>
private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
DatePicker dp = d as DatePicker;
Debug.Assert(dp != null);
if (!dp.IsHandlerSuspended(DatePicker.TextProperty))
{
string newValue = e.NewValue as string;
if (newValue != null)
{
if (dp._textBox != null)
{
dp._textBox.Text = newValue;
}
else
{
dp._defaultText = newValue;
}
dp.SetSelectedDate();
}
else
{
dp.SetValueNoCallback(DatePicker.SelectedDateProperty, null);
}
}
}
private static object OnCoerceText(DependencyObject dObject, object baseValue)
{
DatePicker dp = (DatePicker)dObject;
if (dp._shouldCoerceText)
{
dp._shouldCoerceText = false;
return dp._coercedTextValue;
}
return baseValue;
}
/// <summary>
/// Sets the local Text property without breaking bindings
/// </summary>
/// <param name="value"></param>
private void SetTextInternal(string value)
{
if (BindingOperations.GetBindingExpressionBase(this, DatePicker.TextProperty) != null)
{
Text = value;
}
else
{
_shouldCoerceText = true;
_coercedTextValue = value;
CoerceValue(TextProperty);
}
}
#endregion Text
答案 2 :(得分:0)
在大多数情况下,我相信WPF会为您调用ToString(),但是如果您查看日期选择器的代码,重要的一行是
(string)GetValue(TextProperty)
请注意,它将您分配给“Text”属性的值强制转换为字符串?重点是更传统的BooleanToVisibilityConverter或类似的东西没有默认转换器。