WPF行为以选中/取消选中列表项中的复选框 [英] WPF behaviour to check/uncheck a checkbox in a list item

查看:117
本文介绍了WPF行为以选中/取消选中列表项中的复选框的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有多个项目控件(树视图和其他控件)的应用程序,其中包含一个带有复选框的项目模板。此复选框已选中状态绑定到项目视图模型的IsChecked属性。单击复选框时,此方法可以正常运行,但是无法使用键盘对其进行检查/取消选中(我认为这是由于复选框本身从未获得焦点)。

I have an application with several item controls (treeviews and others) which contain an item template with a checkbox inside. This checkbox checked state is bound to an IsChecked property of the item view model. This works correctly when clicking on the checkbox, but it's impossible to check/uncheck them with the keyboard (I believe this is due to the fact that the checkbox itself never gets the focus).

我喜欢DLeh在这里提出的解决方案: https:// stackoverflow .com / a / 24327765/352826 ,但我想改进一下:我希望行为可以直接在基本视图模型(包含项列表的vm)上调用,而不是在基本视图模型上运行对项目的IsChecked属性进行操作。
我的问题是我不知道如何修改行为或如何在行为上设置绑定,以便行为可以访问项目的IsChecked属性。
因此,而不是以下内容:

I like the solution proposed by DLeh in here: https://stackoverflow.com/a/24327765/352826 but I would like an improvement: Instead of having the behaviour calling a command on the base view model (the vm which contains the list of items), I would like the behaviour to directly act on the IsChecked property of the item. My problem is that I don't know how to modify the behaviour or how to set up the binding on it, so that the behaviour can have access to the item's IsChecked property. So, instead of the following:

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

我会有这样的东西:

<DataGrid>
    <i:Interaction.Behaviors>
        <shared:ToggleSelectOnSpace ItemsIsSelectedProperty="{Binding IsChecked}" />
    </i:Interaction.Behaviors>
...
</DataGrid>

更新
我应该补充一点,我当前的实现使用项目控件中的PreviewKeyUp事件以及实现后的以下代码。这种方法的问题在于,我在文件后的许多代码中都有此代码,因此存在很多重复项。我的目标是将其替换为一种行为。

Update I should add that my current implementation uses the PreviewKeyUp event in the itemscontrol and the following code behind implementation. The problem with this approach is that I have this code in many code behind files, so there is a lot of duplication. My goal is to replace this by a behaviour.

private void TreeView_OnPreviewKeyUp(object sender, KeyEventArgs e)
{
   if (e.Key == Key.Space)
   {
        var tree = (TreeView) sender;
        var item = tree.SelectedItem as IsSelectedViewModelBase;
        if (item != null)
        {
            item.IsSelected = !item.IsSelected;
            e.Handled = true;
        }
   }
}

更新2
这是项目模板,当您按下带有选定项目的空格键时未选中该复选框。

Update 2 This is the item template and the checkbox is not checked when you press the space bar with the item selected.

<DataTemplate DataType="{x:Type viewModels:ItemViewModel}" >
    <StackPanel Orientation="Horizontal" >
      <CheckBox Focusable="False" IsChecked="{Binding IsSelected}" VerticalAlignment="Center" />
      <StackPanel Margin="2">
           <TextBlock Text="{Binding Username}" FontWeight="Bold" />
            <TextBlock Text="{Binding FullName}" />
      </StackPanel>
   </StackPanel>
 </DataTemplate>


推荐答案

不是对每个问题的回答 per se ,但以下内容将说明列表项中的复选框有可能获得键盘焦点。

Not an answer to the asked question per se, but the following will illustrate that it is possible for a check box within a list item to receive keyboard focus.

我使用以下命令创建了一个新的WPF项目:默认的Visual Studio模板。这将创建一个名为 MainWindow的窗口。这是XAML的内容以及该窗口的代码。

I created a new WPF project using the default Visual Studio template. This creates a single window called "MainWindow". Here's the contents of the XAML and code-behind of that window.

MainWindow.xaml.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;

namespace WpfApplication1
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            Thingies = new List<Thingy>
            {
                new Thingy { Name = "abc", IsChecked = false },
                new Thingy { Name = "def", IsChecked = true },
                new Thingy { Name = "ghi", IsChecked = false },
                new Thingy { Name = "jkl", IsChecked = true },
                new Thingy { Name = "mno", IsChecked = false },
            }.ToArray();

            DataContext = this;
        }

        public Thingy[] Thingies { get; private set; }

        public class Thingy : INotifyPropertyChanged
        {
            public string Name { get; set; }

            public bool IsChecked
            {
                get
                {
                    return _isChecked;
                }
                set
                {
                    if (_isChecked != value)
                    {
                        _isChecked = value;
                        if (PropertyChanged != null)
                        {
                            PropertyChanged(this,
                                new PropertyChangedEventArgs("IsChecked"));
                        }
                        Console.WriteLine(Name + " = " + _isChecked);
                    }
                }
            }
            bool _isChecked;

            public event PropertyChangedEventHandler PropertyChanged;
        }
    }
}

MainWindow.xaml

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <ListBox ItemsSource="{Binding Thingies}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <UniformGrid Rows="1" Width="400">
                    <TextBlock Text="{Binding Name}" />
                    <CheckBox IsChecked="{Binding IsChecked}" />
                </UniformGrid>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</Window>

这篇关于WPF行为以选中/取消选中列表项中的复选框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆