Reputation: 8852
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...
Upvotes: 1
Views: 1291
Reputation: 37060
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.
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!
Upvotes: 3