WPF DataGrid 选定项

问题描述 投票:0回答:3

我有一个 DataGrid,用户可以通过在最后一行输入数据来添加项目。我还有一个按钮可以删除当前选定的项目。但是,当选择最后一行(空,用于添加新项目)时,最后选定的项目将保留在 SelectedItem 中。因此,如果我打开窗口,选择最后一行,然后按删除按钮,它将删除第一行,因为默认情况下会选择第一行,并且选择最后一行不会更改 SelectedItem。有什么好的办法解决吗?

澄清一下: SelectedItem="{绑定X}"

当选择最后一行时,ViewModel 中的 X 不会改变(根本不调用 setter)。我不确定 SelectedItem 属性本身是否改变,但我假设它没有改变。

当我选择最后一行(红色边框)时也有一个例外,但是当我再次单击它开始输入数据时,红色边框消失了。不确定这两者是否相关。

c# wpf mvvm datagrid
3个回答
12
投票
运行以下示例,您就会明白为什么它不起作用。

XAML:

<Window x:Class="DataGridTest.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <DockPanel> <TextBlock DockPanel.Dock="Bottom" Text="{Binding SelectedItem, ElementName=dataGrid}"/> <TextBlock DockPanel.Dock="Bottom" Text="{Binding SelectedItem}"/> <DataGrid x:Name="dataGrid" ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}" CanUserAddRows="True" CanUserDeleteRows="True" AutoGenerateColumns="False"> <DataGrid.Columns> <DataGridTextColumn Header="First Name" Binding="{Binding FirstName}"/> <DataGridTextColumn Header="Last Name" Binding="{Binding FirstName}"/> </DataGrid.Columns> </DataGrid> </DockPanel> </Window>
后台代码:

namespace DataGridTest { using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Windows; public partial class MainWindow : Window, INotifyPropertyChanged { private readonly ICollection<Person> items; private Person selectedItem; public MainWindow() { InitializeComponent(); this.items = new ObservableCollection<Person>(); this.items.Add(new Person { FirstName = "Kent", LastName = "Boogaart" }); this.items.Add(new Person { FirstName = "Tempany", LastName = "Boogaart" }); this.DataContext = this; } public ICollection<Person> Items { get { return this.items; } } public Person SelectedItem { get { return this.selectedItem; } set { this.selectedItem = value; this.OnPropertyChanged("SelectedItem"); } } private void OnPropertyChanged(string propertyName) { var handler = this.PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(propertyName)); } } public event PropertyChangedEventHandler PropertyChanged; } public class Person { public string FirstName { get; set; } public string LastName { get; set; } public override string ToString() { return FirstName + " " + LastName; } } }
正如您在运行时所看到的,选择“新”行会导致哨兵值被设置为

DataGrid

中的所选项目。但是,WPF 无法将该哨兵项转换为 
Person
,因此 
SelectedItem
 绑定无法转换。

要解决此问题,您可以在绑定上放置一个转换器来检测哨兵并在检测到时返回

null

。这是一个这样做的转换器:

namespace DataGridTest { using System; using System.Windows.Data; public sealed class SentinelConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return value; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { if (value.Equals(CollectionView.NewItemPlaceholder)) { return null; } return value; } } }
如您所见,不幸的是,需要针对哨兵的 

ToString()

 值进行测试,因为它是内部类型。您也可以(或另外)检查 
GetType().Name
 是否为 
NamedObject


0
投票
没有代码很难说,但我会看看下面的内容。

确保每当删除一个项目并且它也是选定的项目时,将绑定到 ViewModel 中的属性的选定项目设置为 null。您需要确保绑定到属性的 SelectedItem 不是单向绑定的。


0
投票
听起来您忘记设置绑定模式,默认设置为 OneWay。这意味着视图中所做的任何更改都不会传播回视图模型。

并始终确保您拥有正确的数据上下文。

希望有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.