Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF TextBox MaxLength -- Is there any way to bind this to the Data Validation Max Length on the bound field?

ViewModel:

public class MyViewModel
{
    [Required, StringLength(50)]
    public String SomeProperty { ... }
}

XAML:

<TextBox Text="{Binding SomeProperty}" MaxLength="50" />

Is there any way to avoid setting the MaxLength of the TextBox to match up my ViewModel (which could change since it is in a different assembly) and have it automatically set the max length based on the StringLength requirement?

like image 756
michael Avatar asked Jan 05 '12 15:01

michael


People also ask

What is the maximum length of TextBox?

The default is 32767.

What is the default value of MaxLength property of Text box control?

The maximum number of characters that can be manually entered into the text box. The default is 0, which indicates no limit.


1 Answers

I used a Behavior to connect the TextBox to its bound property's validation attribute (if any). The behavior looks like this:

/// <summary>
/// Set the maximum length of a TextBox based on any StringLength attribute of the bound property
/// </summary>
public class RestrictStringInputBehavior : Behavior<TextBox>
{
    protected override void OnAttached()
    {
        AssociatedObject.Loaded += (sender, args) => setMaxLength();
        base.OnAttached();
    }

    private void setMaxLength()
    {
        object context = AssociatedObject.DataContext;
        BindingExpression binding = AssociatedObject.GetBindingExpression(TextBox.TextProperty);

        if (context != null && binding != null)
        {
            PropertyInfo prop = context.GetType().GetProperty(binding.ParentBinding.Path.Path);
            if (prop != null)
            {
                var att = prop.GetCustomAttributes(typeof(StringLengthAttribute), true).FirstOrDefault() as StringLengthAttribute;
                if (att != null)
                {
                    AssociatedObject.MaxLength = att.MaximumLength;
                }
            }
        }
    }
}

You can see, the behavior simply retrieves the data context of the text box, and its binding expression for "Text". Then it uses reflection to get the "StringLength" attribute. Usage is like this:

<UserControl
    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"

    <TextBox Text="{Binding SomeProperty}">
        <i:Interaction.Behaviors>
            <local:RestrictStringInputBehavior />
        </i:Interaction.Behaviors>
    </TextBox>

</UserControl>

You could also add this functionality by extending TextBox, but I like using behaviors because they are modular.

like image 57
McGarnagle Avatar answered Sep 18 '22 14:09

McGarnagle