DataContextChanged of a Tab in a TabControl is raised too early
I have a TabControl binding to some items. Underneath it is a Button where I can add items dynamically. On adding an item, the new item should become the active Tab (works fine with TabControl.SelectedItem):
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:this="clr-namespace:WpfApplication1"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<TabControl ItemsSource="{Binding Items}"
SelectedItem="{Binding SelectedItem, Mode=OneWay}">
<TabControl.ContentTemplate>
<DataTemplate>
<this:UserControl1 />
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
<Button Content="Foo" Click="Button_Click"/>
</StackPanel>
</Window开发者_运维问答>
Code-behind:
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Windows;
namespace WpfApplication1
{
public partial class MainWindow : INotifyPropertyChanged
{
public ObservableCollection<Foo> Items { get; set; }
public Foo SelectedItem { get { return Items.Last(); } }
public event PropertyChangedEventHandler PropertyChanged;
public MainWindow()
{
Items = new ObservableCollection<Foo>();
Items.Add(new Foo {Bar = "bar"});
InitializeComponent();
DataContext = this;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Items.Add(new Foo {Bar = "bar"});
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("Items"));
PropertyChanged(this, new PropertyChangedEventArgs("SelectedItem"));
}
}
}
public class Foo { public string Bar { get; set; } }
}
The UserControl1 looks like this:
<UserControl x:Class="WpfApplication1.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel>
<TextBox/>
<TextBox x:Name="_textBox"
DataContextChanged="OnDataContextChanged"
Text="{Binding Bar}" />
</StackPanel>
</UserControl>
And the code-behind of it should focus _textBox and selectAll its text when the user clicks on the tab:
using System.Windows;
namespace WpfApplication1
{
public partial class UserControl1
{
public UserControl1()
{
InitializeComponent();
}
private void OnDataContextChanged(object sender,
DependencyPropertyChangedEventArgs e)
{
_textBox.Focus();
_textBox.SelectAll();
}
}
}
I try to achieve that with the DataContextChanged-event, but due to its unpredictability (s.f. http://msdn.microsoft.com/en-us/library/system.windows.frameworkelement.datacontextchanged.aspx), it doesn't work all the time. I also tried it with the Loaded-event, but this will be called only once when the DataTemplate is loaded.
So, I think I need to receive the Loaded-event every time the DataContext has changed and the data-binding engine has finished its job. Is there such an event?
Are you wanting to select the text when the user adds a tab AND when the user clicks on a different tab?
If this is the case you may want to to handle this with two event handlers - The tab changed event for the tab control - and then setting it in code when you add a new item.
The DataContext according to your code does not change. It is set to the main window and then inherited down to the child controls.
public MainWindow()
{
Items = new ObservableCollection<Foo>();
Items.Add(new Foo {Bar = "bar"});
InitializeComponent();
DataContext = this;
}
精彩评论