Reputation: 103
I tried to create a TabItem
with a TextBox
in it from this article.
I found out that the TabItem
Header is NOT bind to the TextBox
.
private void MenuItem_Click(object sender, RoutedEventArgs e)
{
TabItem ti = new TabItem();
DataTemplate tabItemTemplate = new DataTemplate();
tabItemTemplate.DataType = typeof(TabItem);
FrameworkElementFactory textBoxFactory = new FrameworkElementFactory(typeof(TextBox));
textBoxFactory.SetBinding(TextBox.TextProperty, new Binding("."));
textBoxFactory.SetValue(NameProperty, "textBox");
textBoxFactory.SetValue(BorderThicknessProperty, new Thickness(0));
//textBoxFactory.SetValue(IsEnabledProperty, false);
tabItemTemplate.VisualTree = textBoxFactory;
ti.Header = "Test!";
ti.HeaderTemplate = tabItemTemplate;
ti.MouseDoubleClick += TabItem_MouseDoubleClick;
tabControl.Items.Add(ti);
}
private void TabItem_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
MessageBox.Show((sender as TabItem).Header.ToString());
}
Could somebody please be so kind and teach me how to bind it correctly?
Much appreciated!
Upvotes: 0
Views: 149
Reputation: 7918
Complementing @BionicCode's answer
The problem with your original binding is that you are pointing to the current Data Context.
Your binding is equivalent to an empty Binding "new Binding ();".
Thus, you get a binding not to a property, but to a source (The default source is the current Data Context).
But the binding can only change the property of the source, not the source itself.
The Header template is applied to the contents of the TabItem's Header property.
Therefore, to get the same value, but not as a source of the binding, but as a property in the Path of the binding, you need to go up to the TabItem level.
@BionicCode in his answer showed you examples of such bindings.
I will offer another option for integration into your code:
private static readonly DataTemplate headerTemplate = (DataTemplate)XamlReader.Parse
(@"
<DataTemplate xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
<TextBox x:Name='textBox'
Text='{Binding Header,
RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TabItem}},
UpdateSourceTrigger=PropertyChanged}'
BorderThickness='0'/>
</DataTemplate>
");
private void MenuItem_Click(object sender, RoutedEventArgs e)
{
TabItem ti = new TabItem();
ti.Header = "Test!";
ti.HeaderTemplate = headerTemplate;
ti.MouseDoubleClick += TabItem_MouseDoubleClick;
tabControl.Items.Add(ti);
}
Upvotes: 1
Reputation: 28988
Your Binding
configuration is wrong.
new Binding(".")
is missing the Binding.Source
.
It should be:
var binding = new Binding("Header") { Source = ti };
The following example replicates your C# code
<TabControl>
<TabItem Header="Test" MouseDoubleClick="TabItem_MouseDoubleClick" >
<TabItem.HeaderTemplate>
<DataTemplate>
<TextBox x:Name="textBox"
Text="{Binding RelativeSource={RelativeSource AncestorType=TabItem}, Path=Header}" />
</DataTemplate>
</TabItem.HeaderTemplate>
</TabItem>
</TabControl>
Upvotes: 1