语境WPF - 无法移动光标到视图模型属性更改一个TextBox
一个WPF基于MVVM(没有框架)应用程序。 XAML出现在下面。
问题 每当searchRegistration文本框失去焦点的视图模型属性EditingState获得通过一个ICommand改变。在这种情况下,EditingState更改为“搜索”,这会导致一些触发器。对于airframeBasicDetails网格,应该启用网格,具有蓝色背景并将编辑光标设置到typeName字段中。这工作,除了游标未设置。事实上,它在窗口的任何地方都不可见。这确定了状态改变发生并触发了触发器,但由于某种原因光标没有移动。
问题
如何将编辑光标移动到类型名称时EditingState成为“搜索”?
注意
我建立了这个应用程序,它完美的作品的一个简化版本。我已经寻找该版本和问题版本之间的差异,但找不到任何东西,因此我发布整个失败的脚本尽可能配对。我不愿意删除太多,以免我的问题存在。
<Window x:Class="ADB_Desktop.MainWindow"
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:ADB_Desktop"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:controls="clr-namespace:System.Windows.Controls;assembly=DotNetProjects.Input.Toolkit"
mc:Ignorable="d"
Title="ADB Desktop"
Width="1100"
Height="800"
FocusManager.FocusedElement="{Binding ElementName=searchRegistration}">
<Window.Resources>
<!-- Binding proxy-->
<local:BindingProxy x:Key="proxy" Data="{Binding}"/>
</Window.Resources>
<DockPanel Name="mainDockPanel" LastChildFill="True">
<Menu Name="mainMenu" DockPanel.Dock="Top">
<Menu.Background>
<SolidColorBrush Color="{DynamicResource ADBMenuStatusBarColour}"/>
</Menu.Background>
<MenuItem Header="_Maintenance"/>
<MenuItem Header="_Reports"/>
</Menu>
<StatusBar x:Name="statusBar" DockPanel.Dock="Bottom" Height="25">
<StatusBar.Background>
<SolidColorBrush Color="{DynamicResource ADBMenuStatusBarColour}"/>
</StatusBar.Background>
</StatusBar>
<TabControl x:Name="mainTabControl" Background="{DynamicResource ADBMainBackgroundColour}" SelectedIndex="1">
<TabItem Header="Gallery"/>
<TabItem Header="Airframes">
<Grid x:Name="airframesGrid">
<Grid.RowDefinitions>
<RowDefinition x:Name="airframeAndImageRow" Height="380"/>
<RowDefinition x:Name="identitiesRow"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="airframeCell" Width="400"/>
<ColumnDefinition x:Name="pictureCell"/>
</Grid.ColumnDefinitions>
<Grid Grid.Column="0">
<Grid.RowDefinitions>
<RowDefinition x:Name="searchRow" Height="80"/>
<RowDefinition x:Name="detailsRow" Height="180"/>
<RowDefinition x:Name="sightingsFlightRow" Height="120"/>
</Grid.RowDefinitions>
<Border Grid.Row="0" BorderBrush="DarkGray" BorderThickness="2" CornerRadius="4" Margin="2">
<Grid Grid.Row="0" Margin="5">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="searchLabelCell" MaxWidth="100"/>
<ColumnDefinition x:Name="searchCell" MinWidth="180"/>
<ColumnDefinition x:Name="researchCell"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0">
<Label VerticalAlignment="Top" Content="Registration:"/>
</StackPanel>
<StackPanel Grid.Column="1">
<StackPanel Orientation="Horizontal">
<TextBox x:Name="searchRegistration" CharacterCasing="Upper" Grid.Column="0" Margin="5" Height="20" Width="80" HorizontalAlignment="Left"
Text="{Binding SearchRegistration, UpdateSourceTrigger=LostFocus}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="LostFocus">
<i:InvokeCommandAction Command="{Binding SearchSaveCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<TextBox.Style>
<Style TargetType="TextBox">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=EditingState}" Value="{x:Static local:EditingState.Initial}">
<Setter Property="IsEnabled" Value="True"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=EditingState}" Value="{x:Static local:EditingState.Search}">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=EditingState}" Value="{x:Static local:EditingState.New}">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
</StackPanel>
</StackPanel>
</Grid>
</Border>
<Border Grid.Row="1" BorderBrush="DarkGray" BorderThickness="2" CornerRadius="4" Margin="2">
<Grid Name="airframeBasicDetails" Grid.Row="1" Margin="5">
<Grid.Style>
<Style TargetType="{x:Type Grid}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=EditingState}" Value="{x:Static local:EditingState.Initial}">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=EditingState}" Value="{x:Static local:EditingState.Search}">
<Setter Property="IsEnabled" Value="True"/>
<Setter Property="FocusManager.FocusedElement" Value="{Binding ElementName=typeName}"/>
<Setter Property="Background" Value="Blue"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=EditingState}" Value="{x:Static local:EditingState.New}">
<Setter Property="IsEnabled" Value="True"/>
<Setter Property="FocusManager.FocusedElement" Value="{Binding ElementName=typeName}"/>
<Setter Property="Background" Value="Blue"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Style>
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="airframeLabels" MaxWidth="100"/>
<ColumnDefinition x:Name="airframeDetails"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition x:Name="typeRow"/>
<RowDefinition x:Name="constructionNoRow"/>
<RowDefinition x:Name="remarksRow"/>
<RowDefinition x:Name="rolledOutDateRow"/>
<RowDefinition x:Name="firstFlightDateRow"/>
<RowDefinition x:Name="statusRow"/>
</Grid.RowDefinitions>
<Label Grid.Column="0" Grid.Row="0">Type</Label>
<controls:AutoCompleteBox Grid.Column="1" Grid.Row="0" Margin="5" Height="20" Width="270" HorizontalAlignment="Left" VerticalAlignment="Center"
Name="typeName"
Text="{Binding Path=AirframeCollectionView/TypeName, UpdateSourceTrigger=PropertyChanged}"
ItemsSource="{Binding Path=TypeNames}"
IsTextCompletionEnabled="True"
FilterMode="Contains" >
</controls:AutoCompleteBox>
<Label Grid.Column="0" Grid.Row="1">Construction no</Label>
<TextBox Grid.Column="1" Grid.Row="1" Margin="5" x:Name="constructionNo" Height="20" Width="80" HorizontalAlignment="Left" VerticalAlignment="Center"
Text="{Binding AirframeCollectionView/ConstructionNumber}"/>
</Grid>
</Border>
</Grid>
</Grid>
<Image x:Name="airframePicture" Grid.Row="0" Grid.Column="1"/>
</Grid>
</TabItem>
</TabControl>
</DockPanel>
</Window>
重温我简单的例子,我注意,我用一个按钮来触发改变EditingState。当我按照我的问题代码将触发器更改为跳出TextBox时,问题就出现了。因此,我认为这与使用Tab键I.e的效果有关。在触发器完成其工作后,Tab键具有进一步改变焦点的效果。搜索继续... – ifinlay
我相信如此 - 试图改变焦点,而UI线程已经忙于改变焦点,并在处理与焦点相关的事件时可能会遇到麻烦。为什么不尝试推迟焦点更改,直到UI线程完成所有与焦点相关的处理? (例如,通过在Dispatcher.BeginInvoke或Dispatcher.InvokeAsync的帮助下将相应的操作添加到调度程序队列中) – elgonzo
@elgonzo好主意。这将是我第一次进入Dispatcher古怪的世界,所以我可能花一点时间把解决方案放在一起。我认为这将涉及降低ICommand的优先级,以便在ICommand导致状态更改和结果数据触发之前,可以在UI线程中完成Tab处理。当我开始工作时,我会发布一些内容,然后可以将您的观察结果标记为答案。 – ifinlay