文本框焦点与DependencyProperty的双向数据绑定

本文关键字:数据绑定 DependencyProperty 焦点 文本 | 更新日期: 2023-09-27 18:27:19

在根据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的回调也不会被调用)。

这种行为有什么明显的原因吗?代码有什么问题吗?

(我尝试将UpdateSourceTriggerPropertyChanged以及LostFocus一起添加到绑定中,还将DependencyProperty的默认值更改为true,但这些都没有改变行为。我还尝试了IsKeyboardFocused而不是IsFocused,但没有任何更改,以及IsKeyboardFocusWithin,这使应用程序在组装网格时关闭,没有任何注释-可能是DevExpress异常。)

文本框焦点与DependencyProperty的双向数据绑定

您不是将GroupFocused属性数据绑定到TextBox.IsFocused属性,而是将其数据绑定到以编程方式调用TextBox上的FocusFocusHelper.IsFocused属性。

有一个明显的区别。在TextBox上调用Focus方法将导致TextBox.IsFocused属性设置为true,但该属性与GroupFocusedFocusHelper.IsFocused属性之间没有连接,因此当TextBox.IsFocused属性设置为false时,两者都不会设置为CCD21。

此外,由于TextBox.IsFocused属性是只读的,因此无法在尝试设置焦点时将其数据绑定到CCD_24。有关详细信息,请参阅MSDN上的UIElement.IsFocused属性页。

然而,有一个简单的解决方案。它可能看起来不漂亮,但肯定会起作用。。。每次将GroupFocused属性设置为true之前,只需将其设置为false即可。也许是这样的:

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

FocusTextBox();