4

简化:在我看来,我有一个 xaml 页面,其中包含一个按钮和某种文本框。按钮绑定到 ViewModel 中的 DelegateCommand,编辑框绑定到 ViewModel 中的某个属性。

View:
<Button Command="{Binding MyCommand}"/>
<TextBox Text="{Binding MyString}"/>

ViewModel:
public DelegateCommand MyCommand { get; set; }
public String MyString { get; set; }

现在,当用户在框中输入内容并单击按钮时,按钮不会收到焦点更改事件。所以它不会将它的内容更新到属性中。所以属性 MyString 不会在单击按钮时反映 TextBox 的内容。因此,无论 MyCommand 正在做什么处理,它都在处理旧数据而不是当前输入。

现在,如果这真的只是一个 TextBox,我会将 UpdateSourceTrigger=PropertyChanged 添加到绑定中,我会很好。但在这种情况下,编辑控件有点复杂,需要对内容进行一些验证。所以当我用鼠标按下按钮时,我需要某种“失去焦点”的信号。

我的问题是:在 MVVM 中,按钮背后的代码无法访问视图,因此不能使其失去焦点。

xaml 中(例如在视图中)有什么方法可以使按钮在鼠标单击时获得键盘焦点?这将是我的自定义控件获得“失去焦点”消息的最简单方法。

4

2 回答 2

3

回复:在 xaml 中(例如在视图中)有什么方法可以使按钮在被鼠标单击时获得键盘焦点?> 一个按钮在被点击时确实会获得键盘焦点——前提是 IsEnabled、Focusable 和 IsHitTestVisible 属性都设置为 true,因为它们是默认的。要以编程方式设置键盘焦点,请调用 Keybaord.Focus,如下例所示。

与流行的 meme 不同,命令不必在 VM 中处理。如果在执行命令时需要独立于 VM 更改视图,则可以在视图中处理命令。事实上,这是 WPF 的原生模式。

以下示例显示了使用按钮上的 Command 属性来处理视图中的命令。为简单起见,该示例没有 VM。即使命令是在视图中处理的,如果有一个虚拟机,视图后面的代码也可以调用它。

public partial class MainWindow : Window
{
    public static readonly RoutedUICommand MyCommand = new RoutedUICommand("My Command", "MyCommand", typeof(MainWindow));
    public String MyString { get; set; }

    public MainWindow()
    {
        MyString = "some text";
        DataContext = this; // this simple example has no VM 
        InitializeComponent();
    }
    private void MyCommand_Executed(object sender, ExecutedRoutedEventArgs e)
    {
        Button1.Content = MyString;
        Keyboard.Focus(Button1);   
    }
}
<Window x:Class="fwLoseFocus.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:me="clr-namespace:fwLoseFocus">
    <Window.CommandBindings>
        <CommandBinding Command="me:MainWindow.MyCommand" Executed="MyCommand_Executed"/>
    </Window.CommandBindings>
    <StackPanel>
        <TextBox Text="{Binding MyString}"/>
        <Button x:Name="Button1" Command="me:MainWindow.MyCommand"/>
    </StackPanel>
</Window>
于 2012-08-21T14:29:47.500 回答
1

是否不可能仍然拥有 Button 的单击事件并让后面的代码使文本框失去焦点?

private void Button_Click(object sender, RoutedEventArgs e) { 
    FocusManager.SetFocusedElement(this, null); 
} 

以下答案与您相关吗?

WPF 在按钮单击时重置焦点

于 2012-08-21T13:18:07.430 回答