在由MVVM原理构建的WPF应用程序中,我需要从代码中明确地将焦点设置为TextBox(对键盘事件做出反应),并且还要知道焦点是否已丢失。从另一个问题我已经收集到,显然,这样做的方法是在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绑定如下所示:
<TextBox Text="{Binding Path=RowData.Row.Group}" helper:FocusHelper.IsFocused="{Binding RowData.Row.GroupFocused, Mode=TwoWay}"
这是在(DevExpress)网格中; Row
是整行绑定的实际ViewModel。
绑定ViewModel中的相应代码:
private bool groupFocused;
public bool GroupFocused
{
get { return this.groupFocused; }
set
{
this.groupFocused = value;
this.NotifyOfPropertyChange(() => this.GroupFocused);
}
}
处理键盘事件时,GroupFocused
设置为true,这肯定会调用DependencyProperty回调并将焦点设置为TextBox。但是,当控件失去焦点时,该更改不会反映在ViewModel上(也不会调用DependencyProperty的回调)。
这种行为有什么明显的原因吗?代码有什么问题吗?
(我尝试将UpdateSourceTrigger
同时添加PropertyChanged
和LostFocus
到绑定中,同时将DependencyProperty的默认值更改为true
,其中没有一个改变了有关行为的任何内容。我还尝试IsKeyboardFocused
代替IsFocused
而没有任何更改,IsKeyboardFocusWithin
,这使应用程序关闭而没有评论 - 可能是DevExpress异常 - 组装网格。)
答案 0 :(得分:0)
您不是将GroupFocused
属性绑定到TextBox.IsFocused
属性的数据,而是将数据绑定到FocusHelper.IsFocused
属性,以编程方式调用Focus
TextBox
。
有明显的区别。在Focus
上调用TextBox
方法会导致TextBox.IsFocused
属性设置为true
,但该属性与您的GroupFocused
或FocusHelper.IsFocused
属性,因此当false
属性设置为TextBox.IsFocused
时,两者都不会设置为false
。
此外,在尝试设置焦点时,您无法将数据绑定到TextBox.IsFocused
属性,因为它是只读的。有关详细信息,请参阅MSDN上的UIElement.IsFocused
Property页面。
然而,有一个简单的解决方案。它可能看起来不漂亮,但它肯定会工作......只需将GroupFocused
属性设置为false
,然后再将其设置为true。也许是这样的:
private void FocusTextBox()
{
GroupFocused = false;
GroupFocused = true;
}
...
FocusTextBox();