使用 MVVM 在 WPF 中设置焦点

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15363814/
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-09-13 08:02:22  来源:igfitidea点击:

Setting focus in WPF with MVVM

c#wpfdata-bindingmvvmfocusmanager

提问by Farawin

I have Grid with multiple Textboxes. Depending on actions the user might take focus should be changed to one of the textboxes. My current solution uses a string property in the ViewModel and a data trigger in xaml to change focus. It works nicely but it seems a rather roundabout way to achieve this so I was wondering if it could be done in a clearner way?

我有多个文本框的网格。根据用户可能采取的操作,应将焦点更改为文本框之一。我当前的解决方案使用 ViewModel 中的字符串属性和 xaml 中的数据触发器来更改焦点。它工作得很好,但似乎是一种相当迂回的方式来实现这一点,所以我想知道是否可以以更清晰的方式完成?

    <Grid.Style>
        <Style TargetType="Grid">
            <Style.Triggers>
                <DataTrigger Binding="{Binding FocusedItem}" Value="number">
                    <Setter Property="FocusManager.FocusedElement" Value="{Binding ElementName=number}"/>
                </DataTrigger>
                <DataTrigger Binding="{Binding FocusedItem}" Value="name">
                    <Setter Property="FocusManager.FocusedElement" Value="{Binding ElementName=name}"/>
                </DataTrigger>
                <DataTrigger Binding="{Binding FocusedItem}" Value="id">
                    <Setter Property="FocusManager.FocusedElement" Value="{Binding ElementName=id}"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Grid.Style>

As you can see the value of the property and the name of the element is the same so I would like to do this i a single trigger instead of having one trigger per element.

正如您所看到的,属性的值和元素的名称是相同的,所以我想使用单个触发器来执行此操作,而不是每个元素有一个触发器。

Maybe someone can come up with a cleaner way?

也许有人可以想出更清洁的方法?

Thanks in advance

提前致谢

回答by Heinrich

The way I handled setting focus in one of my projects was by using a focus extension (I apologize I do not remember where I saw the original post this is from).

我在我的一个项目中处理设置焦点的方式是使用焦点扩展(很抱歉,我不记得我从哪里看到的原始帖子)。

    public static class FocusExtension
    {
        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(FocusExtension),
                 new UIPropertyMetadata(false, OnIsFocusedPropertyChanged));


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

And then in xaml file I use it as a Dependency Property:

然后在 xaml 文件中我将它用作依赖属性:

<TextBox Uid="TB1" FontSize="13" localExtensions:FocusExtension.IsFocused="{Binding Path=TB1Focus}" Height="24" HorizontalAlignment="Left" Margin="113,56,0,0" Name="TB_UserName" VerticalAlignment="Top" Width="165" Text="{Binding Path=TB1Value, UpdateSourceTrigger=PropertyChanged}" />

You can then use a binding to set the focus.

然后,您可以使用绑定来设置焦点。