【问题标题】:WPF setting keyboard-focus without code behind at runtimeWPF 在运行时设置键盘焦点,无需代码
【发布时间】:2013-03-05 06:16:04
【问题描述】:

我在该主题上进行了很多搜索,但在没有代码的情况下无法真正找到解决方案。我知道有些人会说对这个视图相关的事情使用代码隐藏是完全可以的,但我还是想避免它。

我有一个用户控件,它显示一个带有单个文本框和一个确定按钮的“对话框”。该对话框是一个简单的用户控件,位于所有其他控件之上。默认情况下,用户控件的可见性设置为折叠。如果用户控件可见,我想将键盘焦点设置为对话框用户控件上的文本框。有没有办法在 xaml 中完全做到这一点?由于在加载控件时我的对话框控件不可见,因此只需设置

FocusManager.FocusedElement="{Binding ElementName=tbID}"

不会工作。我尝试使用某种可见性触发器:

   <TextBox Grid.Column="3"
             Grid.Row="5"
             Name="tbID"
             VerticalAlignment="Center">
        <TextBox.Style>
            <Style TargetType="{x:Type TextBox}">
                <Style.Triggers>
                    <Trigger Property="Visibility" Value="Visible">
                        <Setter Property="FocusManager.FocusedElement" Value="{Binding ElementName=tbID}" />
                    </Trigger>
                </Style.Triggers>
            </Style>
        </TextBox.Style>
    </TextBox>

但这也不起作用。触发器被触发,但文本框没有获得焦点。我真的很感激对此的任何建议。提前致谢!

【问题讨论】:

    标签: wpf xaml mvvm


    【解决方案1】:

    您可以尝试使用附加行为来设置焦点。下面是一些示例代码:

    public static class Focus
    {
        public static readonly DependencyProperty ShouldFocusWhenVisibleProperty =
            DependencyProperty.RegisterAttached("ShouldFocusWhenVisible", typeof (bool), typeof (Focus), new PropertyMetadata(default(bool), ShouldFocusWhenVisibleChanged));
    
        private static void ShouldFocusWhenVisibleChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            var uiElement = sender as UIElement;
            if (uiElement == null) return;
    
            var shouldFocus = GetShouldFocusWhenVisible(uiElement);
            if (shouldFocus)
            {
                UpdateFocus(uiElement);
                uiElement.IsVisibleChanged += UiElementOnIsVisibleChanged;
            }
            else
                uiElement.IsVisibleChanged -= UiElementOnIsVisibleChanged;
        }
    
        private static void UiElementOnIsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            var uiElement = sender as UIElement;
            if (uiElement == null) return;
    
            UpdateFocus(uiElement);
        }
    
        private static void UpdateFocus(UIElement uiElement)
        {
            if (!uiElement.IsVisible) return;
    
            Keyboard.PrimaryDevice.Focus(uiElement);
        }
    
        public static void SetShouldFocusWhenVisible(UIElement uiElement, bool value)
        {
            uiElement.SetValue(ShouldFocusWhenVisibleProperty, value);
        }
    
        public static bool GetShouldFocusWhenVisible(UIElement uiElement)
        {
            return (bool)uiElement.GetValue(ShouldFocusWhenVisibleProperty);
        }
    }
    

    然后,将以下代码应用于对话框中的文本框:&lt;TextBox local:Focus.ShouldFocusWhenVisible="True" /&gt;。请注意,local: 需要是对上述 Focus 类的命名空间的引用。

    【讨论】:

    • 感谢您的努力!这也是处理我正在寻找的东西的好方法。
    【解决方案2】:

    我认为您想绑定到 UserControl Visibility 属性而不是 TextBox

    例子

    <UserControl x:Class="WpfApplication7.IconButton"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                 mc:Ignorable="d" 
                 d:DesignHeight="100" d:DesignWidth="200" Name="_this">
        <Grid>
            <TextBox Name="tbID" Margin="0,12,0,0" VerticalAlignment="Top">
                <TextBox.Style>
                    <Style TargetType="{x:Type TextBox}">
                        <Style.Triggers>
                            <DataTrigger Binding="{Binding ElementName=_this, Path=Visibility}" Value="Visible">
                                <Setter Property="FocusManager.FocusedElement" Value="{Binding ElementName=tbID}" />
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </TextBox.Style>
            </TextBox>
        </Grid>
    </UserControl>
    

    【讨论】:

    • 这就是灵魂!我将代码中的 _this 更改为我的用户控件的名称,效果很好!非常感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-22
    • 1970-01-01
    • 2010-11-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多