正如您在上图所示,我在列表框中有三列。
第一列是FirstName,第二列是LastName,第三列是Age。
当我在年龄栏上按Enter键时,新的人员被添加到列表中。这最终反映了ListBox的变化。
问题:
当我在年龄栏上按 Enter 时,我按预期添加了一个新的Person。但焦点不会转到下一个ListItem。无论我按 Enter 多少次,我都不会专注于以编程方式添加的项目。
示例:
我创建了一个重现问题的示例项目:
我有一个ListBox如下:
<ListBox ItemsSource="{Binding People}" SelectedItem="{Binding SelectedPerson}">
<ListBox.Resources>
<Style TargetType="ListBoxItem" BasedOn="{StaticResource {x:Type ListBoxItem}}">
<Style.Triggers>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="IsSelected" Value="True"></Setter>
</Trigger>
</Style.Triggers>
<Setter Property="Focusable" Value="False" />
</Style>
</ListBox.Resources>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid x:Name="CurrentItemGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200" />
<ColumnDefinition Width="200" />
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<TextBox Text="{Binding FirstName, UpdateSourceTrigger=PropertyChanged}" Tag="IgnoreEnterKeyTraversal">
<TextBox.InputBindings>
<KeyBinding Command="{Binding DataContext.DeleteUnwantedOrderItemTransactionCommand,
RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"
Gesture="Return" />
<KeyBinding Command="{Binding DataContext.DeleteUnwantedOrderItemTransactionCommand,
RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"
Gesture="Tab" />
</TextBox.InputBindings>
</TextBox>
<TextBox Grid.Column="1" Text="{Binding LastName, UpdateSourceTrigger=PropertyChanged}" Margin="5,0"/>
<TextBox Grid.Column="2" Text="{Binding Age, UpdateSourceTrigger=PropertyChanged}" Margin="5,0" Tag="IgnoreEnterKeyTraversal">
<TextBox.InputBindings>
<KeyBinding Command="{Binding DataContext.AddNewOrderItemTransactionCommand,
RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"
Gesture="Return" />
<KeyBinding Command="{Binding DataContext.AddNewOrderItemTransactionCommand,
RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"
Gesture="Tab" />
</TextBox.InputBindings>
</TextBox>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
在ViewModel中:
public class MainWindowViewModel : INotifyPropertyChanged
{
IEventAggregator eventAggregator;
public MainWindowViewModel(IEventAggregator _eventAggregator)
{
People = new ObservableCollection<Person>();
People.Add(new Person());
eventAggregator = _eventAggregator;
DeleteUnwantedOrderItemTransactionCommand = new RelayCommand(DeleteUnwantedOrderItemTransaction);
AddNewOrderItemTransactionCommand = new RelayCommand(AddNewOrderItemTransaction);
}
public RelayCommand DeleteUnwantedOrderItemTransactionCommand { get; set; }
public RelayCommand AddNewOrderItemTransactionCommand { get; set; }
private ObservableCollection<Person> _People;
public ObservableCollection<Person> People
{
get
{
return _People;
}
set
{
if (_People != value)
{
_People = value;
OnPropertyChanged("People");
}
}
}
private Person _SelectedPerson;
public Person SelectedPerson
{
get
{
return _SelectedPerson;
}
set
{
if (_SelectedPerson != value)
{
_SelectedPerson = value;
OnPropertyChanged("SelectedPerson");
}
}
}
protected void DeleteUnwantedOrderItemTransaction(object obj)
{
if (SelectedPerson.FirstName == "")
{
People.Remove(SelectedPerson);
}
if (People.Count == 0)
{
People.Add(new Person());
}
eventAggregator.GetEvent<ChangeFocusToNextUIElementEvent>().Publish(true);
}
protected void AddNewOrderItemTransaction(object obj)
{
if (SelectedPerson == People.Last())
People.Add(new Person());
eventAggregator.GetEvent<ChangeFocusToNextUIElementEvent>().Publish(true);
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}
在Code-Behind中:
public partial class MainWindow : Window
{
IEventAggregator _eventAggregator = new EventAggregator();
public MainWindow()
{
InitializeComponent();
this.DataContext = new MainWindowViewModel(_eventAggregator);
_eventAggregator.GetEvent<ChangeFocusToNextUIElementEvent>().Subscribe(MoveToNextUIElement);
}
void MoveToNextUIElement(bool obj)
{
// Gets the element with keyboard focus.
UIElement elementWithFocus = Keyboard.FocusedElement as UIElement;
if (elementWithFocus != null)
{
elementWithFocus.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
}
}
}
答案 0 :(得分:1)
当您触发事件时,您已将元素添加到VM,但它可能尚未被View(ListBox)绑定和创建。以低优先级调度焦点请求可能会有所帮助。同时检查您是否可以通过按TAB访问该元素,以便了解遍历工作。
elementWithFocus.Dispatcher.Invoke(() =>
elementWithFocus.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next)),
DispatcherPriority.Input); // !
ListBox元素的虚拟化也可能是个问题。您必须将添加的项目置于视图中。
cheeers。