WPF,聚焦元素 window 显示
WPF, focusing element on window show
我正在尝试将焦点设置到 window 节目中的特定元素。 window 只是带有制表符的 search/replace window;当用户选择 "Search" 时,搜索选项卡被激活,搜索文本框应该获得焦点。同样,当用户选择 "Replace" 时,替换选项卡被激活并且替换文本框应该获得焦点。
由于 window 是非模态的,我重用它并隐藏而不是关闭。问题是没有正确接收到焦点。说:
- 我打开搜索。 Window 显示,搜索文本框 有焦点。
- 我关闭window,然后打开替换。 Window显示,替换文本框没有焦点
- 我关闭 window,然后再打开替换 。 Window 显示,替换文本框 有焦点。
- 我关闭 window,然后打开搜索。搜索文本框没有焦点。
- 我关闭 window,然后再次打开搜索 。搜索文本框 有 焦点。
打开 window 后,根据用户选择,我调用了以下方法之一:
public void ChooseReplaceTab()
{
tcTabs.SelectedItem = tReplace;
FocusManager.SetFocusedElement(this, tbReplaceSearch);
tbReplaceSearch.Focus();
}
public void ChooseSearchTab()
{
tcTabs.SelectedItem = tSearch;
FocusManager.SetFocusedElement(this, tbSearchSearch);
tbSearchSearch.Focus();
}
搜索 window 没有任何花哨的东西,只有一堆选项卡、文本框、单选框和按钮:
<Window x:Class="Dev.Editor.SearchReplaceWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Dev.Editor"
xmlns:p="clr-namespace:Dev.Editor.Resources;assembly=Dev.Editor.Resources"
xmlns:t="clr-namespace:Dev.Editor.BusinessLogic.Types.Search;assembly=Dev.Editor.BusinessLogic"
mc:Ignorable="d"
Title="{x:Static p:Strings.SearchWindow_Title}" SizeToContent="WidthAndHeight" ResizeMode="NoResize" Closing="HandleWindowClosing">
<TabControl x:Name="tcTabs" Margin="{StaticResource DialogWindowPadding}">
<!-- Search -->
<TabItem x:Name="tSearch" Header="{x:Static p:Strings.SearchWindow_SearchTab}" >
<GroupBox Header="{x:Static p:Strings.SearchWindow_SearchTab}" Padding="4">
<StackPanel Orientation="Horizontal">
<StackPanel Orientation="Vertical">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="250" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="{x:Static p:Strings.SearchWindow_SearchedText}"/>
<TextBox x:Name="tbSearchSearch" Grid.Row="0" Grid.Column="1" HorizontalAlignment="Stretch" Text="{Binding Search, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</Grid>
<GroupBox Header="{x:Static p:Strings.SearchWindow_SearchOptions}" Padding="4">
<StackPanel Orientation="Vertical">
<CheckBox Margin="{StaticResource DialogItemsVMargin}" Content="{x:Static p:Strings.SearchWindow_CaseSensitive}"
IsChecked="{Binding CaseSensitive, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<CheckBox Margin="{StaticResource DialogItemsVMargin}" Content="{x:Static p:Strings.SearchWindow_OnlyFullWords}"
IsChecked="{Binding WholeWordsOnly, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<CheckBox Content="{x:Static p:Strings.SearchWindow_SearchBackwards}"
IsChecked="{Binding SearchBackwards, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</StackPanel>
</GroupBox>
<GroupBox Header="{x:Static p:Strings.SearchWindow_SearchMode}" Padding="4">
<StackPanel Orientation="Vertical">
<RadioButton Margin="{StaticResource DialogItemsVMargin}" Content="{x:Static p:Strings.SearchWindow_SearchModeNormal}"
IsChecked="{Binding SearchMode, Converter={StaticResource RadioToEnumConverter}, ConverterParameter={x:Static t:SearchMode.Normal}}"/>
<RadioButton Margin="{StaticResource DialogItemsVMargin}" Content="{x:Static p:Strings.SearchWindow_SearchModeExtended}"
IsChecked="{Binding SearchMode, Converter={StaticResource RadioToEnumConverter}, ConverterParameter={x:Static t:SearchMode.Extended}}"/>
<RadioButton Content="{x:Static p:Strings.SearchWindow_SearchModeRegex}"
IsChecked="{Binding SearchMode, Converter={StaticResource RadioToEnumConverter}, ConverterParameter={x:Static t:SearchMode.RegularExpressions}}"/>
</StackPanel>
</GroupBox>
</StackPanel>
<StackPanel Orientation="Vertical" Margin="10,0,0,0">
<Button Content="{x:Static p:Strings.SearchWindow_FindNext}" Width="150" Margin="{StaticResource DialogItemsVMargin}" Command="{Binding FindNextCommand}" />
<Button Content="{x:Static p:Strings.SearchWindow_Close}" Width="150" Command="{Binding CloseCommand}" />
</StackPanel>
</StackPanel>
</GroupBox>
</TabItem>
<TabItem x:Name="tReplace" Header="{x:Static p:Strings.SearchWindow_ReplaceTab}">
<GroupBox Header="{x:Static p:Strings.SearchWindow_ReplaceTab}" Padding="4">
<StackPanel Orientation="Horizontal">
<StackPanel Orientation="Vertical">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="250" />
</Grid.ColumnDefinitions>
<Label Margin="{StaticResource DialogItemsVMargin}" Grid.Row="0" Grid.Column="0" Content="{x:Static p:Strings.SearchWindow_SearchedText}"/>
<TextBox x:Name="tbReplaceSearch" Margin="{StaticResource DialogItemsVMargin}" Grid.Row="0" Grid.Column="1" HorizontalAlignment="Stretch"
Text="{Binding Search, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<Label Grid.Row="1" Grid.Column="0" Content="{x:Static p:Strings.SearchWindow_ReplaceWith}" />
<TextBox Grid.Row="1" Grid.Column="1" HorizontalAlignment="Stretch"
Text="{Binding Replace, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</Grid>
<GroupBox Header="{x:Static p:Strings.SearchWindow_SearchOptions}" Padding="4">
<StackPanel Orientation="Vertical">
<CheckBox Margin="{StaticResource DialogItemsVMargin}" Content="{x:Static p:Strings.SearchWindow_CaseSensitive}"
IsChecked="{Binding CaseSensitive, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<CheckBox Margin="{StaticResource DialogItemsVMargin}" Content="{x:Static p:Strings.SearchWindow_OnlyFullWords}"
IsChecked="{Binding WholeWordsOnly, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<CheckBox Content="{x:Static p:Strings.SearchWindow_SearchBackwards}"
IsChecked="{Binding SearchBackwards, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</StackPanel>
</GroupBox>
<GroupBox Header="{x:Static p:Strings.SearchWindow_SearchMode}" Padding="4">
<StackPanel Orientation="Vertical">
<RadioButton Margin="{StaticResource DialogItemsVMargin}" Content="{x:Static p:Strings.SearchWindow_SearchModeNormal}"
IsChecked="{Binding SearchMode, Converter={StaticResource RadioToEnumConverter}, ConverterParameter={x:Static t:SearchMode.Normal}}"/>
<RadioButton Margin="{StaticResource DialogItemsVMargin}" Content="{x:Static p:Strings.SearchWindow_SearchModeExtended}"
IsChecked="{Binding SearchMode, Converter={StaticResource RadioToEnumConverter}, ConverterParameter={x:Static t:SearchMode.Extended}}"/>
<RadioButton Content="{x:Static p:Strings.SearchWindow_SearchModeRegex}"
IsChecked="{Binding SearchMode, Converter={StaticResource RadioToEnumConverter}, ConverterParameter={x:Static t:SearchMode.RegularExpressions}}"/>
</StackPanel>
</GroupBox>
</StackPanel>
<StackPanel Orientation="Vertical" Margin="10,0,0,0">
<Button Content="{x:Static p:Strings.SearchWindow_FindNext}" Width="150" Margin="{StaticResource DialogItemsVMargin}" Command="{Binding FindNextCommand}" />
<Button Content="{x:Static p:Strings.SearchWindow_Replace}" Width="150" Margin="{StaticResource DialogItemsVMargin}" Command="{Binding ReplaceCommand}"/>
<Separator Margin="{StaticResource DialogItemsVMargin}" />
<Button Content="{x:Static p:Strings.SearchWindow_ReplaceAll}" Width="150" Margin="{StaticResource DialogItemsVMargin}" Command="{Binding ReplaceAllCommand}"/>
<CheckBox Content="{x:Static p:Strings.SearchWindow_InSelection}" Margin="{StaticResource DialogItemsVMargin}"
IsEnabled="{Binding SelectionAvailable}" IsChecked="{Binding ReplaceAllInSelection, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<Separator Margin="{StaticResource DialogItemsVMargin}" />
<Button Content="{x:Static p:Strings.SearchWindow_Close}" Width="150" Command="{Binding CloseCommand}"></Button>
</StackPanel>
</StackPanel>
</GroupBox>
</TabItem>
</TabControl>
</Window>
在调用这些方法时,我应该怎么做才能正确地将焦点设置到特定元素?
您可以尝试这样的操作:
Dispatcher.BeginInvoke(
DispatcherPriority.ContextIdle,
new Action(delegate()
{
tbSearchSearch.Focus();
}));
来自这个link:Alternative to set focus from within the Enter event
我正在尝试将焦点设置到 window 节目中的特定元素。 window 只是带有制表符的 search/replace window;当用户选择 "Search" 时,搜索选项卡被激活,搜索文本框应该获得焦点。同样,当用户选择 "Replace" 时,替换选项卡被激活并且替换文本框应该获得焦点。
由于 window 是非模态的,我重用它并隐藏而不是关闭。问题是没有正确接收到焦点。说:
- 我打开搜索。 Window 显示,搜索文本框 有焦点。
- 我关闭window,然后打开替换。 Window显示,替换文本框没有焦点
- 我关闭 window,然后再打开替换 。 Window 显示,替换文本框 有焦点。
- 我关闭 window,然后打开搜索。搜索文本框没有焦点。
- 我关闭 window,然后再次打开搜索 。搜索文本框 有 焦点。
打开 window 后,根据用户选择,我调用了以下方法之一:
public void ChooseReplaceTab()
{
tcTabs.SelectedItem = tReplace;
FocusManager.SetFocusedElement(this, tbReplaceSearch);
tbReplaceSearch.Focus();
}
public void ChooseSearchTab()
{
tcTabs.SelectedItem = tSearch;
FocusManager.SetFocusedElement(this, tbSearchSearch);
tbSearchSearch.Focus();
}
搜索 window 没有任何花哨的东西,只有一堆选项卡、文本框、单选框和按钮:
<Window x:Class="Dev.Editor.SearchReplaceWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Dev.Editor"
xmlns:p="clr-namespace:Dev.Editor.Resources;assembly=Dev.Editor.Resources"
xmlns:t="clr-namespace:Dev.Editor.BusinessLogic.Types.Search;assembly=Dev.Editor.BusinessLogic"
mc:Ignorable="d"
Title="{x:Static p:Strings.SearchWindow_Title}" SizeToContent="WidthAndHeight" ResizeMode="NoResize" Closing="HandleWindowClosing">
<TabControl x:Name="tcTabs" Margin="{StaticResource DialogWindowPadding}">
<!-- Search -->
<TabItem x:Name="tSearch" Header="{x:Static p:Strings.SearchWindow_SearchTab}" >
<GroupBox Header="{x:Static p:Strings.SearchWindow_SearchTab}" Padding="4">
<StackPanel Orientation="Horizontal">
<StackPanel Orientation="Vertical">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="250" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="{x:Static p:Strings.SearchWindow_SearchedText}"/>
<TextBox x:Name="tbSearchSearch" Grid.Row="0" Grid.Column="1" HorizontalAlignment="Stretch" Text="{Binding Search, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</Grid>
<GroupBox Header="{x:Static p:Strings.SearchWindow_SearchOptions}" Padding="4">
<StackPanel Orientation="Vertical">
<CheckBox Margin="{StaticResource DialogItemsVMargin}" Content="{x:Static p:Strings.SearchWindow_CaseSensitive}"
IsChecked="{Binding CaseSensitive, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<CheckBox Margin="{StaticResource DialogItemsVMargin}" Content="{x:Static p:Strings.SearchWindow_OnlyFullWords}"
IsChecked="{Binding WholeWordsOnly, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<CheckBox Content="{x:Static p:Strings.SearchWindow_SearchBackwards}"
IsChecked="{Binding SearchBackwards, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</StackPanel>
</GroupBox>
<GroupBox Header="{x:Static p:Strings.SearchWindow_SearchMode}" Padding="4">
<StackPanel Orientation="Vertical">
<RadioButton Margin="{StaticResource DialogItemsVMargin}" Content="{x:Static p:Strings.SearchWindow_SearchModeNormal}"
IsChecked="{Binding SearchMode, Converter={StaticResource RadioToEnumConverter}, ConverterParameter={x:Static t:SearchMode.Normal}}"/>
<RadioButton Margin="{StaticResource DialogItemsVMargin}" Content="{x:Static p:Strings.SearchWindow_SearchModeExtended}"
IsChecked="{Binding SearchMode, Converter={StaticResource RadioToEnumConverter}, ConverterParameter={x:Static t:SearchMode.Extended}}"/>
<RadioButton Content="{x:Static p:Strings.SearchWindow_SearchModeRegex}"
IsChecked="{Binding SearchMode, Converter={StaticResource RadioToEnumConverter}, ConverterParameter={x:Static t:SearchMode.RegularExpressions}}"/>
</StackPanel>
</GroupBox>
</StackPanel>
<StackPanel Orientation="Vertical" Margin="10,0,0,0">
<Button Content="{x:Static p:Strings.SearchWindow_FindNext}" Width="150" Margin="{StaticResource DialogItemsVMargin}" Command="{Binding FindNextCommand}" />
<Button Content="{x:Static p:Strings.SearchWindow_Close}" Width="150" Command="{Binding CloseCommand}" />
</StackPanel>
</StackPanel>
</GroupBox>
</TabItem>
<TabItem x:Name="tReplace" Header="{x:Static p:Strings.SearchWindow_ReplaceTab}">
<GroupBox Header="{x:Static p:Strings.SearchWindow_ReplaceTab}" Padding="4">
<StackPanel Orientation="Horizontal">
<StackPanel Orientation="Vertical">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="250" />
</Grid.ColumnDefinitions>
<Label Margin="{StaticResource DialogItemsVMargin}" Grid.Row="0" Grid.Column="0" Content="{x:Static p:Strings.SearchWindow_SearchedText}"/>
<TextBox x:Name="tbReplaceSearch" Margin="{StaticResource DialogItemsVMargin}" Grid.Row="0" Grid.Column="1" HorizontalAlignment="Stretch"
Text="{Binding Search, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<Label Grid.Row="1" Grid.Column="0" Content="{x:Static p:Strings.SearchWindow_ReplaceWith}" />
<TextBox Grid.Row="1" Grid.Column="1" HorizontalAlignment="Stretch"
Text="{Binding Replace, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</Grid>
<GroupBox Header="{x:Static p:Strings.SearchWindow_SearchOptions}" Padding="4">
<StackPanel Orientation="Vertical">
<CheckBox Margin="{StaticResource DialogItemsVMargin}" Content="{x:Static p:Strings.SearchWindow_CaseSensitive}"
IsChecked="{Binding CaseSensitive, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<CheckBox Margin="{StaticResource DialogItemsVMargin}" Content="{x:Static p:Strings.SearchWindow_OnlyFullWords}"
IsChecked="{Binding WholeWordsOnly, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<CheckBox Content="{x:Static p:Strings.SearchWindow_SearchBackwards}"
IsChecked="{Binding SearchBackwards, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</StackPanel>
</GroupBox>
<GroupBox Header="{x:Static p:Strings.SearchWindow_SearchMode}" Padding="4">
<StackPanel Orientation="Vertical">
<RadioButton Margin="{StaticResource DialogItemsVMargin}" Content="{x:Static p:Strings.SearchWindow_SearchModeNormal}"
IsChecked="{Binding SearchMode, Converter={StaticResource RadioToEnumConverter}, ConverterParameter={x:Static t:SearchMode.Normal}}"/>
<RadioButton Margin="{StaticResource DialogItemsVMargin}" Content="{x:Static p:Strings.SearchWindow_SearchModeExtended}"
IsChecked="{Binding SearchMode, Converter={StaticResource RadioToEnumConverter}, ConverterParameter={x:Static t:SearchMode.Extended}}"/>
<RadioButton Content="{x:Static p:Strings.SearchWindow_SearchModeRegex}"
IsChecked="{Binding SearchMode, Converter={StaticResource RadioToEnumConverter}, ConverterParameter={x:Static t:SearchMode.RegularExpressions}}"/>
</StackPanel>
</GroupBox>
</StackPanel>
<StackPanel Orientation="Vertical" Margin="10,0,0,0">
<Button Content="{x:Static p:Strings.SearchWindow_FindNext}" Width="150" Margin="{StaticResource DialogItemsVMargin}" Command="{Binding FindNextCommand}" />
<Button Content="{x:Static p:Strings.SearchWindow_Replace}" Width="150" Margin="{StaticResource DialogItemsVMargin}" Command="{Binding ReplaceCommand}"/>
<Separator Margin="{StaticResource DialogItemsVMargin}" />
<Button Content="{x:Static p:Strings.SearchWindow_ReplaceAll}" Width="150" Margin="{StaticResource DialogItemsVMargin}" Command="{Binding ReplaceAllCommand}"/>
<CheckBox Content="{x:Static p:Strings.SearchWindow_InSelection}" Margin="{StaticResource DialogItemsVMargin}"
IsEnabled="{Binding SelectionAvailable}" IsChecked="{Binding ReplaceAllInSelection, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<Separator Margin="{StaticResource DialogItemsVMargin}" />
<Button Content="{x:Static p:Strings.SearchWindow_Close}" Width="150" Command="{Binding CloseCommand}"></Button>
</StackPanel>
</StackPanel>
</GroupBox>
</TabItem>
</TabControl>
</Window>
在调用这些方法时,我应该怎么做才能正确地将焦点设置到特定元素?
您可以尝试这样的操作:
Dispatcher.BeginInvoke(
DispatcherPriority.ContextIdle,
new Action(delegate()
{
tbSearchSearch.Focus();
}));
来自这个link:Alternative to set focus from within the Enter event