I was recently working on an MVVM project where various validation attributes were being set on the data model, and was looking for a solution to bind WPF editor control properties to these validation restrictions. (e.g. Setting TextBox.MaxLength based on StringLengthAttribute.)

Combining a couple of Stack Overflow posts:

This can be extended for arbitrary attributes and controls, but the example below deals specifically with TextBox.MaxLength and StringLengthAttribute.

We can set the style globally in a resource dictionary:

<Style TargetType="TextBox" x:Key="DefaultTextBoxStyle">
    <Setter Property="helpers:AttributePropertyExtension.AttributeProperty" Value="True" />
</Style>

We then have a class to apply the behavior:

namespace EliMarshal.ClassLibrary.AttributePropertyHelper
{
    using System.Linq;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Interactivity;

    /// <summary>
    /// Extension to set properties on WPF controls based on attributes on their binding properties
    /// </summary>
    public static class AttributePropertyExtension
    {
        /// <summary>
        /// DependencyProperty set on every control to affect
        /// </summary>
        public static readonly DependencyProperty AttributeProperty = DependencyProperty.RegisterAttached(
             "AttributeProperty", typeof(bool), typeof(AttributePropertyExtension), new UIPropertyMetadata(false, OnAttributePropertyChanged));

        /// <summary>
        /// Gets the AttributeProperty DependencyProperty
        /// </summary>
        /// <param name="obj">The framework element object.</param>
        /// <returns>true if the specified value is valid; otherwise, false.</returns>
        public static bool GetAttributeProperty(FrameworkElement obj)
        {
            return (bool)obj.GetValue(AttributeProperty);
        }

        /// <summary>
        /// Sets the AttributeProperty DependencyProperty
        /// </summary>
        /// <param name="obj">The framework element object.</param>
        /// <param name="value">The value to set AttributeProperty to.</param>
        public static void SetAttributeProperty(FrameworkElement obj, bool value)
        {
            obj.SetValue(AttributeProperty, value);
        }

        /// <summary>
        /// Assigns the AttributeProperty to the control when AttributeProperty changes.
        /// </summary>
        /// <param name="d">The DependencyObject.</param>
        /// <param name="e">The DependencyPropertyChangedEventArgs.</param>
        private static void OnAttributePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var uie = (UIElement)d;
            if ((bool)e.NewValue && uie.Dispatcher != null)
            {
                if (uie is TextBox)
                {
                    AssignAttributePropertyToControl<Control>(d, e);
                }

                uie.SetValue(AttributeProperty, false);
            }
        }

        // Use this space for a different dependency property added to a different type of control in xaml

        /// <summary>
        /// Adds the AttributePropertyBehavior to the AttributeProperty
        /// </summary>
        /// <typeparam name="T">The first generic type parameter.</typeparam>
        /// <param name="d">The DependencyProperty AttributeProperty.</param>
        /// <param name="e">The DependencyPropertyChangedEventArgs for AttributeProperty.</param>
        private static void AssignAttributePropertyToControl<T>(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var behaviors = Interaction.GetBehaviors(d);

            if (!behaviors.OfType<AttributePropertyBehavior>().Any())
            {
                behaviors.Add(new AttributePropertyBehavior());
            }
        }

        /// <summary>
        /// The behavior to set the attribute property on the control.
        /// </summary>
        private class AttributePropertyBehavior : Behavior<DependencyObject>
        {
            /// <summary>
            /// When attached, sets the binding attribute property on the control.
            /// </summary>
            protected override void OnAttached()
            {
                if (AssociatedObject is Control)
                {
                    (AssociatedObject as Control).Loaded += (sender, args)
                        => AttributePropertySetter.SetAttributeProperty(AssociatedObject as Control);
                }

                // Use this space to set AttributeProperty to different types than Control, i.e. FrameworkContentElement
                base.OnAttached();
            }
        }
    }
}

And finally a class to set the property on the control:

namespace EliMarshal.ClassLibrary.AttributePropertyHelper
{
    using System;
    using System.ComponentModel.DataAnnotations;
    using System.Linq;
    using System.Reflection;
    using System.Windows.Controls;
    using System.Windows.Data;

    /// <summary>
    /// Sets the binding attribute property value on the editor control.
    /// </summary>
    public static class AttributePropertySetter
    {
        /// <summary>
        /// Sets the binding attribute property value on the editor control.
        /// </summary>
        /// <param name="editor">The editor control.</param>
        public static void SetAttributeProperty(Control editor)
        {
            object context = editor.DataContext;
            BindingExpression binding = GetBindingExpression(editor);
            if (context == null || binding == null)
            {
                return;
            }

            if (binding.ResolvedSourcePropertyName != null && binding.ResolvedSource != null)
            {
                PropertyInfo prop = binding.ResolvedSource.GetType().GetProperty(binding.ResolvedSourcePropertyName);
                AssignAttributePropertyFromProperty(editor, prop);
                return;
            }

            // Can't effectively test this as is, as .GetProperty() can't be intercepted
            PropertyInfo itemProp = context.GetType().GetProperty("Item");
            if (itemProp != null && itemProp.GetSetMethod() != null)
            {
                var item = itemProp.GetValue(context);
                if (item != null)
                {
                    PropertyInfo prop = item.GetType().GetProperty(binding.ParentBinding.Path.Path);
                    AssignAttributePropertyFromProperty<Control>(editor, prop);
                }
            }
        }

        // Use this space for alternate SetAttributeProperty methods with different paramaters, i.e. FrameworkContentElement rather than Control

        /// <summary>
        /// Gets the binding expression for the editor.
        /// </summary>
        /// <param name="editor">The editor control.</param>
        /// <returns>BindingExpression for the TextProperty if the editor is a TextBox, ArgumentException otherwise.</returns>
        private static BindingExpression GetBindingExpression(Control editor)
        {
            if (editor is TextBox)
            {
                return editor.GetBindingExpression(TextBox.TextProperty);
            }
            else
            {
                throw new ArgumentException("Not a valid control type.");
            }

            // Use the above flow to get binding expressions for editors and properties other than TextBox.TextProperty
        }

        /// <summary>
        /// Sets the property on the editor based on the binding property attribute.
        /// </summary>
        /// <typeparam name="T">The first generic type parameter.</typeparam>
        /// <param name="editor">The editor control.</param>
        /// <param name="prop">The bound property.</param>
        private static void AssignAttributePropertyFromProperty<T>(T editor, PropertyInfo prop)
        {
            if (prop != null)
            {
                if (Attribute.GetCustomAttributes(prop, typeof(StringLengthAttribute), true).FirstOrDefault() is StringLengthAttribute stringLengthAtt)
                {
                    if (editor is TextBox)
                    {
                        (editor as TextBox).MaxLength = stringLengthAtt.MaximumLength;
                    }

                    // Use this space set property to different editor types and/or properties other than TextBox.MaxLength
                }

                // Use this space to get different custom attributes other than StringLengthAttribute
            }
        }
    }
}