简体   繁体   中英

How to bind UIElements in XAML?

I have a class:

class LinkedTextBox: TextBox
{
    public TextBox TextBoxA { get; set; }
    public TextBox TextBoxB { get; set; }
}

Say I have two Textboxes:

    <TextBox x:Name="txt1" />
    <TextBox x:Name="txt2" />

How do I to specify that TextBoxes on my Xaml?

My tests:

(1) " The TypeConverter for "TextBox" does not support converting from a string. "

    <local:LinkedTextBox TextBoxA="txt1" TextBoxB="txt2" />

(2) " A 'Binding' cannot be set on the 'TextBoxA' property of type 'LinkedTextBox'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject. "

    <local:LinkedTextBox 
        TextBoxA="{Binding ElementName=txt1}"  
        TextBoxB="{Binding ElementName=txt2}"  
        />

I think that there is an obvious way to do, but I don't know how to...

Right. Your second example is correct XAML, but it fails because TextBoxA and TextBoxB are the wrong kind of property. The target of a Binding must be a DependencyProperty of a DependencyObject , like it says on the tin. TextBox is already a DependencyObject and you're subclassing it, so that part's taken care of. And defining a DependencyProperty is trivial.

You would define TextBoxA like this, and TextBoxB likewise:

public class LinkedTextBox : TextBox
{
    #region TextBoxA Property
    public TextBox TextBoxA
    {
        get { return (TextBox)GetValue(TextBoxAProperty); }
        set { SetValue(TextBoxAProperty, value); }
    }

    //  Careful with the parameters you pass to Register() here.
    public static readonly DependencyProperty TextBoxAProperty =
        DependencyProperty.Register("TextBoxA", typeof(TextBox), typeof(LinkedTextBox),
            new PropertyMetadata(null));
    #endregion TextBoxA Property
}

But what is your intent here? What are you trying to accomplish? It's very likely that you can do it by binding existing properties to each other in a normal way, without any of these subclass monkeyshines. Possibly you'd want an attached property , which is a specialized type of dependency property.

UPDATE

OP wants to add visual elements illustrating relationships among the text boxes. If you want to add a visual overlay, the WPF Way to Do That is to write an Adorner . So you'd write some kind of TextBoxLinkingAdorner with TextBoxA and TextBoxB dependency properties, and apply that to the main text box, which depending on your requirements might not even have to be a subclass.

Your dependency properties might need to do some work when their values change; if so, they'd look more like this, assuming an Adorner subclass named TextBoxLinkerAdorner :

    #region TextBoxA Property
    public TextBox TextBoxA
    {
        get { return (TextBox)GetValue(TextBoxAProperty); }
        set { SetValue(TextBoxAProperty, value); }
    }


    public static readonly DependencyProperty TextBoxAProperty =
        DependencyProperty.Register("TextBoxA", typeof(TextBox), 
            typeof(TextBoxLinkerAdorner),
            new FrameworkPropertyMetadata(null,
                    FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                    TextBoxA_PropertyChanged)
                        { DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });

    protected static void TextBoxA_PropertyChanged(DependencyObject d, 
        DependencyPropertyChangedEventArgs e)
    {
        var obj = d as TextBoxLinkerAdorner;
    }
    #endregion TextBoxA Property

If all you're looking at on the text boxes is their size and location, you might write an adorner that links arbitrary UIElements , not just text boxes. The sky's the limit! If you can dream it, you can adorn it!

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