【问题标题】:Setting focus in WPF with MVVM使用 MVVM 在 WPF 中设置焦点
【发布时间】:2013-02-28 02:50:59
【问题描述】:

我有多个文本框的网格。根据用户可能采取的行动,应将焦点更改为文本框之一。我当前的解决方案使用 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>

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

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

提前致谢

【问题讨论】:

  • 我能问你为什么要这样设置焦点吗?因为用户也可以通过TabIndex Tab,所以你只需要设置一次焦点
  • 只要这个解决方案适合你,你就应该接受它
  • 我个人认为 Focus 是一个特定于 UI 的概念,所以我会将所有焦点处理放在 View 后面的代码中,而不是放在我的 ViewModel 中(除非焦点在业务逻辑中具有某些特定含义)。
  • @WiiMaxx 这是我的用户组要求的功能。我个人同意你的看法:)
  • @blindmeis 如果我从不尝试改进,我将不会学到任何东西,因此永远不会变得更好,

标签: c# wpf data-binding mvvm focusmanager


【解决方案1】:

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

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

然后在 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}" />

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

【讨论】:

  • 谢谢。我曾考虑过使用这样的解决方案,但决定反对它,因为它将我的 VM 与实际 UI 的耦合过于强烈。我开始认为代码隐藏可能是要走的路。
  • 您的文本框也需要设置 Focusable="True",否则这将不起作用
猜你喜欢
  • 2011-06-09
  • 1970-01-01
  • 2011-07-17
  • 2020-10-14
  • 2017-06-29
  • 2011-06-25
  • 1970-01-01
  • 1970-01-01
  • 2012-07-29
相关资源
最近更新 更多