Я знаю, что на этот вопрос уже тысячи раз отвечали, но я внес некоторые изменения в вклад Анваки, который, я думаю, поможет другим, у которых были похожие проблемы.
Во-первых, я изменил указанное выше свойство Attached следующим образом:
public static class FocusExtension
{
public static readonly DependencyProperty IsFocusedProperty =
DependencyProperty.RegisterAttached("IsFocused", typeof(bool?), typeof(FocusExtension), new FrameworkPropertyMetadata(IsFocusedChanged){BindsTwoWayByDefault = true});
public static bool? GetIsFocused(DependencyObject element)
{
if (element == null)
{
throw new ArgumentNullException("element");
}
return (bool?)element.GetValue(IsFocusedProperty);
}
public static void SetIsFocused(DependencyObject element, bool? value)
{
if (element == null)
{
throw new ArgumentNullException("element");
}
element.SetValue(IsFocusedProperty, value);
}
private static void IsFocusedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var fe = (FrameworkElement)d;
if (e.OldValue == null)
{
fe.GotFocus += FrameworkElement_GotFocus;
fe.LostFocus += FrameworkElement_LostFocus;
}
if (!fe.IsVisible)
{
fe.IsVisibleChanged += new DependencyPropertyChangedEventHandler(fe_IsVisibleChanged);
}
if ((bool)e.NewValue)
{
fe.Focus();
}
}
private static void fe_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
var fe = (FrameworkElement)sender;
if (fe.IsVisible && (bool)((FrameworkElement)sender).GetValue(IsFocusedProperty))
{
fe.IsVisibleChanged -= fe_IsVisibleChanged;
fe.Focus();
}
}
private static void FrameworkElement_GotFocus(object sender, RoutedEventArgs e)
{
((FrameworkElement)sender).SetValue(IsFocusedProperty, true);
}
private static void FrameworkElement_LostFocus(object sender, RoutedEventArgs e)
{
((FrameworkElement)sender).SetValue(IsFocusedProperty, false);
}
}
Моей причиной для добавления ссылок на видимость были вкладки. Очевидно, что если вы использовали присоединенное свойство на любой другой вкладке за пределами первоначально видимой вкладки, присоединенное свойство не будет работать, пока вы не сфокусируете элемент управления вручную.
Другим препятствием было создание более элегантного способа сброса базового свойства в false, когда оно потеряло фокус. Вот где произошли события потерянного фокуса.
<TextBox
Text="{Binding Description}"
FocusExtension.IsFocused="{Binding IsFocused}"/>
Если есть лучший способ справиться с проблемой видимости, пожалуйста, дайте мне знать.
Примечание: спасибо Apfelkuacha за предложение поместить BindsTwoWayByDefault в свойство DependencyProperty. Я сделал это давно в своем собственном коде, но никогда не обновлял этот пост. Из-за этого изменения в коде WPF больше не требуется Mode = TwoWay.