C# 选中/取消选中带有空格的复选框/在listview-wpf的gridview中输入

C# 选中/取消选中带有空格的复选框/在listview-wpf的gridview中输入,c#,wpf,xaml,gridview,C#,Wpf,Xaml,Gridview,我有一个GridView,其中CheckBox作为一列,TextBlock作为另一列。以下是XAML代码: <ListView.View> <GridView> <GridView.ColumnHeaderContainerStyle> <Style> <Setter Property="UIElement.Visibility"

我有一个
GridView
,其中
CheckBox
作为一列,
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>


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

如果您对当前选择的项目有绑定,您可以在
列表视图上处理
PreviewKeyUp
事件:

<ListView PreviewKeyUp="OnGridKeyUp"
          SelectedItem="{Binding MySelectedItem}"
          SelectionMode="Single"
          ItemsSource="{Binding ItemsList}">
    ...
</ListView>
这显然要求您在代码背后拥有viewmodel的句柄。这可以很容易做到:

var vm = DataContext as MyViewModel;

这不是最具MVVM的方式,但嘿…

我用了一种更为MVVM友好的方式来实现这一点:

步骤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);
            }
        }
    }
}
public类切换selectonspace:Behavior
{
public static readonly dependencProperty toggleSelectCommand=
DependencyProperty.Register(“ToggleSelectCommand”,
类型(ICommand),
typeof(ToggleSelectOnSpace));
公共ICommand ToggleSelectCommand
{
get{将this.GetValue(toggleSelectCommand)返回为ICommand;}
设置{this.SetValue(toggleSelectCommand,value);}
}
受保护的覆盖无效附加()
{
base.onatached();
this.AssociatedObject.PreviewKeyUp+=PreviewKeyUp;
}
附加时受保护的覆盖无效()
{
this.AssociatedObject.PreviewKeyUp-=PreviewKeyUp;
base.OnDetaching();
}
private void PreviewKeyUp(对象发送方,KeyEventArgs e)
{
if(e.Key==Key.Space)
{
如果(ToggleSelectCommand!=null)
{
ToggleSelectCommand.Execute(this.AssociatedObject.SelectedItems);
}
}
}
}
步骤2:在视图模型中实现类似的命令(命令的方法逻辑)

private void切换选择参与者(对象选择对象)
{
var items=(System.Collections.IList)selectedObjects;
var collection=items.Cast().ToList();
bool selection=!collection.All(x=>x.IsSelected);
foreach(集合中的var项)
item.IsSelected=选择;
}
步骤3:将行为绑定到网格,并将命令绑定到行为

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

...

()

嘿,我还没有使用MVVM到那种程度,但PreviewKeyUp事件解决了我的问题。谢谢……:)我认为这是一条路要走。我希望实现此解决方案,但我更希望能够绑定到单个项的IsSelected属性(该属性已存在并绑定到复选框),而不必添加命令。我的问题是,我不知道如何将项的属性绑定到行为的属性。你能建议怎么做吗?谢谢你也许应该更彻底地解释你的问题。好的,我已经为它创建了一个问题,试图尽我所能解释它:
    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;
    }
<DataGrid>
    <i:Interaction.Behaviors>
        <shared:ToggleSelectOnSpace ToggleSelectCommand="{Binding Data.ToggleSelectParticipantCommand, Source={StaticResource BindingProxy}}" />
    </i:Interaction.Behaviors>
...
</DataGrid>