Question

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

Was it helpful?

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>

OTHER TIPS

As per your description, "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."

Here, the Convert method will only be called when the binding with the Text property of TextBox changes. Since, you have mentioned Mode=TwoWay for binding, when you enter any text in textbox, the ConvertBack method will be called and the value returned from this method will be assigned to the Source, which, in your case, is SelectedEntity.Amount.

I do not understand why we need to explicitly write the GetBindingExpression(TextBox.TextProperty).UpdateSource(); code on lost focus to update the source.

Ideally, since you have kept the binding mode Two way, it should update the source after calling the ConvertBack method of Converter. The converter code looks ok to me.

Let me know if you need more details or if there is something that I may have misunderstood, please clarify on those points.

If you update manually the binding in the TextChanged event, like this:

GetBindingExpression(TextBox.TextProperty).UpdateSource();

maybe the value you will get in the LostFocus event will not be different from which one you updated in the TextChanged event!

So, probably the converter will not be called, just because the value in the binding is not changed!

Hope this helps!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top