WPF在运行时设置键盘焦点而无需代码

时间:2013-03-04 11:45:36

标签: wpf xaml mvvm

我在那个主题上搜索了很多,但是没有真正找到解决方案,不使用任何代码。我知道有人会说使用代码隐藏这个视图相关的东西是完全可以的,但不过我想避免它。

我有一个usercontrol,它显示一个带有单个文本框和一个OK按钮的“对话框”。该对话框是一个简单的用户控件,放在所有其他控件之上。默认情况下,usercontrols可见性设置为折叠。如果usercontrol可见,我想将keyboardfocus设置为对话框usercontrol上的文本框。有没有办法在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>

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

2 个答案:

答案 0 :(得分:3)

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

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

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

答案 1 :(得分: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>