MVVM中WPF Datagrid的选定项为空

4

我正在尝试使用MVVM模式来处理数据网格。问题在于,每当我更改绑定到SelectedItem的VM属性为null时,视图不会“取消选择”当前选定的项。这是我的XAML绑定:

<DataGrid Grid.Column="0" Grid.Row="0" 
    ItemsSource="{Binding Path=Users}" 
    AutoGenerateColumns="False" 
    CanUserAddRows="False" 
    IsReadOnly="True" 
    SelectedItem="{Binding Path=SelectedUser, Mode=TwoWay}">

所选项绑定是从视图到VM的,因此在SelectedUser属性中我始终拥有所选对象。问题在于,在VM中我正在做一些事情,有时会将SelectedUser属性更改为null,因此我希望数据网格也能取消选择行。然而,它仍保持选中状态,如果我尝试单击相同的行,则属性不会更新。如果单击其他任何行,则属性会按预期更改。

有没有办法让数据网格在绑定的属性设置为null时取消选择?同时,我正在寻找一个MVVM解决方案,因为我不想编写代码后端。我可以通过编写代码后端来解决此问题,因此不要浪费时间提供此类解决方案:)

附:这是我的VM中的属性:

public RPLUser SelectedUser
        {
            get
            {                
                return selectedUser;
            }
            set
            {
                selectedUser = value;
                OnPropertyChanged("SelectedUser");
            }
        }

感谢提前帮忙!

1
当您在ViewModel中设置属性时,是否调用了OnPropertyChanged事件以通知View需要更新? - Purplegoldfish
是的,我正在编辑描述,也会提到这个。好问题,谢谢! - Florin Bombeanu
你能否发布一下你在VM中设置属性的代码以及属性本身的代码? - Purplegoldfish
在绑定中设置UpdateSourceTrigger=PropertyChanged可能会有帮助。 - Louis Kottmann
UpdateSourceTrigger没有解决问题。我尝试了它的所有可能值,包括PropertyChanged。还尝试了OnPropertyChanged("")。这也没有解决问题。确保我将属性设置为null,而不是私有字段,并确保它保持为null,没有其他组件将其设置回去。 - Florin Bombeanu
显示剩余2条评论
4个回答

6

你是否尝试在DataGrid的xaml属性中设置IsSynchronizedWithCurrentItem="True"?据我所知,这将允许你通过将SelectedUser设置为null来取消选择它。
目前我无法测试,但你也可以尝试在属性的setter中添加以下内容:

set
{
    selectedUser = value;
    OnPropertyChanged("SelectedUser");

    ICollectionView collectionView = CollectionViewSource.GetDefaultView(Users);
    collectionView.MoveCurrentTo(selectedUser);

}

要让ICollectionView发挥作用,您需要设置IsSynchronizedWithCurrentItem属性。

就像我说的,我现在无法测试。此外,属性的setter可能不是放置它的最佳位置。也许可以在本地创建一个PropertyChanged事件处理程序并将逻辑放置在那里。

如果有帮助,请告诉我,否则我会尝试运行一个简短的测试...


1
我曾经遇到过类似的问题,设置 IsSynchronizedWithCurrentItem="True" 对我有用!! - Satfactor

6

我建议在Visual Studio中检查输出窗口,看看是否有任何绑定失败。

当你选择某个东西时,你确定选择会更新到SelectedUser属性吗?

你是否在SelectedUser的setter中设置了断点,并查看在数据网格上选择某些内容时是否被触发了?

导致这种绑定断开的原因可能有很多...

  1. SelectedUser与单个Users的类型不同。
  2. SelectedUserUsers中的任何项都不匹配。
  3. 你是如何在哪里设置null的?

在我的情况下,以下代码完全正常运行...

    <tk:DataGrid MaxHeight="200" AutoGenerateColumns="False"
                 ItemsSource="{Binding}"
                 SelectedItem="{Binding MySelItem,
                                        ElementName=MyDGSampleWindow,
                                        Mode=TwoWay}"
                 IsReadOnly="True">
        <tk:DataGrid.Columns>
            <tk:DataGridTextColumn Header="Key"
                                   Binding="{Binding Key,
                                                     Mode=OneWay}"/>
            <tk:DataGridTextColumn Header="Value"
                                   Binding="{Binding Value,
                                                     Mode=OneWay}"/>
        </tk:DataGrid.Columns>
    </tk:DataGrid>

当我将MyDGSampleWindow.MySelItem设置为null时,数据网格会正确地取消选择。也许您需要提供更多关于如何实际将值设置为null的输入。


你说得对,我没有像应该的那样将属性设置为 null。我创建了一个新对象而不是将其设置为 null。通过先将属性设置为 null,然后再给它一个新对象来解决了这个问题。谢谢! - Florin Bombeanu

2

是的,可能需要添加XAML UpdateSourceTrigger来更新UI。

SelectedItem="{Binding SomeProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"

0

数据网格不会自动取消选择,因为 DataGridRowIsSelected 属性应设置为 False

您可以通过在 DataGrid 上设置样式来实现这一点,例如

    <Style x:Key="dataGridRowStyle"
           BasedOn="{StaticResource {x:Type WPFToolkit:DataGridRow}}"
           TargetType="{x:Type WPFToolkit:DataGridRow}">
        <Setter Property="IsSelected" Value="{Binding Path=IsSelected}" />
    </Style>  

IsSelected属性应该是对象的一部分,例如在您的情况下,RPLUser应该有一个名为Isselected的属性

然后,在将SelectedUser设置为null之前...只需执行SelectedUser.IsSelected=False

并且不要忘记将此样式附加到Datagrid中的DataGridRowStyle

我正在使用WPFToolkit,如果您的目标是.NET 4.0,则可以修改样式


你可以删除BasedOn BasedOn="{StaticResource {x:Type WPFToolkit:DataGridRow}}" - Ankesh
这似乎不是数据网格行未被取消选择的问题。我刚刚检查了一下,在基本设置中,当通过绑定将选定项设置为null时,数据网格会取消选择。 - WPF-it
@AngelWPF 我尝试过那种方法,但它没有起作用,所以我尝试了 Style 的方式。 - Ankesh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接