简体   繁体   English

在Tab键上向ListBox添加新项目

[英]Adding new items to ListBox on Tab keypress

I have a WPF ListBox, with a custom DataTemplate for the ListBox ItemTemplate (each item has a set of controls; ie textboxes and datepickers). 我有一个WPF ListBox,带有ListBox ItemTemplate的自定义DataTemplate(每个项目都有一组控件;即文本框和日期选择器)。 I have a Behavior attached to the last DatePicker that allows the user to execute ICommand in the event handler for a PreviewKeyDown event. 我有一个附加到最后一个DatePicker的行为,它允许用户在PreviewKeyDown事件的事件处理程序中执行ICommand。

The idea is that the user will TAB through the controls in the ListBoxItem and when they get to the last control, and press TAB again, a new ListBoxItem get's added to the ListBox. 这个想法是用户将通过ListBoxItem中的控件进行TAB,当它们到达最后一个控件时,再次按TAB,新的ListBoxItem get被添加到ListBox中。 The focus will then move to the first control in the next ListBoxItem. 然后焦点将移动到下一个ListBoxItem中的第一个控件。 My solution works fine when there are 2 items already in the ListBox, and you're tabbing through the first item. 当ListBox中已有2个项目时,我的解决方案正常工作,并且您正在浏览第一个项目。 If there's only 1 item in the ListBox, and you get to the last control, the new ListBoxItem is added (as expected) but the focus moves past the ListBox to the next parent control. 如果ListBox中只有1个项目,并且您到达最后一个控件,则会添加新的ListBoxItem(按预期方式),但焦点将移过ListBox到下一个父控件。

It's like the Behavior code gets called and the ICommand gets called, but the TAB event continues on without waiting for the new ListBoxItem to get added. 这就像调用行为代码并调用ICommand,但TAB事件继续,而不等待添加新的ListBoxItem。

Any suggestions? 有什么建议么?

My behavior (ZBehaviorBase is just a class that allows for "better" clean up): 我的行为(ZBehaviorBase只是一个允许“更好”清理的类):

public class TabOffCommandBehavior : ZBehaviorBase<FrameworkElement>
{
    public ICommand TabCommand
    {
        get { return (ICommand)GetValue(CommandProperty); }
        set { SetValue(CommandProperty, value); }
    }

    public static readonly DependencyProperty CommandProperty =
        DependencyProperty.Register("TabCommand", typeof(ICommand), typeof(TabOffCommandBehavior));

    protected override void Initialize()
    {
        this.AssociatedObject.PreviewKeyDown += new KeyEventHandler(AssociatedObject_PreviewKeyDown);
    }

    protected override void Uninitialize()
    {
        if (this.AssociatedObject != null)
        {
            this.AssociatedObject.PreviewKeyDown -= new KeyEventHandler(AssociatedObject_PreviewKeyDown);
        }
    }

    void AssociatedObject_PreviewKeyDown(object sender, KeyEventArgs e)
    {
        // if you want to pass a command param to CanExecute, need to add another dependency property to bind to
        if (TabCommand != null && e.Key == Key.Tab && TabCommand.CanExecute(null))
        {
            TabCommand.Execute(null);
        }
    }

XAML: XAML:

<ListBox Grid.Row="1" KeyboardNavigation.TabNavigation="Continue" ItemsSource="{Binding Path=OrderLines, Mode=OneWay}" 
                 ItemTemplate="{DynamicResource LineTemplate}" SelectionMode="Extended">
    <ListBox.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
            <Setter Property="Margin" Value="0,5,0,5"/>                        
            <Setter Property="BorderThickness" Value="1"/>
            <Setter Property="Template" Value="{DynamicResource ListBoxItemTemplate}"/>
            <Setter Property="IsEnabled" Value="{Binding Path=IsLocked, Converter={StaticResource NotBoolConverter}}"/>
            <Setter Property="IsSelected" Value="{Binding Path=IsSelected}"/>
        </Style>
    </ListBox.ItemContainerStyle>
</ListBox>

INSIDE "LineTemplate": INSIDE“LineTemplate”:

<TextBox Grid.Column="9" Grid.Row="3" Text="{Binding Path=SellPriceOverride, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" VerticalAlignment="Center" Margin="5,0" TabIndex="10">
    <!--IF ANOTHER INTERACTIVE CONTROL IS ADDED PAST THIS ONE ON THE LINE, THIS COMMENT AND THE BEHAVIOR MUST BE MOVED TO THAT CONTROL INSTEAD-->
    <e:Interaction.Behaviors>
         <ZViewModels:TabOffCommandBehavior TabCommand="{Binding Path=DataContext.AddNewOrderLine, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListBox}}"/>
    </e:Interaction.Behaviors>
</TextBox>

The only thing that get's done in the "Execute" method of the command is that an object is added to a collection which is the ItemsSource for the ListBox 在命令的“执行”方法中唯一完成的是将对象添加到集合中,该集合是ListBox的ItemsSource

In your AddNewOrderLine method, try setting the focus on the new item that you add. 在AddNewOrderLine方法中,尝试将焦点设置在您添加的新项目上。 Then to prevent the focus from changing, modify the following code: 然后,为了防止焦点发生变化,请修改以下代码:

void AssociatedObject_PreviewKeyDown(object sender, KeyEventArgs e)
{
    // if you want to pass a command param to CanExecute, need to add another dependency property to bind to
    if (TabCommand != null && e.Key == Key.Tab && TabCommand.CanExecute(null))
    {
        TabCommand.Execute(null);
        e.Handled = true;
    }
}

尝试

if (e.KeyCode == Keys.Tab)

have you tried this on your ListBox : 你在ListBox上尝试过这个吗?

<ListBox FocusManager.IsFocusScope="True" ... >

or this: 或这个:

<ListBox KeyboardNavigation.DirectionalNavigation="Contained" ... >

or both? 或两者?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM