silverlightconverterslostfocus

Decimal Converter in Silverlight is not working on Lost Focus properly


I m using the binding in Silverlight. I have binded the TextBox with Decimal entity. Below is the Code snipts of bindings.

<TextBox x:Name="AmountBox" Text="{Binding SelectedEntity.Amount,Mode=TwoWay,StringFormat=\{0:n2\},Converter={StaticResource DecimalBlankValueConverter}}" Validate="True" TextChanged="AmountBox_TextChanged" LostFocus="AmountBox_LostFocus"/>

Below is the converter code.

    decimal result;
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {            
        if (!Decimal.TryParse(value.ToString(),out result) || (decimal)value == decimal.Zero)
            return null;
        return decimal.Parse(value.ToString());
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value == null || !Decimal.TryParse(value.ToString(), out result))
            return 0.00;
        return decimal.Parse(value.ToString());
    }

on lost focus I am updating the source with GetBindingExpression(TextBox.TextProperty).UpdateSource();

Everything is workig well, But convert is not called on lost focus and when I am entering string in the textbox, than convert is not called and it will not convert the textBox text to blank.

Can anyone please suggest me , what is the probelm in the code.

Thanks in advance. ----Raj


Solution

  • TwoWay mode binding with TextChanged and LostFocus events are definitely not the best approach. Why do you call GetBindingExpression(TextBox.TextProperty).UpdateSource(); in the LostFocus if binding does it by default? If you want to update a binding manually, set UpdateSourceTrigger=Explicit.

    Anyway your converter seems fine, but I think you don't need it. If I understand right, you want to clear the text if it cannot be cast to decimal. In that case you have a few options, like creating your custom TextBox that allows only digits, or you can check NumericUpDown control from Silverlight Toolkit. Also I've found similar question here.

    If you have installed Microsoft Expression Blend (if don't, you can download BlendSLSDK_en.msi from Microsoft Expression Blend Software Development Kit), add System.Windows.Interactivity dll to your project and create simple Behavior like this:

    public class TextBoxClearTextBehavior : System.Windows.Interactivity.Behavior<System.Windows.Controls.TextBox>
    {
        protected override void OnAttached()
        {
            AssociatedObject.LostFocus += AssociatedObjectLostFocus;
            base.OnAttached();
        }
    
        protected override void OnDetaching()
        {
            AssociatedObject.LostFocus -= AssociatedObjectLostFocus;
            base.OnDetaching();
        }
    
        private void AssociatedObjectLostFocus(object sender, System.Windows.RoutedEventArgs e)
        {
            decimal result;
            if (!decimal.TryParse(AssociatedObject.Text, out result))
                AssociatedObject.Text = string.Empty;
        }
    }
    

    and use it like

    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
    
    ...    
    
    <TextBox Text="{Binding Amount, Mode=TwoWay, StringFormat=\{0:n2\}}">
        <i:Interaction.Behaviors>
            <Behavior:TextBoxClearTextBehavior/>
        </i:Interaction.Behaviors>
    </TextBox>