gpt4 book ai didi

wpf - WPF焦点,无法同时获得逻辑和键盘焦点

转载 作者:行者123 更新时间:2023-12-03 10:34:12 25 4
gpt4 key购买 nike

我浏览过其他一些有关WPF和关注点的文章,据我所知,我的代码中确实缺少一些东西。我正在使用严格的MVVM开发应用程序,因此我试图避免 View 文件中出现任何代码隐藏(在需要代码隐藏的情况下使用附加行为),但此时甚至将焦点代码放在代码中- View 的后面是行不通的。

我有一个带有主窗口的应用程序,并且试图在热键上弹出搜索窗口。我想在用户按下热键后立即将键盘焦点放在搜索文本上,因此它只是热键,然后键入您的搜索词。尽管逻辑焦点在此点上仍在起作用,即使键盘声称已将焦点放在元素上。

我似乎无法从代码中同时获取键盘和逻辑焦点。但是,如果我在搜索框出现后立即点击Tab键,那么我将直接进入文本框。

主窗口代码:

<ribbon:RibbonWindow x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ribbon="clr-namespace:Microsoft.Windows.Controls.Ribbon;assembly=RibbonControlsLibrary"
xmlns:attached="clr-namespace:UserInterface.Attached"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:command="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WPF45"
xmlns:viewModels="clr-namespace:UserInterface.ViewModels"
xmlns:views="clr-namespace:UserInterface.Views"
xmlns:layout="clr-namespace:UserInterface.ViewModels.Layout"
xmlns:layout1="clr-namespace:UserInterface.Views.Layout"
MinHeight="560"
MinWidth="950"
WindowStartupLocation="CenterScreen"
Icon="{Binding Layout.IconPath}"
DataContext="{Binding Main, Source={StaticResource Locator}}"
FocusManager.FocusedElement="{Binding ElementName=LayoutControl}"
Title="{Binding Layout.Title}">

<!-- Ribbon menu shortcuts -->
<Window.InputBindings>
<KeyBinding Modifiers="Control" Key="T" Command="{Binding Layout.Commands[GlobalObjectSearch]}" />
</Window.InputBindings>

<Grid>
<ContentPresenter Content="{Binding Layout}" x:Name="LayoutControl">
<ContentPresenter.Resources>
<DataTemplate DataType="{x:Type layout:MainViewModel}">
<layout1:MainView/>
</DataTemplate>
</ContentPresenter.Resources>
</ContentPresenter>
</Grid>
</ribbon:RibbonWindow>

使搜索窗口出现的代码:
    public SelfClosingDialogView ShowSelfClosingDialog(IWindowDialogViewModel dataContext)
{
dataContext.CheckWhetherArgumentIsNull(nameof(dataContext));

var view = new SelfClosingDialogView
{
DataContext = dataContext,
Owner = Application.Current?.MainWindow
};

view.Show();

return view;
}

搜索窗口代码(已重用,因此很通用):
<Window x:Class="UserInterface.Views.DialogViews.SelfClosingDialogView"
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:attached="clr-namespace:UserInterface.Attached"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
mc:Ignorable="d"
SizeToContent="WidthAndHeight"
WindowStyle="None"
WindowStartupLocation="CenterOwner">

<!-- Allow view models to cause the window to close -->
<Window.Style>
<Style TargetType="{x:Type Window}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsClosed}" Value="true">
<!-- Executes close -->
<Setter Property="attached:WindowCloseBehavior.Close" Value="true" />
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Style>

<!-- Displays the passed-in view model -->
<Grid>
<ContentPresenter x:Name="DialogPresenter" Content="{Binding}" Margin="0" />
</Grid>
</Window>

我的搜索 View 的代码:
<UserControl x:Class="UserInterface.Views.DialogViews.ObjectSearchView"
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"
xmlns:dialogViewModels="clr-namespace:UserInterface.ViewModels.DialogViewModels"
xmlns:utils="clr-namespace:WPF.Utils"
xmlns:attached="clr-namespace:UserInterface.Attached"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance dialogViewModels:ObjectSearchViewModel}"
MinWidth="250"
Focusable="True"
FocusManager.IsFocusScope="True">
<UserControl.InputBindings>
<KeyBinding Key="Enter" Command="{Binding BrowseToObjectCommand}" />
<KeyBinding Key="Escape" Command="{Binding CloseWindowCommand}" />
</UserControl.InputBindings>
<UserControl.Resources>
<Style BasedOn="{StaticResource FormTextBlockStyle}" TargetType="TextBlock" />
</UserControl.Resources>

<StackPanel>
<TextBox Name="SearchText"
Focusable="True"
Text="{utils:ValidatingLiveBinding SearchText}"
attached:NavigatingListBoxBehavior.LinkedListBox="{Binding ElementName=SearchResults}">
</TextBox>
<ScrollViewer HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Auto"
MaxHeight="400">
<ListBox Name="SearchResults"
ItemsSource="{Binding SearchResults}"
SelectedItem="{Binding SelectedSearchItem}"
Visibility="{Binding HasSearchResults, Converter={StaticResource BooleanToVisibilityConverter}}"
attached:ItemsControlProperties.DoubleClickCommand="{Binding BrowseToObjectCommand}"
KeyboardNavigation.IsTabStop="False"
IsSynchronizedWithCurrentItem="True" />
</ScrollViewer>
</StackPanel>
</UserControl>

最后,我试图获得焦点的代码隐藏技巧(加上调试代码,这样我就不会失去来回切换到Visual Studio的焦点):
public partial class ObjectSearchView : UserControl
{
public ObjectSearchView()
{
InitializeComponent();
this.Loaded += this.OnLoad;
}

private void OnLoad(object sender, RoutedEventArgs e)
{
this.PrintFocusInfo();
FocusManager.SetFocusedElement(FocusManager.GetFocusScope(this), this.SearchText);
this.PrintFocusInfo();
this.SearchText.Focus();
this.PrintFocusInfo();
Keyboard.Focus(this.SearchText);
this.PrintFocusInfo();
}

[Conditional("DEBUG")]
private void PrintFocusInfo()
{
var logicalElement = FocusManager.GetFocusedElement(FocusManager.GetFocusScope(this.SearchText));
Debug.WriteLine("Current logical focus is on '{0}', of type '{1}' ({2})".FormatInvariantCulture((logicalElement as FrameworkElement)?.Name, logicalElement?.GetType().Name, logicalElement));
var focusedElement = Keyboard.FocusedElement;
Debug.WriteLine(
"Current Keyboard Focus is on '{0}', of type '{1}' ({2})".FormatInvariantCulture(
(focusedElement as FrameworkElement)?.Name,
focusedElement.GetType().Name,
focusedElement));
}
}

输出窗口内容:
Current logical focus is on '', of type '' ()
Current Keyboard Focus is on '', of type 'MainWindow' (UserInterface.Views.MainWindow)
Current logical focus is on '', of type '' ()
Current Keyboard Focus is on '', of type 'MainWindow' (UserInterface.Views.MainWindow)
Current logical focus is on '', of type '' ()
Current Keyboard Focus is on 'SearchText', of type 'TextBox' (System.Windows.Controls.TextBox)
Current logical focus is on '', of type '' ()
Current Keyboard Focus is on 'SearchText', of type 'TextBox' (System.Windows.Controls.TextBox)

我试图包括我能想到的所有内容,但是我无法逻辑地显示除null以外的任何内容。

最佳答案

这是我最终创建的行为,可以为我解决此问题。我仍然不知道为什么能正常工作的很多事情……但是,如果您在让Focus进行协作时遇到问题,那么当IsVisible设置为true时,就好像 key 在捕获它,并由Dispatcher来设置焦点为你。我将此事件链接到文本框上的IsVisibleChanged元素(通过附加的行为)。

    private void SetFocusOnVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if ((bool)e.NewValue)
{
this.Dispatcher.BeginInvoke(DispatcherPriority.ContextIdle, new Action(() => this.AssociatedObject.Focus()));
}
}

关于wpf - WPF焦点,无法同时获得逻辑和键盘焦点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39946794/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com