DataContextChanged для Tab в TabControl вызывается слишком рано - PullRequest
2 голосов
/ 28 сентября 2010

У меня есть привязка TabControl к некоторым элементам.Под ней находится кнопка, где я могу добавлять элементы динамически.При добавлении элемента, новый элемент должен стать активной вкладкой (прекрасно работает с 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>

Код позади:

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; } }
}

UserControl1 выглядит следующим образом:

<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>

И его код должен выделять _textBox и выбирать весь текст, когда пользователь нажимает на вкладку:

using System.Windows;

namespace WpfApplication1
{
    public partial class UserControl1
    {
        public UserControl1()
        {
            InitializeComponent();
        }

        private void OnDataContextChanged(object sender,
                                          DependencyPropertyChangedEventArgs e)
        {
            _textBox.Focus();
            _textBox.SelectAll();
        }
    }
}

Я пытаюсь добиться этого с помощью события DataContextChanged, но из-за его непредсказуемости (sf http://msdn.microsoft.com/en-us/library/system.windows.frameworkelement.datacontextchanged.aspx), он не работает все время. Я также пробовал это с событием Loaded, но это будет вызываться только один раз, когда загружается DataTemplate.

Итак, я думаю, что мне нужно получать событие Loaded каждый раз, когда DataContext изменяется и механизм привязки данных завершает свою работу. Есть ли такое событие?

1 Ответ

0 голосов
/ 23 августа 2011

Вы хотите выделить текст, когда пользователь добавляет вкладку И когда пользователь нажимает на другую вкладку?

В этом случае вам может потребоваться обработать это с помощью двух обработчиков событий - событие изменения вкладки для элемента управления вкладкой - и затем установить его в коде при добавлении нового элемента.

DataContext в соответствии с вашим кодом не изменяется. Он устанавливается в главное окно, а затем наследуется до дочерних элементов управления.

    public MainWindow()
    {
        Items = new ObservableCollection<Foo>();
        Items.Add(new Foo {Bar = "bar"});

        InitializeComponent();
        DataContext = this;
    }
...