2014-10-21 2 views
0

В приложении WPF, построенном по принципу MVVM, мне нужно явно установить фокус на TextBox из кода (реагировать на событие клавиатуры), а также узнать, имеет ли фокус были потеряны. Из другого вопроса здесь я собрал, что, по-видимому, способ сделать это заключается в привязке данных к DependencyProperty. Для этого я взял следующий код:Двунаправленная привязка текстового поля с DependencyProperty

public static class FocusHelper 
{ 
    public static bool GetIsFocused(DependencyObject obj) 
    { 
     return (bool)obj.GetValue(IsFocusedProperty); 
    } 

    public static void SetIsFocused(DependencyObject obj, bool value) 
    { 
     obj.SetValue(IsFocusedProperty, value); 
    } 

    public static readonly DependencyProperty IsFocusedProperty = 
     DependencyProperty.RegisterAttached(
      "IsFocused", typeof(bool), typeof(FocusHelper), 
      new UIPropertyMetadata(false, OnIsFocusedPropertyChanged)); 

    private static void OnIsFocusedPropertyChanged(DependencyObject d, 
     DependencyPropertyChangedEventArgs e) 
    { 
     var uie = (UIElement)d; 
     if ((bool)e.NewValue) 
     { 
      uie.Focus(); 
     } 
    } 
} 

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

<TextBox Text="{Binding Path=RowData.Row.Group}" helper:FocusHelper.IsFocused="{Binding RowData.Row.GroupFocused, Mode=TwoWay}" 

Это в (DevExpress) сетки; - это фактический ViewModel, к которому привязана вся строка.

Соответствующий код в связанном ViewModel:

private bool groupFocused; 

public bool GroupFocused 
{ 
    get { return this.groupFocused; } 

    set 
    { 
     this.groupFocused = value; 
     this.NotifyOfPropertyChange(() => this.GroupFocused); 
    } 
} 

Когда событие клавиатуры обрабатывается, GroupFocused устанавливается истина, которая достаточно уверен, вызывает функцию обратного вызова DependencyProperty и устанавливает фокус на TextBox. Однако, когда элемент управления теряет фокус, это изменение не возвращается обратно в ViewModel (обратный вызов DependencyProperty также не вызывается).

Есть ли очевидная причина такого поведения? Что-то не так с кодом?

(я попытался добавить UpdateSourceTrigger как с PropertyChanged и LostFocus на связывание, а также изменения значения DependencyProperty по умолчанию true, ни один из которых изменилось ничего о поведении. Я также попытался IsKeyboardFocused вместо IsFocused без изменения, и IsKeyboardFocusWithin , который сделал заявку близко без комментариев - вероятно исключение DevExpress -. по монтажу сетки)

+0

Я не вижу никакой связи между фактической 'IsFocused' (от' TextBox', не ваш вспомогательного класса) (или некоторый обработчик для фокусировки события) и свойство ViewModel здесь. Итак, как он мог отразить это в viewmodel? –

+0

Насколько я понимаю, эта ссылка создана с использованием 'IsFocused' как имя DependencyProperty и привязывает ее к GroupFocused в ViewModel - и эта ссылка существует, потому что привязка работает в одном направлении. – TeaDrivenDev

+0

Я имею в виду фактический 'IsFocused' вашего' TextBox'. Когда изменяется информация о фокусировке TextBox, это единственный источник для получения этого состояния. Здесь мы не видим, что источник существует. Другими словами, теперь у вас есть способ установить состояние фокусировки, но не получить его. –

ответ

0

вы не связывание данных вашего GroupFocused имущества в TextBox.IsFocused собственности, вы данных привязывая его к FocusHelper.IsFocused собственности, которой программно вызывает Focus на TextBox.

Существует четкое различие. Вызов Focus метода на результате TextBoxбудет в TextBox.IsFocused имуществе, устанавливается в true, но нет никакой связи между этим свойством и либо ваши GroupFocused или ваших FocusHelper.IsFocused свойствами, поэтому ни один не будет установлено в false, когда свойство TextBox.IsFocused не установлено до false.

Кроме того, вы не можете привязать данные к свойству TextBox.IsFocused, чтобы установить фокус, потому что он доступен только для чтения. Дополнительную информацию об этом см. На странице UIElement.IsFocused Property на MSDN.

Однако есть простое решение. Это может показаться не очень красивым, но это, безусловно, будет работать ... просто установите для свойства GroupFocused значение false, прежде чем вы установите его значение true. Возможно, что-то вроде этого:

private void FocusTextBox() 
{ 
    GroupFocused = false; 
    GroupFocused = true; 
} 

...

FocusTextBox(); 
+0

Думаю, я начинаю понимать. Установка свойства 'false' непосредственно перед установкой его в' true' ничего не меняет. (Я также не понимаю, почему вы ожидаете этого.) – TeaDrivenDev

+0

Вы не совсем правы, это * делает * сделать одно дело ... установка свойства 'false' просто позволяет вам установить его в true 'снова после. Когда он уже «истинный», вы просто не можете установить его в «true» и вызвать вызов «Фокус». – Sheridan

+0

Я хотел сказать, что я попробовал, и это не меняет поведения. Проблема в том, что я еще не упомянул, что есть другой код, который зависит от того, имеет ли текстовое поле фокус, поэтому мне нужно иметь возможность запрашивать текущий статус в любое время. – TeaDrivenDev

Смежные вопросы