那么如何使用 MVVM 模式将文本框聚焦在按钮单击上?

我创建了一个简单的基于 this Answer 的测试项目,它在第一次点击时工作,但之后它不再设置焦点。我想念什么?

XAML( View )

<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>

View 模型
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
}

这是一个 Download link,为懒惰的人准备好了项目(VS2010);)

最佳答案

在覆盖初始默认值后,您的附加属性值永远不会返回 false。因此,您的 FocusExtension 类不会在 Focus() 上调用 TextBox,因为在将 VM 中的 PropertyChanged 设置为 true 时不需要触发 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.
}


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);
}

更新:

随着上述变化也确保
local:FocusExtension.IsFocused="{Binding IsFocused}"
切换到
local:FocusExtension.IsFocused="{Binding IsFocused, Mode=TwoWay}"
Working Download Link

另一个更新

Mode=TwoWay 类开关中将 FocusExtension 设置为此附加属性的默认值
public static readonly DependencyProperty IsFocusedProperty = DependencyProperty.RegisterAttached(
  "IsFocused",
  typeof(bool),
  typeof(FocusExtension),
  new UIPropertyMetadata(
    false,
    OnIsFocusedPropertyChanged));


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

您可以使用上述声明跳过在 xaml 中显式指定 Mode=TwoWay 的步骤。

关于c# - 如何将文本框聚焦在按钮单击上,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/16964886/

10-12 07:03