此代码(来自DefaultValueConverter.cs @ referencesource.microsoft.com启发)适用于双向绑定到文本框或类似的控制,只要于formatString离开源属性的的ToString()的版本中,可以被转换回的状态。 (也就是说像“#,0.00”这样的格式是可以的,因为“1,234.56”可以被解析回来,但是FormatString =“Some Prefix Text#,0.00”将会转换为无法解析的“Some Prefix Text 1,234.56”。)
XAML:
<TextBox>
<TextBox.Text>
<MultiBinding Converter="{StaticResource ToStringFormatConverter}"
ValidatesOnDataErrors="True" NotifyOnValidationError="True" TargetNullValue="">
<Binding Path="Property" TargetNullValue="" />
<Binding Path="PropertyStringFormat" Mode="OneWay" />
</MultiBinding>
</TextBox.Text>
</TextBox>
注意复制TargetNullValue如果源属性可以为空。
C#:
/// <summary>
/// Allow a binding where the StringFormat is also bound to a property (and can vary).
/// </summary>
public class ToStringFormatConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values.Length == 1)
return System.Convert.ChangeType(values[0], targetType, culture);
if (values.Length >= 2 && values[0] is IFormattable)
return (values[0] as IFormattable).ToString((string)values[1], culture);
return null;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
var targetType = targetTypes[0];
var nullableUnderlyingType = Nullable.GetUnderlyingType(targetType);
if (nullableUnderlyingType != null) {
if (value == null)
return new[] { (object)null };
targetType = nullableUnderlyingType;
}
try {
object parsedValue = ToStringFormatConverter.TryParse(value, targetType, culture);
return parsedValue != DependencyProperty.UnsetValue
? new[] { parsedValue }
: new[] { System.Convert.ChangeType(value, targetType, culture) };
} catch {
return null;
}
}
// Some types have Parse methods that are more successful than their type converters at converting strings
private static object TryParse(object value, Type targetType, CultureInfo culture)
{
object result = DependencyProperty.UnsetValue;
string stringValue = value as string;
if (stringValue != null) {
try {
MethodInfo mi;
if (culture != null
&& (mi = targetType.GetMethod("Parse",
BindingFlags.Public | BindingFlags.Static, null,
new[] { typeof(string), typeof(NumberStyles), typeof(IFormatProvider) }, null))
!= null) {
result = mi.Invoke(null, new object[] { stringValue, NumberStyles.Any, culture });
}
else if (culture != null
&& (mi = targetType.GetMethod("Parse",
BindingFlags.Public | BindingFlags.Static, null,
new[] { typeof(string), typeof(IFormatProvider) }, null))
!= null) {
result = mi.Invoke(null, new object[] { stringValue, culture });
}
else if ((mi = targetType.GetMethod("Parse",
BindingFlags.Public | BindingFlags.Static, null,
new[] { typeof(string) }, null))
!= null) {
result = mi.Invoke(null, new object[] { stringValue });
}
} catch (TargetInvocationException) {
}
}
return result;
}
}
这是一个很好的建议。我得看看这个。我很希望有一个解决方案不涉及自定义控件,但我肯定对它开放。我会在一点研究后再回来看看。 – 2010-06-24 15:32:39
我试图做同样的事情,但我不知道如何设置附加的属性来处理这个问题。我发布了一个新问题:http://stackoverflow.com/q/24119097/65461 – 2014-06-09 11:40:07