如何在按钮单击上聚焦TextBox

Wii*_*axx 2 c# wpf xaml mvvm

那么如何使用MVVM模式关注按钮上的TextBox?

我创建了一个简单的测试项目基于这个答案,它在第一次点击时起作用,但之后它不再设置焦点.我错过了什么?

XAML(查看)

<Grid>
    <TextBox Height='23' HorizontalAlignment='Left' Margin='12,12,0,0' VerticalAlignment='Top' Width='120'
             Text='{Binding TheText}'
             local:FocusExtension.IsFocused="{Binding IsFocused}"/>
    <Button Content='Click' Height='23' HorizontalAlignment='Left' Margin='138,11,0,0' VerticalAlignment='Top' Width='75' 
            Command='{Binding ClickCommand}'/>
    <Button Content='Just to deFocus' Height='28' HorizontalAlignment='Left' Margin='14,44,0,0' Name='button1' VerticalAlignment='Top' Width='199' />
</Grid>
Run Code Online (Sandbox Code Playgroud)

视图模型

public class ViewModel : INotifyPropertyChanged
{
    public string TheText { get; set; }
    public bool IsFocused { get; set; }

    private RelayCommand _clickCommand;
    public ICommand ClickCommand
    {
        get { return _clickCommand ?? (_clickCommand = new RelayCommand(param => this.OnClick())); }
    }
    private void OnClick()
    {
        IsFocused = true;
        RaisePropertyChanged("IsFocused");
    }

    #region INotifyPropertyChanged

    public event PropertyChangedEventHandler PropertyChanged;

    public void RaisePropertyChanged(string propName)
    {
        if (this.PropertyChanged != null)
            this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
    }

    #endregion
}
Run Code Online (Sandbox Code Playgroud)

这是一个下载链接,带有准备好的项目(VS2010),适用于懒人;)

Viv*_*Viv 6

在覆盖初始默认值后,您的附加属性值永远不会返回false.因此,当您在VM中设置为true 时,您的FocusExtension类不会调用Focus(),TextBox因为PropertyChanged不需要触发IsFocused.

切换 OnIsFocusedPropertyChanged(...)

从:

private static void OnIsFocusedPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var uie = (UIElement)d;
    if ((bool)e.NewValue)
        uie.Focus(); // Don't care about false values.
}
Run Code Online (Sandbox Code Playgroud)

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

private static void UieOnLostFocus(object sender, RoutedEventArgs routedEventArgs) {
  var uie = sender as UIElement;
  if (uie == null)
    return;
  uie.LostFocus -= UieOnLostFocus;
  uie.SetValue(IsFocusedProperty, false);
}
Run Code Online (Sandbox Code Playgroud)

更新:

随着上述变化也确定

local:FocusExtension.IsFocused="{Binding IsFocused}"

切换到

local:FocusExtension.IsFocused="{Binding IsFocused, Mode=TwoWay}"

工作下载链接

另一个更新

Mode=TwoWayFocusExtension类开关中为此附加属性设置默认值

public static readonly DependencyProperty IsFocusedProperty = DependencyProperty.RegisterAttached(
  "IsFocused",
  typeof(bool),
  typeof(FocusExtension),
  new UIPropertyMetadata(
    false,
    OnIsFocusedPropertyChanged));
Run Code Online (Sandbox Code Playgroud)

public static readonly DependencyProperty IsFocusedProperty = DependencyProperty.RegisterAttached(
  "IsFocused",
  typeof(bool),
  typeof(FocusExtension),
  new FrameworkPropertyMetadata(
    false,
    FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
    OnIsFocusedPropertyChanged));
Run Code Online (Sandbox Code Playgroud)

您可以跳过Mode=TwoWay使用上述声明在xaml中明确指定.