WPF DataGrid SelectedItems未取消选择

时间:2014-03-27 20:59:03

标签: wpf mvvm datagrid contextmenu

我有一个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>

来自我的viewmodel的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. 取消选中所有行的复选框(错误!)
  8. 情景2:

    1. 控制负载,未选择任何内容
    2. 点击并拖动并选择前两个条目
    3. 右键单击并选择Select,选中复选框
    4. 取消选中第1行和第2行
    5. 选择第4行和第5行
    6. 右键点击&gt; Select
    7. 现在检查第1,2,4和5行。 (错误的)
    8. 取消选中1,2,4和5
    9. 选择第7行和第8行
    10. 右键点击&gt; Select
    11. 现在检查第1,2,7和8行。 (正是如此。)
    12. 我发现很难想出某种一致的理由,就是这样做。我最好的猜测是,当我右键单击datagrid时,它不会作为正常的选择操作。任何人都有任何线索,为什么会发生这种情况,或者我如何强制网格正确选择我告诉它的行?

2 个答案:

答案 0 :(得分:1)

我发现了这个问题。我正在使用包装类来启用对象的选择:Selectable<T>。该对象包含IsSelected bool和T Item。此类的创建者已覆盖EqualsGetHashCode方法。这导致等于检查失败,因此DataGrid没有正确地取消选择对象,因为它们被检测为不同的项目。

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

答案 1 :(得分:0)

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

您有一个用于DataSource的Model对象:AccountJobList 它是Model对象的列表,我假设它是AccountJob。

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

现在我们创建一个AccountJobListViewModel,它继承ObservableCollection(或List<AccountJobViewModel>,如果你不需要你的集合是Observable)。 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;
}