Reputation: 1440
I want to make a string DependencyProperty
which can handle assigning to a nullable number value (like the textbox TextProperty
does).
I basically copied the decompiled code from TextBox
and changed it for the DependencyProperty
I was creating.
[DefaultValue(null)]
//[DefaultValue(string.Empty)]
[Localizability(LocalizationCategory.Text)]
public string Number
{
get { return (string)GetValue(NumberProperty); }
set { SetValue(NumberProperty, value); }
}
public static readonly DependencyProperty NumberProperty =
DependencyProperty.Register(
"Number", // Property name
typeof(string), // Property type
typeof(NumberControl), // Property owner
new FrameworkPropertyMetadata( // Property metadata
null, // default value
//string.Empty, // default value
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault | // Flags
FrameworkPropertyMetadataOptions.Journal,
OnNumberPropertyChanged, // property changed callback
CoerceText,
true, // IsAnimationProhibited
UpdateSourceTrigger.PropertyChanged // DefaultUpdateSourceTrigger
));
private static object CoerceText(DependencyObject d, object value)
{
var sv = value as string;
if (sv == String.Empty) return null;
return value;
//if( value == null) return string.Empty;
}
private static void OnNumberPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var tb = (NumberControl) d;
if (tb.Number != tb.Text)
{
tb.Text = tb.Number;
}
}
However when binding this property to a decimal? this is the exception which occurs
System.Windows.Data Error: 7 : ConvertBack cannot convert value '' (type 'String'). BindingExpression:Path=DecimalProperty; DataItem='MainWindowViewModel' (HashCode=58431997); target element is 'NumberControl' (Name=''); target property is 'Number' (type 'String') FormatException:'System.FormatException: Input string was not in a correct format.
at System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal)
at System.Number.ParseDecimal(String value, NumberStyles options, NumberFormatInfo numfmt)
at System.Convert.ToDecimal(String value, IFormatProvider provider)
at System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider)
at System.Windows.Data.BindingExpression.ConvertBackHelper(IValueConverter converter, Object value, Type sourceType, Object parameter, CultureInfo culture)'
Note: I tried leaving the default string.empty behaviour which didn't work, and the code I've provided tries null which also doesn't work
Is there some way that TextBox.Text
has specified some other default converter?
Upvotes: 1
Views: 1048
Reputation: 1440
Quick Answer
You need to set the DependancyProperty
directly to null
with in the PropertyChangedCallback
method specified for that DependancyProperty
so that it doesn't use the default converter.
So in my case the OnNumberPropertyChanged
method which is being used as the PropertyChangedCallback
in the DependancyProperty
needed to call
tb.SetValue(NumberProperty, null);
Long Answer
Damn I found this question and answer after posting my question, that question wasn't really phrased in a way that my searching came up with until I'd posted "default converter" at the end of my question.
The way I got it working was to manually set the DependancyProperty
value to null
at the appropriate time with the code:
if (tb.Number == null)
{
tb.SetValue(NumberProperty, null);
}
So the full OnNumberPropertyChanged method is:
/// <summary>
/// Callback for changes to the Number property
/// </summary>
private static void OnNumberPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var tb = (NumberControl) d;
if (tb.Number != tb.Text)
{
tb.Text = tb.Number;
}
if (tb.Number == null)
{
tb.SetValue(NumberProperty, null);
}
}
Upvotes: 2