【问题标题】:WPF DataGrid horizontal cell selectionWPF DataGrid 水平单元格选择
【发布时间】:2014-11-01 15:45:36
【问题描述】:

我必须实现一个 WPF DataGrid,它可以只选择一行中的单元格。我怎么能做到这一点?我知道属性SelectionUnitSelectionMode,但是这两个属性的每个组合都没有成功。

XAML:

<DataGrid AutoGenerateColumns="True" CanUserAddRows="False" 
    ItemsSource="{Binding DPGridCR}" HeadersVisibility="None" SelectionUnit="Cell"
    SelectionMode="Extended" CanUserResizeRows="False" />

此时我只能选择多行中的多个单元格,或者只选择一个单元格或选择一整行。但我想在一行中选择多个单元格。

编辑:

<UserControl x:Class="DesignerPro.Controls.DZLeerformularGrid"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
    xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
    xmlns:ViewModel="clr-namespace:ViewModel;assembly=ViewModel"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="300"
    x:Name="DZLeerformularGridControl">

    <UserControl.Resources>
        <ViewModel:DZLeerformularGridViewModel x:Key="ViewModel" />
    </UserControl.Resources>

    <DataGrid AutoGenerateColumns="True" CanUserAddRows="False"
        ItemsSource="{Binding DPGridCR}" HeadersVisibility="None" SelectionUnit="Cell"
        SelectionMode="Extended" CanUserResizeRows="False">

        <i:Interaction.Triggers>
            <i:EventTrigger EventName="SelectedCellsChanged">
                <ei:CallMethodAction TargetObject="{Binding Mode=OneWay, Source={StaticResource ViewModel}}" MethodName="DataGrid_SelectedCellsChanged" />
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </DataGrid>
</UserControl>

使用EventTrigger,我尝试将SelectedCellsChanged-Event 绑定到我的ViewModel。您的解决方案在代码隐藏中运行良好,但在我的 ViewModel 中它不起作用:(

【问题讨论】:

  • 你是用CTRL键做多选吗?
  • 没有。我只是使用 WPF 默认 DataGrid 和几个 SelectionUnitSelectionMode 组合。
  • 我的意思是,在您设置 SelectionUnit="Cell" 和 SelectionMode="Extended" 之后,它应该可以工作。但是,为了进行多选,您需要在单击单元格时按住 CTRL。 (或者,您可以单击并拖动,如 Excel)如果您希望它以不同的方式操作,那么您需要编写一些自定义代码。
  • 您的解决方案无法以我喜欢的方式运行。我想防止用户选择多行中的单元格。用户只能选择一行中的单元格。例如:用户选择第 8 行中的第 3 到第 7 个单元格。这是允许的,但用户不应该能够选择第八行和第九行中的单元格!有没有聪明的方法来做到这一点?

标签: c# wpf datagrid


【解决方案1】:

尝试将此事件处理程序添加到代码隐藏中的 SelectedCellsChanged 事件:

private void DataGrid_SelectedCellsChanged(object sender, SelectedCellsChangedEventArgs e)
{
    var grid = sender as DataGrid;

    if (grid == null || !grid.SelectedCells.Any())
        return;

    var row = grid.Items.IndexOf(grid.SelectedCells[0].Item);

    try
    {
        // Disable the event handler to prevent a stack overflow.
        grid.SelectedCellsChanged -= DataGrid_SelectedCellsChanged;

        // If any of the selected cells don't match the row of the first selected cell,
        // undo the selection by removing the added cells and adding the removed cells.
        if (grid.SelectedCells.Any(c => grid.Items.IndexOf(c.Item) != row))
        {
            e.AddedCells.ToList().ForEach(c => grid.SelectedCells.Remove(c));
            e.RemovedCells.ToList().ForEach(c => grid.SelectedCells.Add(c));
        }
    }
    finally
    {
        // Don't forget to re-enable the event handler.
        grid.SelectedCellsChanged += DataGrid_SelectedCellsChanged;
    }
}

【讨论】:

  • 你的代码产生了一些 StackOverflowExceptions 因为这个 sn-p 创建了一个递归方法。禁用事件处理程序不会阻止堆栈溢出。我该如何解决这个问题?
  • 我试图实现一个锁定解锁解决方案,但这不是正确的方法:)
  • Remove(c)Add(c) 方法被调用时,SelectedCellsChanged 事件将被触发。因此,会创建递归并导致堆栈溢出。
  • 您的应用程序中发生了其他事情。我在一个基本的 wpf 应用程序中重新创建了它,并且没有堆栈溢出异常。只要您之前删除事件处理程序并在之后将其添加回来,它就不应该在 Remove() 和 Add() 期间被调用。您是否偶然添加了多个事件处理程序?
  • @PatrickVogt,你能发布更多代码吗?或者,如果您愿意,我可以将我创建的 wpf 应用程序发送给您以进行测试。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-29
  • 1970-01-01
  • 2013-06-08
  • 2017-08-07
  • 2015-04-12
  • 2017-07-14
相关资源
最近更新 更多