在研究文本框上按Enter后,第一个结果DataGrid的WPF自动单击按钮

时间:2018-07-06 10:46:33

标签: c# wpf mvvm

我正在处理WPF MVVM项目。 DataGrid显示服务找到的记录。每行都有一个按钮,该按钮将执行一个与选定记录一起执行的操作。

public class ReferenceDossier
{
}

XAML

<GroupBox>
    <Grid>
        <StackPanel>
            <TextBox>
                <TextBox.InputBindings>
                    <KeyBinding Key="Enter" Command="{Binding SearchCommand}"/>
                </TextBox.InputBindings>
            </TextBox>
        </StackPanel>
    </Grid>
</GroupBox>

<GroupBox>
    <Grid>
        <StackPanel>
            <DataGrid ItemsSource="{Binding ReferenceDossiers}">
                <DataGrid.Columns>
                    <DataGridTemplateColumn>
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <Button Command="{Binding Command}"
                                                CommandParameter="{Binding}">>
                                    <iconPacks:PackIconFontAwesome Kind="PlusCircle" Foreground="#FF94bf00"/>
                                </Button>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>
                </DataGrid.Columns>
            </DataGrid>
        </StackPanel>
    </Grid>
</GroupBox>

当我使用TextBox中的关键字进行搜索并点击Enter时,它将执行计算并在DataGrid中显示结果。

我要编码的内容:

如果用户再次按ENTER(在DataGrid中显示的记录之后)并且用户尚未选择行,则第一行Command中的Button必须为在调用网格中的多少条记录(并不重要)时,必须选择第一个。

如果用户在DataGrid中选择一行并按Enter,则该行Command中的Button被调用。

如果记录为零,则什么也不做。

目标是减少在GUI上进行选择的时间。

但是我找不到通过MVVM方法做到这一点的方法。

通过一些尝试,当我点击关键字后按ENTER时,TextBox始终处于焦点状态。我再次按ENTER,它将重新执行计算。

2 个答案:

答案 0 :(得分:0)

您可以使用EventTrigger来实现。

XAML

<Style TargetType="DataGridRow">
    <Style.Triggers>
        <local:EnterDownEventTrigger EventName="KeyDown">
            <i:InvokeCommandAction Command="{Binding Command}" CommandParameter="{Binding}"/>
        </local:EnterDownEventTrigger>
    </Style.Triggers>
</Style>

由于只希望通过 Enter 键调用Command,因此需要为此编写自定义EventTrigger

输入键的自定义事件触发器

using System.Windows.Interactivity;
public class EnterDownEventTrigger : EventTrigger 
{    
    public EnterDownEventTrigger() : base("KeyDown") { }

    protected override void OnEvent(EventArgs eventArgs) 
    {
        var e = eventArgs as KeyEventArgs;
        if (e != null && e.Key == Key.Enter)
            this.InvokeActions(eventArgs);
    }
}

引用程序集: System.Windows.Interactivity.dll

答案 1 :(得分:0)

找到解决方案:

在此answer之后,我们可以将焦点设置为由自定义属性IsFocused控制。

因此,我将此属性置于按钮上,如果该属性位于第一行,则将该属性设置为true并绑定Enter InputBinding

public class ReferenceDossier : INotifyPropertyChanged
    {
        private bool _selected;
        public bool Selected
        {
            get
            {
                return _selected;
            }
            set
            {
                _selected = value;
                RaisePropertyChanged("Selected");
            }
        }
}

为第一条记录设置Selected,以使第一行的按钮聚焦。

if(ReferenceDossiers.FirstOrDefault() != null)
                    ReferenceDossiers.First().Selected = true;

XAML

                     <DataGridTemplateColumn>
                            <DataGridTemplateColumn.CellStyle>
                                <Style TargetType="DataGridCell">
                                    <Setter Property="IsTabStop" Value="False" />
                                    <Setter Property="BorderThickness" Value="0"/>                                        
                                </Style>
                            </DataGridTemplateColumn.CellStyle>
                            <DataGridTemplateColumn.CellTemplate>
                                <DataTemplate>
                                    <Button behaviors:FocusExtension.IsFocused="{Binding Selected}"
                                         Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type controls:MetroWindow}}, Path=DataContext.AddCommand}"
                                            CommandParameter="{Binding}">
                                        <Button.InputBindings>
                                            <KeyBinding Key="Enter" Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type controls:MetroWindow}}, Path=DataContext.AddCommand}"
                                            CommandParameter="{Binding}"/>
                                        </Button.InputBindings>
                                        <iconPacks:PackIconFontAwesome Kind="PlusCircle" Foreground="#FF94bf00"/>
                                    </Button>
                                </DataTemplate>
                            </DataGridTemplateColumn.CellTemplate>
                        </DataGridTemplateColumn>

要通过上/下键选择其他行的按钮,我们应该自定义单元格,否则,CellTemplate会集中在该按钮上,而ENTER键不起作用。