Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/289.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在Tab键上向列表框添加新项目_C#_Wpf_Listbox_Listboxitem_Attachedbehaviors - Fatal编程技术网

C# 在Tab键上向列表框添加新项目

C# 在Tab键上向列表框添加新项目,c#,wpf,listbox,listboxitem,attachedbehaviors,C#,Wpf,Listbox,Listboxitem,Attachedbehaviors,我有一个WPF列表框,其中有一个用于列表框ItemTemplate的自定义数据模板(每个项目都有一组控件;即文本框和日期选择器)。最后一个日期选择器附带了一个行为,允许用户在PreviewKeyDown事件的事件处理程序中执行ICommand 这样做的目的是,用户将通过ListBoxItem中的控件进行TAB,当它们到达最后一个控件时,再次按TAB键,一个新的ListBoxItem get将添加到ListBox中。然后焦点将移动到下一个ListBoxItem中的第一个控件。如果列表框中已经有2个

我有一个WPF列表框,其中有一个用于列表框ItemTemplate的自定义数据模板(每个项目都有一组控件;即文本框和日期选择器)。最后一个日期选择器附带了一个行为,允许用户在PreviewKeyDown事件的事件处理程序中执行ICommand

这样做的目的是,用户将通过ListBoxItem中的控件进行TAB,当它们到达最后一个控件时,再次按TAB键,一个新的ListBoxItem get将添加到ListBox中。然后焦点将移动到下一个ListBoxItem中的第一个控件。如果列表框中已经有2个项目,并且您正在切换第一个项目,则我的解决方案可以正常工作。如果ListBox中只有1个项,并且您到达最后一个控件,则会添加新的ListBoxItem(如预期的那样),但焦点会从ListBox移到下一个父控件

这就像调用行为代码和ICommand一样,但是TAB事件继续进行,而不等待添加新的ListBoxItem

有什么建议吗

我的行为(ZBehaviorBase只是一个允许“更好”清理的类):

公共类TabOffCommandBehavior:ZBehaviorBase
{
公共ICommand命令
{
获取{return(ICommand)GetValue(CommandProperty);}
set{SetValue(CommandProperty,value);}
}
公共静态只读DependencyProperty CommandProperty=
Register(“TabCommand”、typeof(ICommand)、typeof(TabOffCommandBehavior));
受保护的覆盖无效初始化()
{
this.AssociatedObject.PreviewKeyDown+=新的KeyEventHandler(AssociatedObject\u PreviewKeyDown);
}
受保护的覆盖无效取消初始化()
{
if(this.AssociatedObject!=null)
{
this.AssociatedObject.PreviewKeyDown-=新的KeyEventHandler(AssociatedObject\u PreviewKeyDown);
}
}
void associated object_PreviewKeyDown(对象发送方,KeyEventArgs e)
{
//如果要将命令参数传递给CanExecute,则需要添加另一个要绑定的依赖项属性
if(TabCommand!=null&&e.Key==Key.Tab&&TabCommand.CanExecute(null))
{
TabCommand.Execute(null);
}
}
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>
<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>

在“LineTemplate”内:

<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>
<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>

在命令的“Execute”方法中完成的唯一一件事是将一个对象添加到一个集合中,该集合是ListBox的ItemsSource

if (e.KeyCode == Keys.Tab)

在AddNewOrderLine方法中,尝试在添加的新项目上设置焦点。然后,为防止焦点更改,请修改以下代码:

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;
    }
}

您是否在列表框中尝试过此选项:

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

或者这个:

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


或者两者都有?

KeyCode是WinForms属性,是WinForms世界中的KeyDown处理程序的一部分。我正在处理WPF。另外,我已经在用e.Key==Key.Tab测试Tab了。你可以添加更多的代码吗?例如,我想看看你在哪里处理添加新控件。我明天可以,但这是在我的视图模型中完成的。当我调用com时另外,我在observablecollection中添加了一个项,它是列表框的项源。我还需要进一步研究它,但只需在您自己的TabCommand中处理焦点更改,并中断键关闭事件,可能就可以了。@TomGarske不确定“中断键关闭事件”是什么意思但是我按照您的要求添加了代码。我可能不理解这个问题,但是您是否尝试过设置事件e.Handled=true;然后手动将焦点设置在正确的对象上?您建议我如何将焦点设置到新项?我特别想要的是第一个输入字段(即文本框)在新的ListBoxItem上有焦点,但由于我正在通过命令和ViewModel中的ObservableCollection向ListBoxItem添加,因此我没有直接访问权限(我也不应该)可以创建一个自定义控件并将逻辑放入构造函数中——这样每次创建一个新的ListBox时,它都会为它的第一个项获取焦点。我想这是一个选项——将ListBoxItem DataTemplate转换为自定义控件——但如果不是这样的话,我宁愿不走这条路非常必要。我可能可以通过绑定来处理它……我在想一些关于viewmodel(ListBoxItem的datacontext)属性的事情,第一个文本框可以绑定到告诉它应该有焦点,然后