Невозможно сфокусировать кнопку, которая находится в шаблоне данных - PullRequest
0 голосов
/ 07 февраля 2012

У меня есть кнопка, которая находится в DataTemplate в расширенном наборе инструментов BusyIndicator. У меня есть триггер данных (и я попробовал триггер стиля), связанный с видимостью элемента управления BusyIndicator, чтобы FocusManager установил фокус на кнопку, когда BusyIndicator видим.
Это не работает. Я также пытался обработать событие IsVisibleChanged на BusyIndicator, чтобы установить фокус на кнопке в выделенном фрагменте кода, обходя визуальное дерево, и это тоже не сработало. Есть ли какой-нибудь особый способ настройки фокуса клавиатуры на кнопке?

Ответы [ 2 ]

1 голос
/ 07 февраля 2012

Я думаю, у меня была такая же проблема.Вот код, который я использовал:

public delegate void SimpleDelegate();
private void grid_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
    if (grid.Visibility == System.Windows.Visibility.Visible)
    {
        TextBox tb = (TextBox)(sender as Grid).FindName("theTextbox");

        tb.SelectAll();
        Dispatcher.BeginInvoke(DispatcherPriority.Input, new SimpleDelegate(delegate { tb.Focus(); }));
    }
}

Этот код также выделяет весь текст, когда отображается сетка, содержащая текстовое поле.

Возможно, есть лучший способ сделать это, но используяДиспетчер для установки фокуса, казалось, работал на меня.

0 голосов
/ 07 февраля 2012

Эта статья SO описывает, как вы можете выбрать контейнер элемента в ItemsControl и перемещаться по дереву, чтобы выбрать элемент, который вы хотите изменить (в данном случае фокусируясь на нем).

Пересмотр моего кода снизу:

public void WhateverMethodForShowingBusy ()
{
    //Get a reference to your View
    FrameworkElement myView = this.View;  // I generally have a reference to the view living on the ViewModel set at construction time
    // Get a reference to your ItemsControl - in this example by name
    ListBox custListBox = myView.ListBoxName;
    // Get the currently selected Item which will be a CustomerViewModel 
    // (not a DataTemplate or ListBoxItem)
    CustomerViewModel cvm = custListBox.SelectedItem;

    //Generate the ContentPresenter
    ContentPresenter cp = custListBox.ItemContainerGenerator.ContainerFromItem(cvm) as ContentPresenter;

    //Now get the button and focus it.
    Button myButton = cp.FindName("MyButtonName");
    myButton.Focus();
}

Приведенная ниже информация неверна на основании ошибки, что IsFocused был свойством чтения / записи, которое устанавливало бы фокус. Это не применимо.

Это еще одно место, где MVVM действительно хорошо работает. Если вы не знакомы с MVVM, я настоятельно рекомендую изучить его. Он решает множество подобных проблем и при правильной реализации может сделать ваш код более удобным для обслуживания.

Если вы используете подход MVVM, просто разместите логическое свойство (назовем его IsFocused) в ViewModel, который находится за DataTemplate. Например, у нас есть класс Customer, класс CustomerViewModel, который содержит экземпляр customer, а затем ваш MainViewModel, который содержит коллекцию CustomerViewModels. Свойство ItemsSource вашего ItemsControl привязано к коллекции CustomerViewModels, а свойство IsFocused кнопки DataTemplate привязано к свойству IsFocused в CustomerViewModel.

Я не уверен в вашем рабочем процессе, но вы можете сделать что-то вроде этого:

public void WhateverMethodForShowingBusy ()
{
    //Get a reference to your View
    FrameworkElement myView = this.View;  // I generally have a reference to the view living on the ViewModel set at construction time
    // Get a reference to your ItemsControl - in this example by name
    ListBox custListBox = myView.ListBoxName;
    // Get the currently selected Item which will be a CustomerViewModel 
    // (not a DataTemplate or ListBoxItem)
    CustomerViewModel cvm = custListBox.SelectedItem;

    //Finally set the property.
    cvm.IsFocused = true;
}

Как и во всех вещах в MVVM, убедитесь, что вы реализуете INotifyPropertyChanged.

...