在列表视图中的网格视图中选中/取消选中带有空格/输入的复选框 - wpf

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16939859/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 08:56:11  来源:igfitidea点击:

Check/Uncheck checkbox with Space/Enter in gridview in listview - wpf

c#wpfxamlgridview

提问by quitprog

I have a GridViewwith CheckBoxas a column and TextBlockas another column. Here is the XAMLcode:

我有一个GridViewwithCheckBox作为一列和TextBlock另一列。这是XAML代码:

<ListView.View>
    <GridView>
        <GridView.ColumnHeaderContainerStyle>
            <Style>
                <Setter Property="UIElement.Visibility"
                        Value="Collapsed"/>
            </Style>
        </GridView.ColumnHeaderContainerStyle>

        <GridViewColumn>
            <GridViewColumn.CellTemplate>
                <DataTemplate>
                    <CheckBox Tag="{Binding}"
                              IsChecked="{Binding Path=IsFormChecked, Mode=TwoWay}"
                              IsEnabled="{Binding Path=IsUnRestricted}"
                              IsThreeState="False" 
                              UIElement.KeyUp="CheckBox_KeyUp" />
                </DataTemplate>
            </GridViewColumn.CellTemplate>
        </GridViewColumn>

        <GridViewColumn Width="auto">
            <GridViewColumn.CellTemplate>
                <DataTemplate>
                    <TextBlock Width="600"
                               Tag="{Binding}"
                               IsEnabled="{Binding Path=IsUnRestricted}"
                               Text="{Binding Path=FormName}" 
                               MouseUp="TextBlock_MouseUp">
                        <TextBlock.ToolTip>
                            <TextBlock Text="{Binding Path=FormName}"/>
                        </TextBlock.ToolTip>
                    </TextBlock>
                </DataTemplate>
            </GridViewColumn.CellTemplate>
        </GridViewColumn>
    </GridView>
</ListView.View>

When I access this GridViewwith the keyboard complete row is selected (CheckBoxas well as TextBlock). Now at this point if i press space key, nothing happens. If I want to access the CheckBoxwith keyboard, I have to press tab key once more so that focus is set on checkbox and the I can check/uncheck it using space bar. What I want to do is when the focus is on the row I want to check/uncheck checkbox with only one key press of space bar.

当我使用GridView键盘访问它时,选择了完整的行(CheckBox以及TextBlock)。现在,如果我按空格键,则什么也不会发生。如果我想CheckBox使用键盘访问,我必须再次按 Tab 键,以便将焦点设置在复选框上,并且我可以使用空格键选中/取消选中它。我想要做的是当焦点位于我想要选中/取消选中复选框的行上时,只需按一下空格键。

采纳答案by RoelF

If you have a binding on the currently selected item, you can handle the PreviewKeyUpevent on your ListView:

如果您对当前选定的项目进行了绑定,则可以PreviewKeyUp在您的 上处理该事件ListView

<ListView PreviewKeyUp="OnGridKeyUp"
          SelectedItem="{Binding MySelectedItem}"
          SelectionMode="Single"
          ItemsSource="{Binding ItemsList}">
    ...
</ListView>

and then handle this in code-behind:

然后在代码隐藏中处理这个:

private void OnGridKeyUp(object sender, KeyEventArgs e)
{
    if(vm.mySelectedItem != null && e.Key == Key.Space)
    {
        vm.MySelectedItem.IsChecked = !vm.MySelectedItem.IsChecked;
        e.Handled = true; //this is necessary because otherwise when the checkbox cell is selected, it will apply this keyup and also apply the default behavior for the checkbox
    }
}

This obviously requires you to have a handle on your viewmodel from your code behind. This could be as easy as:

这显然需要您从背后的代码中处理您的视图模型。这可能很简单:

var vm = DataContext as MyViewModel;

this is not the most MVVM way, but hey...

这不是最 MVVM 的方式,但是嘿...

回答by DLeh

I made a more MVVM friendly way to do this:

我做了一个更 MVVM 友好的方式来做到这一点:

Step 1: Create this behavior

第 1 步:创建此行为

public class ToggleSelectOnSpace : Behavior<DataGrid>
{
    public static readonly DependencyProperty toggleSelectCommand =
        DependencyProperty.Register("ToggleSelectCommand",
        typeof(ICommand),
        typeof(ToggleSelectOnSpace));

    public ICommand ToggleSelectCommand
    {
        get { return this.GetValue(toggleSelectCommand) as ICommand; }
        set { this.SetValue(toggleSelectCommand, value); }
    }

    protected override void OnAttached()
    {
        base.OnAttached();

        this.AssociatedObject.PreviewKeyUp += PreviewKeyUp;
    }

    protected override void OnDetaching()
    {
        this.AssociatedObject.PreviewKeyUp -= PreviewKeyUp;
        base.OnDetaching();
    }

    private void PreviewKeyUp(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.Space)
        {
            if (ToggleSelectCommand != null)
            {
                ToggleSelectCommand.Execute(this.AssociatedObject.SelectedItems);
            }
        }
    }
}

Step 2: Implement a command like this in your View Model (method logic for the command)

第 2 步:在您的视图模型中实现这样的命令(命令的方法逻辑)

    private void ToggleSelectParticipant(object selectedObjects)
    {
        var items = (System.Collections.IList)selectedObjects;
        var collection = items.Cast<MyItemType>().ToList();
        bool selection = !collection.All(x => x.IsSelected);
        foreach (var item in collection)
            item.IsSelected = selection;
    }

Step 3: Bind the behavior to the grid, and bind the command to the behavior

第三步:将行为绑定到网格,将命令绑定到行为

<DataGrid>
    <i:Interaction.Behaviors>
        <shared:ToggleSelectOnSpace ToggleSelectCommand="{Binding Data.ToggleSelectParticipantCommand, Source={StaticResource BindingProxy}}" />
    </i:Interaction.Behaviors>
...
</DataGrid>

(Info on the BindingProxy source)

有关 BindingProxy 源的信息