将焦点设置为 xaml wpf 中的文本框

尽管有一些帖子在这个论坛和其他我不能找到一些东西,告诉我如何设置一个 TextBox的重点。

我有一个包含许多标签和文本框的 userControl。在加载表单时,我希望特定的 textBox 具有焦点。

我已经设置了 tabIndex,但似乎没有起作用。

有什么建议吗?

98110 次浏览

You can use the FocusManager.FocusedElement attached property for this purpose. Here's a piece of code that set the focus to TxtB by default.

<StackPanel Orientation="Vertical" FocusManager.FocusedElement="{Binding ElementName=TxtB}">
<TextBox x:Name="TxtA" Text="A" />
<TextBox x:Name="TxtB" Text="B" />
</StackPanel>

You can also use TxtB.Focus() in your code-behind if you don't want to do this in XAML.

You can apply this property directly on the TextBox :

<TextBox Text="{Binding MyText}" FocusManager.FocusedElement="{Binding RelativeSource={RelativeSource Self}}"/>

bind the element you want to point the focus in as

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

in grid or groupbox etc

FocusManager was not in intellisense and this confused me a bit. I just typed the entire attribute and it worked.

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


Microsoft Visual Studio Enterprise 2015 version 14.0.23107.0/C#/WPF

For completeness, there is also a way to handle this from code behind (e.g. in the case of controls that, for whatever reason, are created dynamically and don't exist in XAML). Attach a handler to the window's Loaded event and then use the ".Focus()" method of the control you want. Bare-bones example below.

public class MyWindow
{
private VisualCollection controls;
private TextBox textBox;


// constructor
public MyWindow()
{
controls = new VisualCollection(this);
textBox = new TextBox();
controls.Add(textBox);


Loaded += window_Loaded;
}


private void window_Loaded(object sender, RoutedEventArgs e)
{
textBox.Focus();
}
}

I am new to using WPF and reading through the above examples I had a similar experience trying set the focus to a textbox using the xaml code examples given, i.e. all the examples above didn't work.

What I found was I had to place the FocusManager.FocusElement in the page element. I assume this would probably work as well if you used a Window as the parent element. Anyway, here is the code that worked for me.

 <Page x:Class="NameOfYourClass"
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"
Title="Title"
Height="720"
Width="915"
Background="white"
Loaded="pgLoaded"
FocusManager.FocusedElement="{Binding ElementName=NameOfYourTextBox}">


<!-- Create child elements here. -->


</Page>

From experimenting around, the xaml solution

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

seems to work best when you place it in the highest element in the window hierarchy (usually Window, or the Grid you place everything else in)

Usage: local:FocusManager.FocusOnLoad="True"

    public class FocusManager
{
public static readonly DependencyProperty FocusOnLoad = DependencyProperty.RegisterAttached(
"FocusOnLoad",
typeof(bool),
typeof(FocusManager),
new UIPropertyMetadata(false, new PropertyChangedCallback(OnValueChanged))
);


private static void OnValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
if (!(sender is Control control))
return;


if ((bool) e.NewValue == false)
return;


control.Loaded += (s, e) => control.Focus();
}


public static bool GetFocusOnLoad(DependencyObject d) => (bool) d.GetValue(FocusOnLoad);


public static void SetFocusOnLoad(DependencyObject d, bool value) => d.SetValue(FocusOnLoad, value);
}

I have a TextBox inside a Grid inside a DataTemplate which I want to have keyboard focus when it becomes visible. I also found that

<DataTemplate x:Key="DistanceView" DataType="{x:Type vm:ROI}">
<Grid FocusManager.FocusedElement="{Binding ElementName=tbDistance}">
<TextBox x:Name="tbDistance" Grid.Column="1" Grid.Row="1" VerticalAlignment="Bottom"/>
</Grid>
</DataTemplate>

did not work for me.

However when I call Focus() in the parent ContentControl

private void ContentControl_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if ((sender as ContentControl).IsVisible)
{
(sender as ContentControl).Focus();
}
}

it starts to work and the caret is visible in the TextBox. I think the FocusScope has to be given focus for the FocusManager.FocusedElement property to have any effect.

Jerry

Further to my comment on Feb 04 '22, I solved it this way:

In the UserControl definitionin the XAML add a Loaded event handler. (pressing tab after Loaded= will automatically add an event handler to the code behind)

Then edit the event handler in the code behind:

private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
expressionTextBox.Focus();
}

I'm hoping that WPF is clever enough to handle th unhooking of the evnt at some point, allowing the class to be garbage collected and not give rise to memory leaks, but I don't know. I'd be interested in any comments on that.