C# WPF MVVM 焦点字段加载

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1178449/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 10:08:41  来源:igfitidea点击:

WPF MVVM Focus Field on Load

c#wpfmvvmtextboxfocus

提问by Shaun Bowe

I have a View that has a single TextBoxand a couple Buttons below it. When the window loads I want that TextBoxto have focus.

我有一个视图,它下面有一个TextBox和几个Buttons。当窗口加载时,我希望它TextBox具有焦点。

If I was not using MVVM I would just call TextBox.Focus()in the Loaded event. However my ViewModel does not know about my view so how can I accomplish this without putting code into the codebehind of my view?

如果我不使用 MVVM,我只会调用TextBox.Focus()Loaded 事件。但是,我的 ViewModel 不知道我的视图,所以如何在不将代码放入视图的代码隐藏中的情况下完成此操作?

EDIT: After reading the answers I decided to put this code in the view xaml

编辑:阅读答案后,我决定将此代码放在视图 xaml 中

<DockPanel FocusManager.FocusedElement="{Binding ElementName=MessageTextBox}">    
    <TextBox Name="MessageTextBox" Text="{Binding Message}"/>
</DockPanel>

If this were anything other than initial page focus I would probably recommend Jon Galloway's answer since it can be controlled from the ViewModel.

如果这不是初始页面焦点,我可能会推荐 Jon Galloway 的答案,因为它可以从 ViewModel 进行控制。

采纳答案by Anderson Imes

If it makes you feel better (it makes me feel better) you can do this in Xaml using an attached property:

如果它让您感觉更好(这让我感觉更好),您可以使用附加属性在 Xaml 中执行此操作:

http://msdn.microsoft.com/en-us/library/system.windows.input.focusmanager.focusedelement.aspx

http://msdn.microsoft.com/en-us/library/system.windows.input.focusmanager.focusedelement.aspx

Anything you can do in codebehind you can do in Xaml if you know the tricks. Fortunately, you didn't have to implement this trick - MS did it for you.

如果您知道技巧,您可以在代码隐藏中执行的任何操作都可以在 Xaml 中执行。幸运的是,您不必实施此技巧 - MS 为您做到了。

回答by Martin Harris

In this case I think that it is fine to put the code into the view. Setting focus to a control affects the behaviour of the user interface rather than logic of the application and therefore is the responsibility of the view.

在这种情况下,我认为将代码放入视图中是可以的。为控件设置焦点会影响用户界面的行为而不是应用程序的逻辑,因此是视图的责任。

回答by Steven Robbins

I'd consider the control with focus to be very much "visual only", so wouldn't have any problem with that being in code behind.

我认为具有焦点的控件非常“仅可视”,因此在代码后面不会有任何问题。

The idea of a VM is to move logic away from the View, and provide a databinding friendly version of your model for the view to bind to. This doesn't necessarily mean that allcode should live in the VM, just the logic code and anything that isn't directly tied to the UI.

VM 的想法是将逻辑从视图中移开,并为要绑定到的视图提供模型的数据绑定友好版本。这并不一定意味着所有代码都应该存在于 VM 中,只是逻辑代码和任何不直接绑定到 UI 的代码。

回答by maciejkow

Actually, isn't focus a UI concern? MVVM is about separating concerns - what belongs to model is in model, what belongs to view is in view, and what bind model and view together is in ViewModel (this is of course oversimplified description).

实际上,焦点不是 UI 问题吗?MVVM 是关于分离关注点 - 属于模型的在模型中,属于视图的在视图中,将模型和视图绑定在一起的在 ViewModel 中(这当然是过于简化的描述)。

This means, that UI logic remains in View - TextBox.Focus() is, in my opinion, appropriate way to make this happen.

这意味着,UI 逻辑保留在 View 中 - 在我看来,TextBox.Focus() 是实现这一目标的合适方法。

回答by Jon Galloway

  1. Have a property in your ViewModel which indicates which is the currently focused element.
  2. Use the FocusManager to bind to that property.

    <Window FocusManager.FocusedElement="{Binding ElementName=ViewModel.FocusedItem}"/>
    
  1. 在您的 ViewModel 中有一个属性,指示哪个是当前聚焦的元素。
  2. 使用 FocusManager 绑定到该属性。

    <Window FocusManager.FocusedElement="{Binding ElementName=ViewModel.FocusedItem}"/>
    

Your ViewModel is a translator which exists solely to provide information to the View, so you can add whatever information to the VM that the View needs to function.

您的 ViewModel 是一个转换器,它的存在只是为了向 View 提供信息,因此您可以将 View 运行所需的任何信息添加到 VM。

回答by OrPaz

After having a 'WPF Initial Focus Nightmare' and based on some answers on stack, the following proved for me to be the best solution.

在经历了“WPF Initial Focus Nightmare”并基于堆栈上的一些答案之后,以下对我来说证明是最好的解决方案。

First, add your App.xaml OnStartup() the followings:

首先,添加您的 App.xaml OnStartup() 以下内容:

EventManager.RegisterClassHandler(typeof(Window), Window.LoadedEvent,
          new RoutedEventHandler(WindowLoaded));

Then add the 'WindowLoaded' event also in App.xaml :

然后在 App.xaml 中添加 'WindowLoaded' 事件:

void WindowLoaded(object sender, RoutedEventArgs e)
    {
        var window = e.Source as Window;
        System.Threading.Thread.Sleep(100);
        window.Dispatcher.Invoke(
        new Action(() =>
        {
            window.MoveFocus(new TraversalRequest(FocusNavigationDirection.First));

        }));
    }

The threading issue must be use as WPF initial focus mostly fails due to some framework race conditions.

必须使用线程问题,因为 WPF 初始焦点主要由于某些框架竞争条件而失败。

I found the following solution best as it is used globally for the whole app.

我发现以下解决方案最好,因为它在整个应用程序中全局使用。

Hope it helps...

希望能帮助到你...

Oran

奥兰