ListBox ItemTemplate のカスタム DataTemplate を持つ WPF ListBox があります (各項目には一連のコントロールがあります。つまり、テキスト ボックスと日付ピッカー)。ユーザーが PreviewKeyDown イベントのイベント ハンドラーで ICommand を実行できるようにする Behavior を最後の DatePicker にアタッチしました。
これは、ユーザーが ListBoxItem 内のコントロールを TAB で移動し、最後のコントロールに移動してもう一度 TAB を押すと、新しい ListBoxItem が ListBox に追加されるという考え方です。フォーカスは、次の ListBoxItem の最初のコントロールに移動します。ListBox に既に 2 つの項目があり、最初の項目をタブで移動している場合、私のソリューションは正常に機能します。ListBox に項目が 1 つしかなく、最後のコントロールに到達すると、新しい ListBoxItem が (予想どおり) 追加されますが、フォーカスは ListBox を超えて次の親コントロールに移動します。
Behavior コードが呼び出され、ICommand が呼び出されるようなものですが、新しい ListBoxItem が追加されるのを待たずに TAB イベントが続行されます。
助言がありますか?
私の行動(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:
<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":
<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>
コマンドの「実行」メソッドで行われる唯一のことは、ListBox の ItemsSource であるコレクションにオブジェクトが追加されることです。