I was on to implement a UserControl
called PhoneBox that contains a single TextBox
, some custom logic, and has a DependencyProperty called PhoneNo. It was to be used in in a two-way binding scenario with a LostFocus
for UpdateSourceTrigger
. So I wrote the following code -
XAML (UserControl):
<StackPanel>
<TextBox Name="txtPhone" MinWidth="120" MinHeight="23" LostFocus="txtPhone_LostFocus" GotFocus="txtPhone_GotFocus"/>
</StackPanel>
Code-Behind (UserControl):
public partial class PhoneBox : UserControl
{
//Some Code
static PhoneBox()
{
FrameworkPropertyMetadata phoneNoMetadata =
new FrameworkPropertyMetadata(new PropertyChangedCallback(OnPhoneNoChanged),
new CoerceValueCallback(CoercePhoneNoValue));
PhoneNoProperty = DependencyProperty.Register("PhoneNo", typeof (string), typeof (PhoneBox),
phoneNoMetadata,
new ValidateValueCallback(ValidatePhoneNoValue));
}
public readonly static DependencyProperty PhoneNoProperty;
public string PhoneNo
{
get { return (string)GetValue(PhoneNoProperty); }
set { SetValue(PhoneNoProperty, value); }
}
private static void OnPhoneNoChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
PhoneBox phoneBox = (PhoneBox)d;
string newValue = (string)e.NewValue;
phoneBox.txtPhone.Text = newValue;
}
private static object CoercePhoneNoValue(DependencyObject d, object basevalue)
{
return basevalue;
}
private static bool ValidatePhoneNoValue(object value)
{
return true;
}
private void txtPhone_LostFocus(object sender, RoutedEventArgs e)
{
this.SetValue(PhoneNoProperty, this.txtPhone.Text);
}
private void txtPhone_GotFocus(object sender, RoutedEventArgs e)
{
if (!String.IsNullOrEmpty(txtPhone.Text))
this.txtPhone.Text = this.FilterText(txtPhone.Text);
}
private string FilterText(string text)
{
//Some cutom logic
}
//Some more Code
}
XAML (Consumer):
<pbc:PhoneBox PhoneNo="{Binding Path=User.Phone, Mode=TwoWay, UpdateSourceTrigger=LostFocus}"/>
It works. But my question is, the way I used the txtPhone_LostFocus
event handler to set proerty value (and in turn update source), is that appropriate? Is there any more appropriate way to do this? I'm a novice in this DependencyProperty
thing, so any guiding, suggestion, comments will be thankfully appreciated.
The WPF way to handle this situation is to have a Binding between your UserControl's DependencyProperty
and the TextBox
declared in the UserControl's XAML file. This is also where you would set the LostFocus UpdateSourceTrigger
(which you don't have to, since it is the default behaviour). You'd declare the Binding on the TextBox
(i.e. inside the UserControl), so client code using the UserControl would be free to set another binding on the PhoneNo property (from outside of the UserControl). Also, if your CoerceValue callback only returns the base value, better go without it from the start.
This might be what David meant initially...