简体   繁体   中英

How can I get the binding object of TextProperty through an attached Property

I have a class called TxtBox with an attached Property:

public class TxtBox
{
    public static readonly DependencyProperty TypeProperty = DependencyProperty.RegisterAttached(
        "Type", typeof (Enums.FieldType), typeof (TextBox), new PropertyMetadata(default(Enums.FieldType),OnTypeChanged));

    public static void SetType(DependencyObject element, Enums.FieldType value)
    {
        element.SetValue(TypeProperty, value);
    }

    public static Enums.FieldType GetType(DependencyObject element)
    {
        return (Enums.FieldType) element.GetValue(TypeProperty);
    }

    private static void OnTypeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var src = (TextBox) d; //(FrameworkElement)d;
        var binding = BindingOperations.GetBinding(src, TextBox.TextProperty);
        if (binding != null) //Binding here is always null ?????????
        {
            binding.Converter = new NumberConverter();
            binding.ConverterParameter = e.NewValue;
        }
    }
}

At MainWindow.xaml :

<Grid Margin="10">
   <TextBox Text="{Binding RequestNo}"  att:TxtBox.Type="Number" />
<\Grid>

I need to assign the Converter and ConverterParameter for the TextProperty once I have set the type for the textbox control through the attached property (Type). When the OnTypeChanged method fires, I can't get the Binding, as it is always null !!!

Thanks in advance :)

Your attached property is being set before the Binding is applied to the Text property of the Text box. You can work around this by attempting to update the Binding when the value of Text changes:

private static void OnTypeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var src = (TextBox)d;

    var dpd = DependencyPropertyDescriptor.FromProperty(TextBox.TextProperty, typeof(TextBox));

    dpd.AddValueChanged(src, UpdateBindingHandler);

    UpdateBinding(src);
}

protected static void UpdateBindingHandler(object sender, EventArgs e)
{
    UpdateBinding((TextBox)sender);
}

private static void UpdateBinding(TextBox tbox)
{
    var binding = BindingOperations.GetBinding(tbox, TextBox.TextProperty);

    if (binding != null)
    {
        binding.Converter = new NumberConverter();
        binding.ConverterParameter = GetType(tbox);

        var dpd = DependencyPropertyDescriptor.FromProperty(TextBox.TextProperty, typeof(TextBox));

        //  Don't do this every time the value changes, only the first time 
        //  it changes after TxtBox.Type has changed. 
        dpd.RemoveValueChanged(tbox, UpdateBindingHandler);
    }
}

When you do that, you'll find that your whole design is flawed: You can't alter a Binding once it's been used. It throws an exception.

You might be able to get away with creating a new binding, clone the properties of the old one, and put a converter on it. Bindings have a lot of properties, though, and if there's already a converter, you'll need to replace it with a chain converter that preserves that one while adding yours.

I'm not sure this feature is going to work out.

Finally,I have got the solution, I changed the design as Mr Peter Duniho advised me to write a markup extension to take the place of the {Binding}

public class TextBoxTypeExtension:MarkupExtension
    {
        private readonly Binding _binding;
        public TextBoxTypeExtension(Binding binding,Enums.FieldType type)
        {
            _binding = binding;
            _binding.Converter = new NumberConverter();
            _binding.ConverterParameter = type;
        }
        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            return _binding.ProvideValue(serviceProvider);
        }
    }

At MainWindow.xaml :

  <TextBox  MaxLength="10" Grid.Row="1" Grid.Column="1"
                        Text="{extension:TextBoxType {Binding Request.RequestNo},Number}"/>

Reference: MarkupExtension that uses a DataBinding value

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM