应用shift键盘修改器时,多行的复选框列

时间:2014-06-06 01:50:04

标签: wpf checkbox

我有一个包含“IsChecked”属性的视图模型。此属性绑定到DataGrid RowHeaderTemplate。

我希望能够按住shift + ctrl键盘修饰符以允许更新多个复选框值。

例如:如果您选中第一行中的复选框,请按住shift键,然后选中第5行中的复选框;然后,行1-5将有一个选中的复选框。

以下是行标题模板:

<DataGrid.RowHeaderTemplate>
    <DataTemplate>
        <CheckBox VerticalAlignment="Center"
                  VerticalContentAlignment="Center"
                  IsChecked="{Binding IsChecked}" />
    </DataTemplate>
</DataGrid.RowHeaderTemplate>

我尝试了几种捕获PreviewMouseLeftButtonDown和KeyPress事件的组合,但我不确定绑定属性是否可行。

2 个答案:

答案 0 :(得分:2)

我通过收听改变了IsChecked属性来提出解决方案。这可以满足我的需求。

    private void OnItemOnPropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs)
    {
            ItemViewModel newCheckedItem = sender as ItemViewModel;

            int newCheckedItemIndex = _items.IndexOf(newCheckedItem);

            if ((Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift)) && newCheckedItemIndex != _lastCheckedItemIndex)
            {
                int start = Math.Min(_lastCheckedItemIndex, newCheckedItemIndex);
                int end = Math.Max(_lastCheckedItemIndex, newCheckedItemIndex);

                int countToTake = end - start;

                var itemsToCheck = _items.Skip(start).Take(countToTake).ToList();

                foreach (ItemViewModel itemToCheck in itemsToCheck)
                {
                    // Unhook the property changed event so we don't enter this method again
                    itemToCheck.PropertyChanged -= OnItemOnPropertyChanged;

                    itemToCheck.IsChecked = true;
                    // Re-register the proeprty changed event so that if we're unchecked/re-checked, we can respond.
                    itemToCheck.PropertyChanged += OnItemOnPropertyChanged;
                }

                _lastCheckedItemIndex = -1;
            }
            else
            {
                _lastCheckedItemIndex = newCheckedItemIndex;
            }
        }
    }

答案 1 :(得分:0)

我遇到了同样的问题并且实现了与Michael G所呈现的类似的解决方案,但更直接。坦率地说,我无法使OnPropertyChanged事件正常工作,所以我开发了以下解决方案:

XAML:

        <DataGrid x:Name="_dg_DatasZones" Grid.Row="4" ItemsSource="{Binding}" LoadingRow="_dg_DatasZones_LoadingRow" Style="{StaticResource StandardGrid}" IsReadOnly="False"
                 SelectionMode="Single" >
          <DataGrid.Columns>
            <DataGridTemplateColumn CommonClasses:DataGridTemplateColumnStyleExtensions.Style="{StaticResource DataGridColumnIcon}">
              <DataGridTemplateColumn.HeaderTemplate>
                <DataTemplate>
                  <CheckBox Name="_CheckBox_SelectAllZone" Click="_CheckBox_SelectAllZone_Click" />
                </DataTemplate>
              </DataGridTemplateColumn.HeaderTemplate>
              <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                  <CheckBox IsChecked="{Binding IsChecked, UpdateSourceTrigger=PropertyChanged}" Checked="Zone_Checked" />
                </DataTemplate>
              </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            <DataGridTextColumn Foreground="Black" Width="50" Binding="{Binding Id}" ElementStyle="{StaticResource DataGridTextStyle}" Header="ID" HeaderTemplate="{StaticResource DataGridHeaderStyle}" IsReadOnly="True"  />
            <DataGridTextColumn Foreground="Black" MinWidth="100" Binding="{Binding Name}" ElementStyle="{StaticResource DataGridTextStyle}" Header="ZoneName" HeaderTemplate="{StaticResource DataGridHeaderStyle}" IsReadOnly="True" />

          </DataGrid.Columns>
        </DataGrid>

确保SelectionMode="Single"

C#代码:

    int _lastSelectedZoneIndex = -1;
    private void Zone_Checked(object sender, RoutedEventArgs e)
    {
        int index = _dg_DatasZones.SelectedIndex;
        if (  (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift))
                 &&  index != _lastSelectedZoneIndex && _lastSelectedZoneIndex >= 0)
        {
            CheckBox chbx = (CheckBox)sender;
            ListCollectionView view = _dg_DatasZones.DataContext as ListCollectionView;
            if (view == null)
                return;
            int startindex = Math.Min(_lastSelectedZoneIndex, index);
            int endindex = Math.Max(_lastSelectedZoneIndex, index);
            for (int i = startindex; i < endindex; i++)
                (view.GetItemAt(i) as TaskZoneData).IsChecked = (chbx.IsChecked == true);
        }
        else
        {
            _lastSelectedZoneIndex = index;
        }
        e.Handled = true;
    }

目前这只适用于选择辩护,但不能取消选择。 要选择,您应该检查开始行(复选框)然后按Shift并检查结束行 - 并且将选择整个diapason。