【问题标题】:WPF DataGrid SelectedItems not deselectingWPF DataGrid SelectedItems 未取消选择
【发布时间】:2014-03-27 20:59:03
【问题描述】:

我有一个 DataGrid,它的复选框绑定到项目的 IsSelected 属性。我正在尝试创建一个功能,允许您通过单击/拖动或单击/移位单击/ ctrl 单击其他行来选择网格中的行,然后右键单击>选择以设置我的项目的IsSelected 属性。复选框工作正常,正确地双向绑定到我的对象的 IsSelected 属性。

我已经达到了 90%,但是当我发送 DataGrid 的 SelectedItems 值时,它有时会发送已选择但不再选择的项目。

我找到了将 DataGrid 的 SelectedItems 发送到命令 here. 的代码

<DataGrid ItemsSource="{Binding MyItemList}">
    <DataGrid.ContextMenu>
        <ContextMenu>
            <MenuItem Header="Select" 
                      Command="{Binding Data.SelectCommand, Source={StaticResource BindingProxy}}" 
                      CommandParameter="{Binding PlacementTarget.SelectedItems,RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}}" />
        </ContextMenu>
    </DataGrid.ContextMenu>

来自我的视图模型的 C# 代码

private void Select(object selectedObjects)
{ 
    var items = (System.Collections.IList)selectedObjects;
    var collection = items.Cast<ItemType>().ToList();
    foreach (var item in collection)
        item.IsSelected = true;
} 

这是我复制它的方法。

场景 1:

  1. 控件加载,默认没有选择任何内容
  2. 我单击并拖动以选择所有选项
  3. 右键单击并选择Select
  4. 所有复选框现在都设置为选中状态,正如预期的那样
  5. 单击第一行,使其仅突出显示
  6. 右键选择Deselect
  7. 所有行的复选框都被取消选中(错误!)

场景 2:

  1. 控件加载,未选择任何内容
  2. 单击并拖动并选择前 2 个条目
  3. 右键单击并选择Select,复选框被选中
  4. 取消选中第 1 行和第 2 行
  5. 选择第 4 行和第 5 行
  6. 右键 > Select
  7. 现在检查第 1、2、4 和 5 行。 (错误)
  8. 取消选中 1、2、4 和 5
  9. 选择第 7 行和第 8 行
  10. 右键>Select
  11. 现在检查第 1、2、7 和 8 行。 (只是什么。)

我发现很难找到某种一致的理由来说明它的行为方式。我最好的猜测是,当我右键单击数据网格时,它不会充当正常的选择操作。任何人都知道为什么会发生这种情况,或者我如何强制网格正确选择我告诉它的行?

【问题讨论】:

    标签: wpf mvvm datagrid contextmenu


    【解决方案1】:

    我发现了问题。我正在使用包装类来启用对我的对象的选择:Selectable&lt;T&gt;。该对象包含一个IsSelected bool 和一个T Item。这个类的创建者重写了Equals 和GetHashCode 方法。这导致等于检查失败,因此 DataGrid 没有正确取消选择对象,因为它们被检测为不同的项目。

    如果您对对象进行正确的Equals 检查,上述问题中的代码应该可以正常工作。

    【讨论】:

      【解决方案2】:

      您几乎正在使用 MVVM,但是您的 ViewModel 在哪里?使用 ViewModel,这变得很容易。

      您有一个用于数据源的模型对象:AccountJobList 它是一个模型对象列表,我假设它是 AccountJob。

      所以也许 AccountJob 没有 IsChecked 属性,或者它有但没有实现 INotifyPropertyChanged。这就是我们创建 ViewModel 的原因。 因此,创建一个 AccountJobViewModel,它是 AccountJob 的包装器。此 AccountJobViewModel 必须实现 INotifyPropertyChanged。现在在我们的 ViewModel 中添加一个 IsChecked 属性。

      现在我们创建一个继承 ObservableCollection 的 AccountJobListViewModel(或者 List&lt;AccountJobViewModel&gt;,如果你不需要你的集合是可观察的)。 AccountJobListViewModel 接受一个 AccountJobList 和 foreach AccountJob 在列表中,它创建一个 AccountJobViewModel 并将其添加到集合中。

      您还需要 AccountJobListViewModel 或其父级中的 SelectedItems 属性。我假设您的 Select/Deselect 方法位于某种 ViewModel 中,所以它可能会放在那里。

      现在您只需在 ViewModel 上绑定 IsChecked。

      <CheckBox IsChecked="{Binding IsChecked}" />
      

      现在在您的代码中,您只需将每个选定的 AccountJobViewModel 的 IsChecked 属性设置为 true。

      private void Select(object selectedObjects)
      {
        foreach (AccountJobViewModel item in SelectedItems)
          item.IsChecked = true;
      }
      

      【讨论】:

      • 对不起,我不是很明确,我试图简洁。我有一个视图模型,上面的 C# 代码来自视图模型。该复选框已正确绑定到我的对象的 IsSelected 属性,这不是问题。
      • 我想做的是在我的视图模型中有另一个对象绑定到 DataGrid 的 SelectedItems 属性,然后我的 Select 方法可以简单地查看该列表,但它没有让我绑定到 SelectedItems 属性。这就是为什么我试图将 DataGrid 的 SelectedItems 作为参数发送到 Select 命令/方法
      • 我想我不小心点击了编辑你的答案而不是我的问题。对此感到抱歉。
      • 发现问题。我正在使用的对象中有一些奇怪的东西。不过,您让我找到了问题所在!
      猜你喜欢
      • 2010-12-07
      • 2011-10-14
      • 2011-09-17
      • 2020-12-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-31
      相关资源
      最近更新 更多